From d0f2d8b42677b578e725cae999db7589fbe35e83 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 15:40:07 +0100 Subject: simplify code structure, reduce exposure of keystate struct --- src/mint/Makefile.am | 1 - src/mint/taler-mint-httpd.c | 1 - src/mint/taler-mint-httpd_db.c | 5 +- src/mint/taler-mint-httpd_db.h | 1 - src/mint/taler-mint-httpd_deposit.c | 1 - src/mint/taler-mint-httpd_keys.c | 74 ---------------------------- src/mint/taler-mint-httpd_keys.h | 51 -------------------- src/mint/taler-mint-httpd_keystate.c | 93 ++++++++++++++++++++++++++++++++++++ src/mint/taler-mint-httpd_keystate.h | 61 +++++++---------------- src/mint/taler-mint-httpd_refresh.c | 3 +- 10 files changed, 114 insertions(+), 177 deletions(-) delete mode 100644 src/mint/taler-mint-httpd_keys.c delete mode 100644 src/mint/taler-mint-httpd_keys.h diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index 19fba62f0..211d3c8fd 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -70,7 +70,6 @@ taler_mint_httpd_SOURCES = \ taler-mint-httpd_parsing.c taler-mint-httpd_parsing.h \ taler-mint-httpd_responses.c taler-mint-httpd_responses.h \ taler-mint-httpd_mhd.c \ - taler-mint-httpd_keys.c \ taler-mint-httpd_deposit.c \ taler-mint-httpd_withdraw.c \ taler-mint-httpd_refresh.c diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 416851066..7903d5c1c 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -31,7 +31,6 @@ #include "taler_util.h" #include "taler-mint-httpd_parsing.h" #include "taler-mint-httpd_mhd.h" -#include "taler-mint-httpd_keys.h" #include "taler-mint-httpd_deposit.h" #include "taler-mint-httpd_withdraw.h" #include "taler-mint-httpd_refresh.h" diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 63bca2ecc..5e57e152d 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -28,7 +28,6 @@ #include #include "taler-mint-httpd_db.h" #include "taler_signatures.h" -#include "taler-mint-httpd_keys.h" #include "taler-mint-httpd_responses.h" #include "mint_db.h" #include "taler_util.h" @@ -733,7 +732,7 @@ check_commitment (struct MHD_Connection *connection, GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n"); /* FIXME: return more specific error with original signature (#3712) */ - return (MHD_YES == + return (MHD_YES == TALER_MINT_reply_refresh_reveal_missmatch (connection, off, j, @@ -761,7 +760,7 @@ check_commitment (struct MHD_Connection *connection, &shared_secret)) { GNUNET_break (0); - return (MHD_YES == + return (MHD_YES == TALER_MINT_reply_internal_error (connection, "Decryption error")) ? GNUNET_NO : GNUNET_SYSERR; diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 84e65eef2..a40e3ae22 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -25,7 +25,6 @@ #include #include #include "taler_util.h" -#include "taler-mint-httpd_keys.h" #include "mint_db.h" diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 915a7389c..d37e69e40 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -36,7 +36,6 @@ #include "taler_signatures.h" #include "taler_util.h" #include "taler-mint-httpd_parsing.h" -#include "taler-mint-httpd_keys.h" #include "taler-mint-httpd_db.h" #include "taler-mint-httpd_deposit.h" #include "taler-mint-httpd_responses.h" diff --git a/src/mint/taler-mint-httpd_keys.c b/src/mint/taler-mint-httpd_keys.c deleted file mode 100644 index c22040d00..000000000 --- a/src/mint/taler-mint-httpd_keys.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ -/** - * @file taler-mint-httpd_keys.c - * @brief Handle /keys requests - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include "platform.h" -#include -#include -#include -#include "taler-mint-httpd_keys.h" -#include "taler-mint-httpd_keystate.h" - - -/** - * Function to call to handle the request by sending - * back static data from the @a rh. - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TALER_MINT_handler_keys (struct RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size) -{ - struct MintKeyState *key_state; - struct MHD_Response *response; - int ret; - - key_state = TALER_MINT_key_state_acquire (); - response = MHD_create_response_from_buffer (strlen (key_state->keys_json), - key_state->keys_json, - MHD_RESPMEM_MUST_COPY); - TALER_MINT_key_state_release (key_state); - if (NULL == response) - { - GNUNET_break (0); - return MHD_NO; - } - (void) MHD_add_response_header (response, - "Content-Type", - rh->mime_type); - ret = MHD_queue_response (connection, - rh->response_code, - response); - MHD_destroy_response (response); - return ret; -} - - -/* end of taler-mint-httpd_keys.c */ diff --git a/src/mint/taler-mint-httpd_keys.h b/src/mint/taler-mint-httpd_keys.h deleted file mode 100644 index bb1bc7216..000000000 --- a/src/mint/taler-mint-httpd_keys.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 GNUnet e.V. - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero 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 Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, If not, see -*/ -/** - * @file taler-mint-httpd_keys.h - * @brief Handle /keys requests and manage key state - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#ifndef TALER_MINT_HTTPD_KEYS_H -#define TALER_MINT_HTTPD_KEYS_H - -#include -#include -#include -#include "taler-mint-httpd.h" - - -/** - * Handle a "/keys" request - * - * @param rh context of the handler - * @param connection the MHD connection to handle - * @param[IN|OUT] connection_cls the connection's closure (can be updated) - * @param upload_data upload data - * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data - * @return MHD result code - */ -int -TALER_MINT_handler_keys (struct RequestHandler *rh, - struct MHD_Connection *connection, - void **connection_cls, - const char *upload_data, - size_t *upload_data_size); - - - -#endif diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 7edae9f7b..a26e30b90 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -29,6 +29,55 @@ #include "taler-mint-httpd_parsing.h" +/** + * Snapshot of the (coin and signing) + * keys (including private keys) of the mint. + */ +struct MintKeyState +{ + /** + * JSON array with denomination keys. + */ + json_t *denom_keys_array; + + /** + * JSON array with signing keys. + */ + json_t *sign_keys_array; + + /** + * Cached JSON text that the mint will send for + * a /keys request. + */ + char *keys_json; + + /** + * Mapping from denomination keys to denomination key issue struct. + */ + struct GNUNET_CONTAINER_MultiHashMap *denomkey_map; + + /** + * When did we initiate the key reloading? + */ + struct GNUNET_TIME_Absolute reload_time; + + /** + * When is the next key invalid and we have to reload? + */ + struct GNUNET_TIME_Absolute next_reload; + + /** + * Mint signing key that should be used currently. + */ + struct TALER_MINT_SignKeyIssuePriv current_sign_key_issue; + + /** + * Reference count. + */ + unsigned int refcnt; +}; + + /** * Mint key state. Never use directly, instead access via * #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release. @@ -486,4 +535,48 @@ TALER_MINT_keys_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, } +/** + * Function to call to handle the request by sending + * back static data from the @a rh. + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param[IN|OUT] connection_cls the connection's closure (can be updated) + * @param upload_data upload data + * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data + * @return MHD result code + */ +int +TALER_MINT_handler_keys (struct RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size) +{ + struct MintKeyState *key_state; + struct MHD_Response *response; + int ret; + + key_state = TALER_MINT_key_state_acquire (); + response = MHD_create_response_from_buffer (strlen (key_state->keys_json), + key_state->keys_json, + MHD_RESPMEM_MUST_COPY); + TALER_MINT_key_state_release (key_state); + if (NULL == response) + { + GNUNET_break (0); + return MHD_NO; + } + (void) MHD_add_response_header (response, + "Content-Type", + rh->mime_type); + ret = MHD_queue_response (connection, + rh->response_code, + response); + MHD_destroy_response (response); + return ret; +} + + + /* end of taler-mint-httpd_keystate.c */ diff --git a/src/mint/taler-mint-httpd_keystate.h b/src/mint/taler-mint-httpd_keystate.h index 4b700d1c1..d72538a13 100644 --- a/src/mint/taler-mint-httpd_keystate.h +++ b/src/mint/taler-mint-httpd_keystate.h @@ -35,49 +35,7 @@ * Snapshot of the (coin and signing) * keys (including private keys) of the mint. */ -struct MintKeyState -{ - /** - * When did we initiate the key reloading? - */ - struct GNUNET_TIME_Absolute reload_time; - - /** - * JSON array with denomination keys. - */ - json_t *denom_keys_array; - - /** - * JSON array with signing keys. - */ - json_t *sign_keys_array; - - /** - * Mapping from denomination keys to denomination key issue struct. - */ - struct GNUNET_CONTAINER_MultiHashMap *denomkey_map; - - /** - * When is the next key invalid and we have to reload? - */ - struct GNUNET_TIME_Absolute next_reload; - - /** - * Mint signing key that should be used currently. - */ - struct TALER_MINT_SignKeyIssuePriv current_sign_key_issue; - - /** - * Cached JSON text that the mint will send for - * a /keys request. - */ - char *keys_json; - - /** - * Reference count. - */ - unsigned int refcnt; -}; +struct MintKeyState; /** @@ -135,5 +93,22 @@ TALER_MINT_keys_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, struct GNUNET_CRYPTO_EddsaSignature *sig); +/** + * Handle a "/keys" request + * + * @param rh context of the handler + * @param connection the MHD connection to handle + * @param[IN|OUT] connection_cls the connection's closure (can be updated) + * @param upload_data upload data + * @param[IN|OUT] upload_data_size number of bytes (left) in @a upload_data + * @return MHD result code + */ +int +TALER_MINT_handler_keys (struct RequestHandler *rh, + struct MHD_Connection *connection, + void **connection_cls, + const char *upload_data, + size_t *upload_data_size); + #endif diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index a5d609ed8..c7bda5a79 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -28,7 +28,6 @@ #include "taler_signatures.h" #include "taler_util.h" #include "taler-mint-httpd_parsing.h" -#include "taler-mint-httpd_keys.h" #include "taler-mint-httpd_mhd.h" #include "taler-mint-httpd_refresh.h" #include "taler-mint-httpd_responses.h" @@ -125,8 +124,8 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, } // FIXME: badness, use proper way to set to zero... - key_state = TALER_MINT_key_state_acquire (); memset (&total_cost, 0, sizeof (struct TALER_Amount)); + key_state = TALER_MINT_key_state_acquire (); for (i=0;i Date: Sun, 15 Mar 2015 16:05:48 +0100 Subject: fix memory leaks on keystate reloading, simplify keystate reloading logic --- src/mint/taler-mint-httpd_keystate.c | 116 +++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 54 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index a26e30b90..a66802010 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -201,7 +201,7 @@ TALER_MINT_conf_duration_provide () /** - * Iterator for denomination keys. + * Iterator for (re)loading/initializing denomination keys. * * @param cls closure * @param dki the denomination key issue @@ -240,7 +240,8 @@ reload_keys_denom_iter (void *cls, res = GNUNET_CONTAINER_multihashmap_put (ctx->denomkey_map, &denom_key_hash, - GNUNET_memdup (dki, sizeof (struct TALER_MINT_DenomKeyIssuePriv)), + GNUNET_memdup (dki, + sizeof (struct TALER_MINT_DenomKeyIssuePriv)), GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); if (GNUNET_OK != res) GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -302,46 +303,24 @@ reload_keys_sign_iter (void *cls, /** - * Load the mint's key state from disk. + * Iterator for freeing denomination keys. * - * @return fresh key state (with reference count 1) + * @param cls closure with the `struct MintKeyState` + * @param key key for the denomination key + * @param alias coin alias + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to stop iteration with no error, + * #GNUNET_SYSERR to abort iteration with error! */ -static struct MintKeyState * -reload_keys () +static int +free_denom_key (void *cls, + const struct GNUNET_HashCode *key, + void *value) { - struct MintKeyState *key_state; - json_t *keys; - - key_state = GNUNET_new (struct MintKeyState); - key_state->refcnt = 1; - - key_state->next_reload = GNUNET_TIME_UNIT_FOREVER_ABS; - - key_state->denom_keys_array = json_array (); - GNUNET_assert (NULL != key_state->denom_keys_array); - - key_state->sign_keys_array = json_array (); - GNUNET_assert (NULL != key_state->sign_keys_array); - - key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, - GNUNET_NO); - GNUNET_assert (NULL != key_state->denomkey_map); + struct TALER_MINT_DenomKeyIssuePriv *dki = value; - key_state->reload_time = GNUNET_TIME_absolute_get (); - - TALER_MINT_denomkeys_iterate (mintdir, &reload_keys_denom_iter, key_state); - TALER_MINT_signkeys_iterate (mintdir, &reload_keys_sign_iter, key_state); - - keys = json_pack ("{s:o, s:o, s:o, s:o}", - "master_pub", TALER_JSON_from_data (&master_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)), - "signkeys", key_state->sign_keys_array, - "denoms", key_state->denom_keys_array, - "list_issue_date", TALER_JSON_from_abs (key_state->reload_time)); - - key_state->keys_json = json_dumps (keys, JSON_INDENT(2)); - - return key_state; + GNUNET_free (dki); + return GNUNET_OK; } @@ -358,6 +337,12 @@ TALER_MINT_key_state_release (struct MintKeyState *key_state) key_state->refcnt--; if (0 == key_state->refcnt) { + json_decref (key_state->denom_keys_array); + json_decref (key_state->sign_keys_array); + GNUNET_CONTAINER_multihashmap_iterate (key_state->denomkey_map, + &free_denom_key, + key_state); + GNUNET_CONTAINER_multihashmap_destroy (key_state->denomkey_map); GNUNET_free (key_state); } GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex)); @@ -376,19 +361,41 @@ TALER_MINT_key_state_acquire (void) { struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct MintKeyState *key_state; + json_t *keys; GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex)); - if (NULL == internal_key_state) + if (internal_key_state->next_reload.abs_value_us <= now.abs_value_us) { - internal_key_state = reload_keys (); + TALER_MINT_key_state_release (internal_key_state); + internal_key_state = NULL; } - else if (internal_key_state->next_reload.abs_value_us <= now.abs_value_us) + if (NULL == internal_key_state) { - GNUNET_assert (0 < internal_key_state->refcnt); - internal_key_state->refcnt--; - if (0 == internal_key_state->refcnt) - GNUNET_free (internal_key_state); - internal_key_state = reload_keys (); + key_state = GNUNET_new (struct MintKeyState); + key_state->next_reload = GNUNET_TIME_UNIT_FOREVER_ABS; + key_state->denom_keys_array = json_array (); + GNUNET_assert (NULL != key_state->denom_keys_array); + key_state->sign_keys_array = json_array (); + GNUNET_assert (NULL != key_state->sign_keys_array); + key_state->denomkey_map = GNUNET_CONTAINER_multihashmap_create (32, + GNUNET_NO); + key_state->reload_time = GNUNET_TIME_absolute_get (); + TALER_MINT_denomkeys_iterate (mintdir, + &reload_keys_denom_iter, + key_state); + TALER_MINT_signkeys_iterate (mintdir, + &reload_keys_sign_iter, + key_state); + keys = json_pack ("{s:o, s:o, s:o, s:o}", + "master_pub", + TALER_JSON_from_data (&master_pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)), + "signkeys", key_state->sign_keys_array, + "denoms", key_state->denom_keys_array, + "list_issue_date", TALER_JSON_from_abs (key_state->reload_time)); + key_state->keys_json = json_dumps (keys, + JSON_INDENT(2)); + internal_key_state = key_state; } key_state = internal_key_state; key_state->refcnt++; @@ -458,6 +465,9 @@ handle_signal (int signal_number) /** * Read signals from a pipe in a loop, and reload keys from disk if * SIGUSR1 is read from the pipe. + * + * @return #GNUNET_SYSERR on errors, otherwise does not return + * (FIXME: #3474) */ int TALER_MINT_key_reload_loop (void) @@ -487,16 +497,15 @@ TALER_MINT_key_reload_loop (void) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "(re-)loading keys\n"); - GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex)); if (NULL != internal_key_state) { GNUNET_assert (0 != internal_key_state->refcnt); - internal_key_state->refcnt -= 1; - if (0 == internal_key_state->refcnt) - GNUNET_free (internal_key_state); + TALER_MINT_key_state_release (internal_key_state); } - internal_key_state = reload_keys (); - GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex)); + /* This will re-initialize 'internal_key_state' with + an initial refcnt of 1 */ + (void) TALER_MINT_key_state_acquire (); + read_again: errno = 0; res = read (reload_pipe[0], &c, 1); @@ -513,8 +522,7 @@ read_again: /** - * Sign the message in @a purpose with the mint's signing - * key. + * Sign the message in @a purpose with the mint's signing key. * * @param purpose the message to sign * @param[OUT] sig signature over purpose using current signing key -- cgit v1.2.3 From 76dda24c111c7316da36eba050b18494c6c83c56 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 16:12:43 +0100 Subject: fixing another minor leak, improving comments --- src/mint/taler-mint-httpd_keystate.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index a66802010..d9eb81a9c 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -30,29 +30,39 @@ /** - * Snapshot of the (coin and signing) - * keys (including private keys) of the mint. + * Snapshot of the (coin and signing) keys (including private keys) of + * the mint. There can be multiple instances of this struct, as it is + * reference counted and only destroyed once the last user is done + * with it. The current instance is acquired using + * #TALER_MINT_key_state_acquire(). Using this function increases the + * reference count. The contents of this structure (except for the + * reference counter) should be considered READ-ONLY until it is + * ultimately destroyed (as there can be many concurrent users). */ struct MintKeyState { /** - * JSON array with denomination keys. + * JSON array with denomination keys. (Currently not really used + * after initialization.) */ json_t *denom_keys_array; /** - * JSON array with signing keys. + * JSON array with signing keys. (Currently not really used + * after initialization.) */ json_t *sign_keys_array; /** - * Cached JSON text that the mint will send for - * a /keys request. + * Cached JSON text that the mint will send for a "/keys" request. + * Includes our @e master_pub public key, the signing and + * denomination keys as well as the @e reload_time. */ char *keys_json; /** * Mapping from denomination keys to denomination key issue struct. + * Used to lookup the key by hash. */ struct GNUNET_CONTAINER_MultiHashMap *denomkey_map; @@ -62,7 +72,8 @@ struct MintKeyState struct GNUNET_TIME_Absolute reload_time; /** - * When is the next key invalid and we have to reload? + * When is the next key invalid and we have to reload? (We also + * reload on SIGUSR1.) */ struct GNUNET_TIME_Absolute next_reload; @@ -72,7 +83,7 @@ struct MintKeyState struct TALER_MINT_SignKeyIssuePriv current_sign_key_issue; /** - * Reference count. + * Reference count. The struct is released when the RC hits zero. */ unsigned int refcnt; }; @@ -80,7 +91,7 @@ struct MintKeyState /** * Mint key state. Never use directly, instead access via - * #TALER_MINT_key_state_acquire and #TALER_MINT_key_state_release. + * #TALER_MINT_key_state_acquire() and #TALER_MINT_key_state_release(). */ static struct MintKeyState *internal_key_state; @@ -343,6 +354,7 @@ TALER_MINT_key_state_release (struct MintKeyState *key_state) &free_denom_key, key_state); GNUNET_CONTAINER_multihashmap_destroy (key_state->denomkey_map); + GNUNET_free (key_state->keys_json); GNUNET_free (key_state); } GNUNET_assert (0 == pthread_mutex_unlock (&internal_key_state_mutex)); @@ -351,8 +363,8 @@ TALER_MINT_key_state_release (struct MintKeyState *key_state) /** * Acquire the key state of the mint. Updates keys if necessary. - * For every call to #TALER_MINT_key_state_acquire, a matching call - * to #TALER_MINT_key_state_release must be made. + * For every call to #TALER_MINT_key_state_acquire(), a matching call + * to #TALER_MINT_key_state_release() must be made. * * @return the key state */ @@ -499,8 +511,8 @@ TALER_MINT_key_reload_loop (void) "(re-)loading keys\n"); if (NULL != internal_key_state) { - GNUNET_assert (0 != internal_key_state->refcnt); TALER_MINT_key_state_release (internal_key_state); + internal_key_state = NULL; } /* This will re-initialize 'internal_key_state' with an initial refcnt of 1 */ -- cgit v1.2.3 From 53b189868edbc855240026c2a02fe6c4e53f9bb0 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 16:39:06 +0100 Subject: moving low-level JSON encoding logic to json.c --- src/include/taler_json_lib.h | 20 ++++++++++++++++ src/mint/taler-mint-httpd_keystate.c | 8 +------ src/mint/taler-mint-httpd_responses.c | 38 +++++++----------------------- src/util/json.c | 44 +++++++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index ffa440d56..1048b89f6 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -76,6 +76,26 @@ TALER_JSON_from_ecdsa_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpo const struct GNUNET_CRYPTO_EcdsaSignature *signature); +/** + * Convert RSA public key to JSON. + * + * @param pk public key to convert + * @return corresponding JSON encoding + */ +json_t * +TALER_JSON_from_rsa_public_key (struct GNUNET_CRYPTO_rsa_PublicKey *pk); + + +/** + * Convert RSA signature to JSON. + * + * @param sig signature to convert + * @return corresponding JSON encoding + */ +json_t * +TALER_JSON_from_rsa_signature (struct GNUNET_CRYPTO_rsa_Signature *sig); + + /** * Convert binary data to a JSON string * with the base32crockford encoding. diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index d9eb81a9c..abc746e7d 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -116,8 +116,6 @@ static int reload_pipe[2]; static json_t * denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) { - char *buf; - size_t buf_len; json_t *dk_json = json_object (); json_object_set_new (dk_json, @@ -134,13 +132,9 @@ denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) "stamp_expire_deposit", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend))); - buf_len = GNUNET_CRYPTO_rsa_public_key_encode (dki->denom_pub, - &buf); json_object_set_new (dk_json, "denom_pub", - TALER_JSON_from_data (buf, - buf_len)); - GNUNET_free (buf); + TALER_JSON_from_rsa_public_key (dki->denom_pub)); json_object_set_new (dk_json, "value", TALER_JSON_from_amount (TALER_amount_ntoh (dki->value))); diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index dc51dee4b..1a0a7c997 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -581,15 +581,9 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, const struct CollectableBlindcoin *collectable) { json_t *sig_json; - size_t sig_buf_size; - char *sig_buf; int ret; - sig_buf_size = GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, - &sig_buf); - sig_json = TALER_JSON_from_data (sig_buf, - sig_buf_size); - GNUNET_free (sig_buf); + sig_json = TALER_JSON_from_rsa_signature (collectable->sig); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -691,22 +685,14 @@ TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, int newcoin_index; json_t *root; json_t *list; - char *buf; - size_t buf_size; int ret; root = json_object (); list = json_array (); json_object_set_new (root, "ev_sigs", list); for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++) - { - buf_size = GNUNET_CRYPTO_rsa_signature_encode (sigs[newcoin_index], - &buf); json_array_append_new (list, - TALER_JSON_from_data (buf, - buf_size)); - GNUNET_free (buf); - } + TALER_JSON_from_rsa_signature (sigs[newcoin_index])); ret = TALER_MINT_reply_json (connection, root, MHD_HTTP_OK); @@ -772,26 +758,18 @@ TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, for (pos = ldl; NULL != pos; pos = pos->next) { json_t *obj; - char *buf; - size_t buf_len; obj = json_object (); json_object_set_new (obj, "link_enc", TALER_JSON_from_data (ldl->link_data_enc->coin_priv_enc, sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) + ldl->link_data_enc->blinding_key_enc_size)); - buf_len = GNUNET_CRYPTO_rsa_public_key_encode (ldl->denom_pub, - &buf); - json_object_set_new (obj, "denom_pub", - TALER_JSON_from_data (buf, - buf_len)); - GNUNET_free (buf); - buf_len = GNUNET_CRYPTO_rsa_signature_encode (ldl->ev_sig, - &buf); - json_object_set_new (obj, "ev_sig", - TALER_JSON_from_data (buf, - buf_len)); - GNUNET_free (buf); + json_object_set_new (obj, + "denom_pub", + TALER_JSON_from_rsa_public_key (ldl->denom_pub)); + json_object_set_new (obj, + "ev_sig", + TALER_JSON_from_rsa_signature (ldl->ev_sig)); json_array_append_new (list, obj); } diff --git a/src/util/json.c b/src/util/json.c index a9d6dc5cc..84fac4c98 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -150,6 +150,50 @@ TALER_JSON_from_ecdsa_sig (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpo } +/** + * Convert RSA public key to JSON. + * + * @param pk public key to convert + * @return corresponding JSON encoding + */ +json_t * +TALER_JSON_from_rsa_public_key (struct GNUNET_CRYPTO_rsa_PublicKey *pk) +{ + char *buf; + size_t buf_len; + json_t *ret; + + buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pk, + &buf); + ret = TALER_JSON_from_data (buf, + buf_len); + GNUNET_free (buf); + return ret; +} + + +/** + * Convert RSA signature to JSON. + * + * @param sig signature to convert + * @return corresponding JSON encoding + */ +json_t * +TALER_JSON_from_rsa_signature (struct GNUNET_CRYPTO_rsa_Signature *sig) +{ + char *buf; + size_t buf_len; + json_t *ret; + + buf_len = GNUNET_CRYPTO_rsa_signature_encode (sig, + &buf); + ret = TALER_JSON_from_data (buf, + buf_len); + GNUNET_free (buf); + return ret; +} + + /** * Convert binary data to a JSON string * with the base32crockford encoding. -- cgit v1.2.3 From 37a194c0bada3161bd75d765da00d6fb9de3d5f9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 16:44:53 +0100 Subject: simplify json construction code --- src/mint/mint_db.c | 3 +- src/mint/taler-mint-httpd_keystate.c | 82 ++++++++++++++--------------------- src/mint/taler-mint-httpd_responses.c | 4 +- 3 files changed, 38 insertions(+), 51 deletions(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 848f9e045..50904df39 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1049,7 +1049,8 @@ TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub, &denom_pub_enc); denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, &denom_sig_enc); + GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, + &denom_sig_enc); struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR (h_blind), TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size - 1), diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index abc746e7d..4be13a0bb 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -116,38 +116,27 @@ static int reload_pipe[2]; static json_t * denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) { - json_t *dk_json = json_object (); - - json_object_set_new (dk_json, - "master_sig", - TALER_JSON_from_data (&dki->signature, - sizeof (struct GNUNET_CRYPTO_EddsaSignature))); - json_object_set_new (dk_json, - "stamp_start", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->start))); - json_object_set_new (dk_json, - "stamp_expire_withdraw", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_withdraw))); - json_object_set_new (dk_json, - "stamp_expire_deposit", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend))); - - json_object_set_new (dk_json, - "denom_pub", - TALER_JSON_from_rsa_public_key (dki->denom_pub)); - json_object_set_new (dk_json, - "value", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->value))); - json_object_set_new (dk_json, - "fee_withdraw", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_withdraw))); - json_object_set_new (dk_json, - "fee_deposit", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_deposit))); - json_object_set_new (dk_json, - "fee_refresh", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_refresh))); - return dk_json; + return + json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", + "master_sig", + TALER_JSON_from_data (&dki->signature, + sizeof (struct GNUNET_CRYPTO_EddsaSignature)), + "stamp_start", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->start)), + "stamp_expire_withdraw", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_withdraw)), + "stamp_expire_deposit", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend)), + "denom_pub", + TALER_JSON_from_rsa_public_key (dki->denom_pub), + "value", + TALER_JSON_from_amount (TALER_amount_ntoh (dki->value)), + "fee_withdraw", + TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_withdraw)), + "fee_deposit", + TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_deposit)), + "fee_refresh", + TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_refresh))); } @@ -160,23 +149,18 @@ denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) static json_t * sign_key_issue_to_json (const struct TALER_MINT_SignKeyIssue *ski) { - json_t *sk_json = json_object (); - - json_object_set_new (sk_json, - "stamp_start", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->start))); - json_object_set_new (sk_json, - "stamp_expire", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire))); - json_object_set_new (sk_json, - "master_sig", - TALER_JSON_from_data (&ski->signature, - sizeof (struct GNUNET_CRYPTO_EddsaSignature))); - json_object_set_new (sk_json, - "key", - TALER_JSON_from_data (&ski->signkey_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); - return sk_json; + return + json_pack ("{s:o, s:o, s:o, s:o}", + "stamp_start", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->start)), + "stamp_expire", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire)), + "master_sig", + TALER_JSON_from_data (&ski->signature, + sizeof (struct GNUNET_CRYPTO_EddsaSignature)), + "key", + TALER_JSON_from_data (&ski->signkey_pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); } diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 1a0a7c997..3d827b118 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -689,7 +689,9 @@ TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, root = json_object (); list = json_array (); - json_object_set_new (root, "ev_sigs", list); + json_object_set_new (root, + "ev_sigs", + list); for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++) json_array_append_new (list, TALER_JSON_from_rsa_signature (sigs[newcoin_index])); -- cgit v1.2.3 From 92afa4e1db4fc9e4e29f26ca94bd22ccb0963cb5 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 16:52:19 +0100 Subject: adding filename argument to signkey iterator for better diagnostic messages --- src/mint/key_io.c | 8 +++- src/mint/key_io.h | 27 ++++++++---- src/mint/taler-mint-httpd_keystate.c | 82 +++++++++++++++++++++--------------- src/mint/taler-mint-keycheck.c | 5 ++- 4 files changed, 77 insertions(+), 45 deletions(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index 6b70e980a..e02e0f563 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -55,10 +55,14 @@ signkeys_iterate_dir_iter (void *cls, sizeof (struct TALER_MINT_SignKeyIssuePriv)); if (nread != sizeof (struct TALER_MINT_SignKeyIssuePriv)) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid signkey file: '%s'\n", filename); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid signkey file: '%s'\n", + filename); return GNUNET_OK; } - return skc->it (skc->it_cls, &issue); + return skc->it (skc->it_cls, + filename, + &issue); } diff --git a/src/mint/key_io.h b/src/mint/key_io.h index c9fd57625..bd7f95112 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -41,13 +41,21 @@ */ struct TALER_MINT_SignKeyIssuePriv { + /** + * FIXME. + */ struct GNUNET_CRYPTO_EddsaPrivateKey signkey_priv; + /** + * FIXME. + */ struct TALER_MINT_SignKeyIssue issue; }; - +/** + * FIXME. + */ struct TALER_MINT_DenomKeyIssuePriv { /** @@ -56,16 +64,18 @@ struct TALER_MINT_DenomKeyIssuePriv */ struct GNUNET_CRYPTO_rsa_PrivateKey *denom_priv; + /** + * FIXME. + */ struct TALER_MINT_DenomKeyIssue issue; }; - - /** * Iterator for sign keys. * * @param cls closure + * @param filename name of the file the key came from * @param ski the sign key issue * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, @@ -73,8 +83,10 @@ struct TALER_MINT_DenomKeyIssuePriv */ typedef int (*TALER_MINT_SignkeyIterator)(void *cls, + const char *filename, const struct TALER_MINT_SignKeyIssuePriv *ski); + /** * Iterator for denomination keys. * @@ -97,7 +109,8 @@ typedef int */ int TALER_MINT_signkeys_iterate (const char *mint_base_dir, - TALER_MINT_SignkeyIterator it, void *cls); + TALER_MINT_SignkeyIterator it, + void *it_cls); /** @@ -105,7 +118,8 @@ TALER_MINT_signkeys_iterate (const char *mint_base_dir, */ int TALER_MINT_denomkeys_iterate (const char *mint_base_dir, - TALER_MINT_DenomkeyIterator it, void *cls); + TALER_MINT_DenomkeyIterator it, + void *it_cls); /** @@ -132,7 +146,4 @@ TALER_MINT_read_denom_key (const char *filename, struct TALER_MINT_DenomKeyIssuePriv *dki); - - - #endif diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 4be13a0bb..d5872d96d 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -140,30 +140,6 @@ denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) } -/** - * Convert the public part of a sign key issue to a JSON object. - * - * @param ski the sign key issue - * @return a JSON object describing the sign key isue (public part) - */ -static json_t * -sign_key_issue_to_json (const struct TALER_MINT_SignKeyIssue *ski) -{ - return - json_pack ("{s:o, s:o, s:o, s:o}", - "stamp_start", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->start)), - "stamp_expire", - TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire)), - "master_sig", - TALER_JSON_from_data (&ski->signature, - sizeof (struct GNUNET_CRYPTO_EddsaSignature)), - "key", - TALER_JSON_from_data (&ski->signkey_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); -} - - /** * Get the relative time value that describes how * far in the future do we want to provide coin keys. @@ -207,6 +183,7 @@ reload_keys_denom_iter (void *cls, struct MintKeyState *ctx = cls; struct GNUNET_TIME_Absolute stamp_provide; struct GNUNET_HashCode denom_key_hash; + struct TALER_MINT_DenomKeyIssuePriv *d2; int res; stamp_provide = GNUNET_TIME_absolute_add (ctx->reload_time, @@ -214,39 +191,71 @@ reload_keys_denom_iter (void *cls, if (GNUNET_TIME_absolute_ntoh (dki->issue.expire_spend).abs_value_us < ctx->reload_time.abs_value_us) { - // this key is expired + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping expired denomination key `%s'\n", + alias); return GNUNET_OK; } if (GNUNET_TIME_absolute_ntoh (dki->issue.start).abs_value_us > stamp_provide.abs_value_us) { - // we are to early for this key + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping future denomination key `%s'\n", + alias); return GNUNET_OK; } GNUNET_CRYPTO_hash (&dki->issue.denom_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), &denom_key_hash); - + d2 = GNUNET_memdup (dki, + sizeof (struct TALER_MINT_DenomKeyIssuePriv)); res = GNUNET_CONTAINER_multihashmap_put (ctx->denomkey_map, &denom_key_hash, - GNUNET_memdup (dki, - sizeof (struct TALER_MINT_DenomKeyIssuePriv)), + d2, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); if (GNUNET_OK != res) + { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Duplicate denomination key\n"); - + "Duplicate denomination key `%s'\n", + alias); + GNUNET_free (d2); + return GNUNET_OK; + } json_array_append_new (ctx->denom_keys_array, denom_key_issue_to_json (&dki->issue)); - return GNUNET_OK; } +/** + * Convert the public part of a sign key issue to a JSON object. + * + * @param ski the sign key issue + * @return a JSON object describing the sign key isue (public part) + */ +static json_t * +sign_key_issue_to_json (const struct TALER_MINT_SignKeyIssue *ski) +{ + return + json_pack ("{s:o, s:o, s:o, s:o}", + "stamp_start", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->start)), + "stamp_expire", + TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (ski->expire)), + "master_sig", + TALER_JSON_from_data (&ski->signature, + sizeof (struct GNUNET_CRYPTO_EddsaSignature)), + "key", + TALER_JSON_from_data (&ski->signkey_pub, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); +} + + /** * Iterator for sign keys. * * @param cls closure + * @param filename name of the file the key came from * @param ski the sign key issue * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, @@ -254,6 +263,7 @@ reload_keys_denom_iter (void *cls, */ static int reload_keys_sign_iter (void *cls, + const char *filename, const struct TALER_MINT_SignKeyIssuePriv *ski) { struct MintKeyState *ctx = cls; @@ -264,13 +274,17 @@ reload_keys_sign_iter (void *cls, if (GNUNET_TIME_absolute_ntoh (ski->issue.expire).abs_value_us < ctx->reload_time.abs_value_us) { - // this key is expired + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping expired signing key `%s'\n", + filename); return GNUNET_OK; } if (GNUNET_TIME_absolute_ntoh (ski->issue.start).abs_value_us > stamp_provide.abs_value_us) { - // we are to early for this key + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping future signing key `%s'\n", + filename); return GNUNET_OK; } diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c index c934d08fa..b8f40c580 100644 --- a/src/mint/taler-mint-keycheck.c +++ b/src/mint/taler-mint-keycheck.c @@ -28,11 +28,14 @@ static char *mintdir; + static struct GNUNET_CONFIGURATION_Handle *kcfg; static int -signkeys_iter (void *cls, const struct TALER_MINT_SignKeyIssuePriv *ski) +signkeys_iter (void *cls, + const char *filename, + const struct TALER_MINT_SignKeyIssuePriv *ski) { struct GNUNET_TIME_Absolute start; -- cgit v1.2.3 From 51b9d209f5d73abcfb2fc580ba7acd8e2bde1e62 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 16:58:21 +0100 Subject: warn if no signing key was found, fix next_reload calculation --- src/mint/taler-mint-httpd_keystate.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index d5872d96d..159db9bed 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -288,16 +288,14 @@ reload_keys_sign_iter (void *cls, return GNUNET_OK; } - // the signkey is valid for now, check - // if it's more recent than the current one! + /* The signkey is valid at this time, check if it's more recent than + what we have so far! */ if (GNUNET_TIME_absolute_ntoh (ctx->current_sign_key_issue.issue.start).abs_value_us > GNUNET_TIME_absolute_ntoh (ski->issue.start).abs_value_us) + { + /* We keep the most recent one around */ ctx->current_sign_key_issue = *ski; - - - ctx->next_reload = GNUNET_TIME_absolute_min (ctx->next_reload, - GNUNET_TIME_absolute_ntoh (ski->issue.expire)); - + } json_array_append_new (ctx->sign_keys_array, sign_key_issue_to_json (&ski->issue)); @@ -376,7 +374,6 @@ TALER_MINT_key_state_acquire (void) if (NULL == internal_key_state) { key_state = GNUNET_new (struct MintKeyState); - key_state->next_reload = GNUNET_TIME_UNIT_FOREVER_ABS; key_state->denom_keys_array = json_array (); GNUNET_assert (NULL != key_state->denom_keys_array); key_state->sign_keys_array = json_array (); @@ -390,6 +387,11 @@ TALER_MINT_key_state_acquire (void) TALER_MINT_signkeys_iterate (mintdir, &reload_keys_sign_iter, key_state); + key_state->next_reload = GNUNET_TIME_absolute_ntoh (key_state->current_sign_key_issue.issue.expire); + if (0 == key_state->next_reload.abs_value_us) + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No valid signing key found!\n"); + keys = json_pack ("{s:o, s:o, s:o, s:o}", "master_pub", TALER_JSON_from_data (&master_pub, -- cgit v1.2.3 From a16c7ae39fd592edff7d65cd3e434cb269f9cb5d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:08:12 +0100 Subject: cleaner /keys set filtering logic --- src/mint/taler-mint-httpd_keystate.c | 39 +++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 159db9bed..b39ef3f8d 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -181,25 +181,27 @@ reload_keys_denom_iter (void *cls, const struct TALER_MINT_DenomKeyIssuePriv *dki) { struct MintKeyState *ctx = cls; - struct GNUNET_TIME_Absolute stamp_provide; + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Absolute horizon; struct GNUNET_HashCode denom_key_hash; struct TALER_MINT_DenomKeyIssuePriv *d2; int res; - stamp_provide = GNUNET_TIME_absolute_add (ctx->reload_time, - TALER_MINT_conf_duration_provide ()); - - if (GNUNET_TIME_absolute_ntoh (dki->issue.expire_spend).abs_value_us < ctx->reload_time.abs_value_us) + horizon = GNUNET_TIME_relative_to_absolute (TALER_MINT_conf_duration_provide ()); + if (GNUNET_TIME_absolute_ntoh (dki->issue.expire_spend).abs_value_us > + horizon.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Skipping expired denomination key `%s'\n", + "Skipping future denomination key `%s'\n", alias); return GNUNET_OK; } - if (GNUNET_TIME_absolute_ntoh (dki->issue.start).abs_value_us > stamp_provide.abs_value_us) + now = GNUNET_TIME_absolute_get (); + if (GNUNET_TIME_absolute_ntoh (dki->issue.expire_spend).abs_value_us < + now.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Skipping future denomination key `%s'\n", + "Skipping expired denomination key `%s'\n", alias); return GNUNET_OK; } @@ -267,30 +269,31 @@ reload_keys_sign_iter (void *cls, const struct TALER_MINT_SignKeyIssuePriv *ski) { struct MintKeyState *ctx = cls; - struct GNUNET_TIME_Absolute stamp_provide; - - stamp_provide = GNUNET_TIME_absolute_add (ctx->reload_time, - TALER_MINT_conf_duration_provide (cfg)); + struct GNUNET_TIME_Absolute now; + struct GNUNET_TIME_Absolute horizon; - if (GNUNET_TIME_absolute_ntoh (ski->issue.expire).abs_value_us < ctx->reload_time.abs_value_us) + horizon = GNUNET_TIME_relative_to_absolute (TALER_MINT_conf_duration_provide ()); + if (GNUNET_TIME_absolute_ntoh (ski->issue.start).abs_value_us > + horizon.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Skipping expired signing key `%s'\n", + "Skipping future signing key `%s'\n", filename); return GNUNET_OK; } - - if (GNUNET_TIME_absolute_ntoh (ski->issue.start).abs_value_us > stamp_provide.abs_value_us) + now = GNUNET_TIME_absolute_get (); + if (GNUNET_TIME_absolute_ntoh (ski->issue.expire).abs_value_us < + now.abs_value_us) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Skipping future signing key `%s'\n", + "Skipping expired signing key `%s'\n", filename); return GNUNET_OK; } /* The signkey is valid at this time, check if it's more recent than what we have so far! */ - if (GNUNET_TIME_absolute_ntoh (ctx->current_sign_key_issue.issue.start).abs_value_us > + if (GNUNET_TIME_absolute_ntoh (ctx->current_sign_key_issue.issue.start).abs_value_us < GNUNET_TIME_absolute_ntoh (ski->issue.start).abs_value_us) { /* We keep the most recent one around */ -- cgit v1.2.3 From c7d4216274f12314a06e8e79fa94fd5f9e33a70c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:10:15 +0100 Subject: use GNUNET_CRYPTO_rsa_public_key_hash instead of re-implementing it --- src/mint/taler-mint-httpd_keystate.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index b39ef3f8d..3463143c5 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -426,18 +426,12 @@ struct TALER_MINT_DenomKeyIssuePriv * TALER_MINT_get_denom_key (const struct MintKeyState *key_state, const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) { - struct GNUNET_HashCode hash; - char *buf; - size_t buf_len; - - buf_len = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, - &buf); - GNUNET_CRYPTO_hash (buf, - buf_len, - &hash); - GNUNET_free (buf); + struct GNUNET_HashCode hc; + + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub, + &hc); return GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map, - &hash); + &hc); } -- cgit v1.2.3 From 39f5ff83c63bcb4a61e49a9043d1daf202ad8240 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:13:19 +0100 Subject: minor beautifications --- src/mint/taler-mint-httpd_keystate.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 3463143c5..0e5f82d72 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 GNUnet e.V. + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -449,9 +449,11 @@ handle_signal (int signal_number) if (SIGUSR1 == signal_number) { - errno = 0; - res = write (reload_pipe[1], &c, 1); - if ((res < 0) && (EINTR != errno)) + res = write (reload_pipe[1], + &c, + 1); + if ( (res < 0) && + (EINTR != errno) ) { GNUNET_break (0); return; @@ -476,6 +478,7 @@ int TALER_MINT_key_reload_loop (void) { struct sigaction act; + struct sigaction rec; if (0 != pipe (reload_pipe)) { @@ -483,16 +486,20 @@ TALER_MINT_key_reload_loop (void) "Failed to create pipe.\n"); return GNUNET_SYSERR; } - memset (&act, 0, sizeof (struct sigaction)); + memset (&act, + 0, + sizeof (struct sigaction)); act.sa_handler = &handle_signal; - - if (0 != sigaction (SIGUSR1, &act, NULL)) + if (0 != sigaction (SIGUSR1, + &act, + &rec)) { fprintf (stderr, "Failed to set signal handler.\n"); return GNUNET_SYSERR; } + /* FIXME: allow for 'clean' termination or restart (#3474) */ while (1) { char c; @@ -520,6 +527,15 @@ read_again: if (EINTR == errno) goto read_again; } + + if (0 != sigaction (SIGUSR1, + &rec, + &act)) + { + fprintf (stderr, + "Failed to restore signal handler.\n"); + return GNUNET_SYSERR; + } return GNUNET_OK; } @@ -589,5 +605,4 @@ TALER_MINT_handler_keys (struct RequestHandler *rh, } - /* end of taler-mint-httpd_keystate.c */ -- cgit v1.2.3 From 1479d2ce0628adb354480a8ae3238256b890d62f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:14:11 +0100 Subject: minor beautifications --- src/mint/taler-mint-httpd_keystate.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 0e5f82d72..b1c51c284 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -479,6 +479,7 @@ TALER_MINT_key_reload_loop (void) { struct sigaction act; struct sigaction rec; + int ret; if (0 != pipe (reload_pipe)) { @@ -499,6 +500,7 @@ TALER_MINT_key_reload_loop (void) return GNUNET_SYSERR; } + ret = GNUNET_OK; /* FIXME: allow for 'clean' termination or restart (#3474) */ while (1) { @@ -518,11 +520,14 @@ TALER_MINT_key_reload_loop (void) read_again: errno = 0; - res = read (reload_pipe[0], &c, 1); + res = read (reload_pipe[0], + &c, + 1); if ((res < 0) && (EINTR != errno)) { GNUNET_break (0); - return GNUNET_SYSERR; + ret = GNUNET_SYSERR; + break; } if (EINTR == errno) goto read_again; @@ -536,7 +541,7 @@ read_again: "Failed to restore signal handler.\n"); return GNUNET_SYSERR; } - return GNUNET_OK; + return ret; } -- cgit v1.2.3 From 7e6b7e6b539dbbf042f51530db23f316688352a6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:17:29 +0100 Subject: remove dead #includes --- src/mint/key_io.h | 4 +--- src/mint/taler-mint-httpd_keystate.c | 4 ---- src/mint/taler-mint-httpd_keystate.h | 12 ++++++------ 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/mint/key_io.h b/src/mint/key_io.h index bd7f95112..a9acc3fe3 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, If not, see */ /** - * @file key_io.h + * @file mint/key_io.h * @brief IO operations for the mint's private keys * @author Florian Dold * @author Benedikt Mueller @@ -27,8 +27,6 @@ #define KEY_IO_H #include -#include -#include "taler_util.h" #include "taler_signatures.h" #define DIR_SIGNKEYS "signkeys" diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index b1c51c284..405b4bec6 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -21,12 +21,8 @@ * @author Christian Grothoff */ #include "platform.h" -#include #include -#include "taler_signatures.h" #include "taler-mint-httpd_keystate.h" -#include "taler_util.h" -#include "taler-mint-httpd_parsing.h" /** diff --git a/src/mint/taler-mint-httpd_keystate.h b/src/mint/taler-mint-httpd_keystate.h index d72538a13..4bb468ea0 100644 --- a/src/mint/taler-mint-httpd_keystate.h +++ b/src/mint/taler-mint-httpd_keystate.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 GNUnet e.V. + Copyright (C) 2014, 2015 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, If not, see */ /** - * @file taler-mint-httpd_keystate.h + * @file mint/taler-mint-httpd_keystate.h * @brief management of our private signing keys (denomination keys) * @author Florian Dold * @author Benedikt Mueller @@ -23,10 +23,8 @@ #ifndef TALER_MINT_HTTPD_KEYSTATE_H #define TALER_MINT_HTTPD_KEYSTATE_H - #include #include -#include #include "taler-mint-httpd.h" #include "key_io.h" @@ -59,7 +57,8 @@ TALER_MINT_key_state_release (struct MintKeyState *key_state); /** - * Look up the issue for a denom public key. + * Look up the issue for a denom public key. Note that the result + * is only valid while the @a key_state is not released! * * @param key state to look in * @param denom_pub denomination public key @@ -75,7 +74,8 @@ TALER_MINT_get_denom_key (const struct MintKeyState *key_state, * Read signals from a pipe in a loop, and reload keys from disk if * SIGUSR1 is read from the pipe. * - * @return #GNUNET_OK if we terminated normally, #GNUNET_SYSERR on error + * @return #GNUNET_OK if we terminated normally, + * #GNUNET_SYSERR on error */ int TALER_MINT_key_reload_loop (void); -- cgit v1.2.3 From 64d2ca9e5c1cf9c890c6518a32131aa92daad193 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:21:18 +0100 Subject: fixing minor memory leak --- src/mint/key_io.c | 63 ++++++++++++++++++++++++++++++++----------------------- src/mint/key_io.h | 2 +- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index e02e0f563..1954c629f 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -15,7 +15,7 @@ */ /** - * @file key_io.c + * @file mint/key_io.c * @brief I/O operations for the Mint's private keys * @author Florian Dold * @author Benedikt Mueller @@ -33,14 +33,6 @@ struct SignkeysIterateContext }; -struct DenomkeysIterateContext -{ - const char *alias; - TALER_MINT_DenomkeyIterator it; - void *it_cls; -}; - - static int signkeys_iterate_dir_iter (void *cls, const char *filename) @@ -56,7 +48,7 @@ signkeys_iterate_dir_iter (void *cls, if (nread != sizeof (struct TALER_MINT_SignKeyIssuePriv)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid signkey file: '%s'\n", + "Invalid signkey file: `%s'\n", filename); return GNUNET_OK; } @@ -68,19 +60,23 @@ signkeys_iterate_dir_iter (void *cls, int TALER_MINT_signkeys_iterate (const char *mint_base_dir, - TALER_MINT_SignkeyIterator it, void *cls) + TALER_MINT_SignkeyIterator it, + void *it_cls) { char *signkey_dir; - size_t len; struct SignkeysIterateContext skc; + int ret; - len = GNUNET_asprintf (&signkey_dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS), mint_base_dir); - GNUNET_assert (len > 0); - + GNUNET_asprintf (&signkey_dir, + "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, + mint_base_dir); skc.it = it; - skc.it_cls = cls; - - return GNUNET_DISK_directory_scan (signkey_dir, &signkeys_iterate_dir_iter, &skc); + skc.it_cls = it_cls; + ret = GNUNET_DISK_directory_scan (signkey_dir, + &signkeys_iterate_dir_iter, + &skc); + GNUNET_free (signkey_dir); + return ret; } @@ -104,7 +100,8 @@ TALER_MINT_read_denom_key (const char *filename, ret = GNUNET_SYSERR; data = NULL; offset = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.signature); + - offsetof (struct TALER_MINT_DenomKeyIssuePriv, + issue.signature); if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, @@ -161,16 +158,18 @@ TALER_MINT_write_denom_key (const char *filename, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) goto cleanup; wsize = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.signature); + - offsetof (struct TALER_MINT_DenomKeyIssuePriv, + issue.signature); if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh, &dki->issue.signature, wsize))) goto cleanup; if (wrote != wsize) goto cleanup; - if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh, - priv_enc, - priv_enc_size))) + if (GNUNET_SYSERR == + (wrote = GNUNET_DISK_file_write (fh, + priv_enc, + priv_enc_size))) goto cleanup; if (wrote != priv_enc_size) goto cleanup; @@ -183,6 +182,14 @@ TALER_MINT_write_denom_key (const char *filename, } +struct DenomkeysIterateContext +{ + const char *alias; + TALER_MINT_DenomkeyIterator it; + void *it_cls; +}; + + static int denomkeys_iterate_keydir_iter (void *cls, const char *filename) @@ -191,7 +198,9 @@ denomkeys_iterate_keydir_iter (void *cls, struct DenomkeysIterateContext *dic = cls; struct TALER_MINT_DenomKeyIssuePriv issue; - if (GNUNET_OK != TALER_MINT_read_denom_key (filename, &issue)) + if (GNUNET_OK != + TALER_MINT_read_denom_key (filename, + &issue)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Invalid denomkey file: '%s'\n", @@ -211,7 +220,9 @@ denomkeys_iterate_topdir_iter (void *cls, dic->alias = GNUNET_STRINGS_get_short_name (filename); // FIXME: differentiate between error case and normal iteration abortion - if (0 > GNUNET_DISK_directory_scan (filename, &denomkeys_iterate_keydir_iter, dic)) + if (0 > GNUNET_DISK_directory_scan (filename, + &denomkeys_iterate_keydir_iter, + dic)) return GNUNET_SYSERR; return GNUNET_OK; } diff --git a/src/mint/key_io.h b/src/mint/key_io.h index a9acc3fe3..85c0166da 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 -- cgit v1.2.3 From ee2180b144eea0b73fd615101ffb3d315d48a2c8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:21:38 +0100 Subject: fixing minor memory leak --- src/mint/key_io.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index 1954c629f..ee9bc1332 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -37,7 +37,6 @@ static int signkeys_iterate_dir_iter (void *cls, const char *filename) { - struct SignkeysIterateContext *skc = cls; ssize_t nread; struct TALER_MINT_SignKeyIssuePriv issue; -- cgit v1.2.3 From ca8612b6db0b40c801ab8cb0a6fdf80af90c657e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 17:39:44 +0100 Subject: documenting --- src/mint/key_io.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++------ src/mint/key_io.h | 18 +++++++++++++++ 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index ee9bc1332..928d51db3 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -21,18 +21,39 @@ * @author Benedikt Mueller * @author Sree Harsha Totakura * @author Christian Grothoff + * + * TODO: + * - document better + * - revisit IO with respect to variable-size RSA keys! */ #include "platform.h" #include "key_io.h" - +/** + * + */ struct SignkeysIterateContext { + + /** + * + */ TALER_MINT_SignkeyIterator it; + + /** + * + */ void *it_cls; }; +/** + * + * + * @param cls + * @param filename + * @return + */ static int signkeys_iterate_dir_iter (void *cls, const char *filename) @@ -181,19 +202,40 @@ TALER_MINT_write_denom_key (const char *filename, } +/** + * + */ struct DenomkeysIterateContext { + + /** + * + */ const char *alias; + + /** + * + */ TALER_MINT_DenomkeyIterator it; + + /** + * + */ void *it_cls; }; +/** + * + * + * @param cls + * @param filename + * @return + */ static int denomkeys_iterate_keydir_iter (void *cls, const char *filename) { - struct DenomkeysIterateContext *dic = cls; struct TALER_MINT_DenomKeyIssuePriv issue; @@ -206,10 +248,19 @@ denomkeys_iterate_keydir_iter (void *cls, filename); return GNUNET_OK; } - return dic->it (dic->it_cls, dic->alias, &issue); + return dic->it (dic->it_cls, + dic->alias, + &issue); } +/** + * + * + * @param cls + * @param filename + * @return + */ static int denomkeys_iterate_topdir_iter (void *cls, const char *filename) @@ -229,7 +280,8 @@ denomkeys_iterate_topdir_iter (void *cls, int TALER_MINT_denomkeys_iterate (const char *mint_base_dir, - TALER_MINT_DenomkeyIterator it, void *cls) + TALER_MINT_DenomkeyIterator it, + void *it_cls) { char *dir; size_t len; @@ -241,7 +293,7 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, GNUNET_assert (len > 0); dic.it = it; - dic.it_cls = cls; + dic.it_cls = it_cls; // scan over alias dirs return GNUNET_DISK_directory_scan (dir, @@ -250,5 +302,4 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, } - -/* end of mint_common.c */ +/* end of key_io.c */ diff --git a/src/mint/key_io.h b/src/mint/key_io.h index 85c0166da..ae7f183e4 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -29,9 +29,17 @@ #include #include "taler_signatures.h" +/** + * + */ #define DIR_SIGNKEYS "signkeys" + +/** + * + */ #define DIR_DENOMKEYS "denomkeys" + /** * On disk format used for a mint signing key. * Includes the private key followed by the signed @@ -104,6 +112,11 @@ typedef int /** * FIXME + * + * @param mint_base_dir + * @param it + * @param it_cls closure for @a it + * @return */ int TALER_MINT_signkeys_iterate (const char *mint_base_dir, @@ -113,6 +126,11 @@ TALER_MINT_signkeys_iterate (const char *mint_base_dir, /** * FIXME + * + * @param mint_base_dir + * @param it + * @param it_cls closure for @a it + * @return */ int TALER_MINT_denomkeys_iterate (const char *mint_base_dir, -- cgit v1.2.3 From af79e61f4deee64c9fbec443f37b8bcada8e5cd6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:03:57 +0100 Subject: fixing minor memory leak, improving documentation --- src/mint/key_io.c | 104 ++++++++++++++++++++++++++++++++++++------------------ src/mint/key_io.h | 69 +++++++++++++++++++++--------------- 2 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index 928d51db3..ad06da62d 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -13,7 +13,6 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file mint/key_io.c * @brief I/O operations for the Mint's private keys @@ -23,36 +22,40 @@ * @author Christian Grothoff * * TODO: - * - document better * - revisit IO with respect to variable-size RSA keys! */ #include "platform.h" #include "key_io.h" + /** - * + * Closure for the #signkeys_iterate_dir_iter(). */ struct SignkeysIterateContext { /** - * + * Function to call on each signing key. */ TALER_MINT_SignkeyIterator it; /** - * + * Closure for @e it. */ void *it_cls; }; /** + * Function called on each file in the directory with + * our signing keys. Parses the file and calls the + * iterator from @a cls. * - * - * @param cls - * @param filename - * @return + * @param cls the `struct SignkeysIterateContext *` + * @param filename name of the file to parse + * @return #GNUNET_OK to continue, + * #GNUNET_NO to stop iteration without error, + * #GNUNET_SYSERR to stop iteration with error */ static int signkeys_iterate_dir_iter (void *cls, @@ -78,6 +81,18 @@ signkeys_iterate_dir_iter (void *cls, } +/** + * Call @a it for each signing key found in the @a mint_base_dir. + * + * @param mint_base_dir base directory for the mint, + * the signing keys must be in the #DIR_SIGNKEYS + * subdirectory + * @param it function to call on each signing key + * @param it_cls closure for @a it + * @return number of files found (may not match + * number of keys given to @a it as malformed + * files are simply skipped), -1 on error + */ int TALER_MINT_signkeys_iterate (const char *mint_base_dir, TALER_MINT_SignkeyIterator it, @@ -101,10 +116,10 @@ TALER_MINT_signkeys_iterate (const char *mint_base_dir, /** - * Import a denomination key from the given file + * Import a denomination key from the given file. * * @param filename the file to import the key from - * @param dki pointer to return the imported denomination key + * @param[OUT] dki set to the imported denomination key * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ int @@ -203,34 +218,40 @@ TALER_MINT_write_denom_key (const char *filename, /** - * + * Closure for #denomkeys_iterate_keydir_iter() and + * #denomkeys_iterate_topdir_iter(). */ struct DenomkeysIterateContext { /** - * + * Set to the name of the directory below the top-level directory + * during the call to #denomkeys_iterate_keydir_iter(). */ const char *alias; /** - * + * Function to call on each denomination key. */ TALER_MINT_DenomkeyIterator it; /** - * + * Closure for @e it. */ void *it_cls; }; /** + * Decode the denomination key in the given file @a filename and call + * the callback in @a cls with the information. * - * - * @param cls - * @param filename - * @return + * @param cls the `struct DenomkeysIterateContext *` + * @param filename name of a file that should contain + * a denomination key + * @return #GNUNET_OK to continue to iterate + * #GNUNET_NO to abort iteration with success + * #GNUNET_SYSERR to abort iteration with failure */ static int denomkeys_iterate_keydir_iter (void *cls, @@ -255,11 +276,14 @@ denomkeys_iterate_keydir_iter (void *cls, /** + * Function called on each subdirectory in the #DIR_DENOMKEYS. Will + * call the #denomkeys_iterate_keydir_iter() on each file in the + * subdirectory. * - * - * @param cls - * @param filename - * @return + * @param cls the `struct DenomkeysIterateContext *` + * @param filename name of the subdirectory to scan + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR if we need to abort */ static int denomkeys_iterate_topdir_iter (void *cls, @@ -268,8 +292,6 @@ denomkeys_iterate_topdir_iter (void *cls, struct DenomkeysIterateContext *dic = cls; dic->alias = GNUNET_STRINGS_get_short_name (filename); - - // FIXME: differentiate between error case and normal iteration abortion if (0 > GNUNET_DISK_directory_scan (filename, &denomkeys_iterate_keydir_iter, dic)) @@ -278,6 +300,19 @@ denomkeys_iterate_topdir_iter (void *cls, } +/** + * Call @a it for each denomination key found in the @a mint_base_dir. + * + * @param mint_base_dir base directory for the mint, + * the signing keys must be in the #DIR_DENOMKEYS + * subdirectory + * @param it function to call on each denomination key found + * @param it_cls closure for @a it + * @return -1 on error, 0 if no files were found, otherwise + * a positive number (however, even with a positive + * number it is possible that @a it was never called + * as maybe none of the files were well-formed) + */ int TALER_MINT_denomkeys_iterate (const char *mint_base_dir, TALER_MINT_DenomkeyIterator it, @@ -286,19 +321,18 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, char *dir; size_t len; struct DenomkeysIterateContext dic; + int ret; - len = GNUNET_asprintf (&dir, - "%s" DIR_SEPARATOR_STR DIR_DENOMKEYS, - mint_base_dir); - GNUNET_assert (len > 0); - + GNUNET_asprintf (&dir, + "%s" DIR_SEPARATOR_STR DIR_DENOMKEYS, + mint_base_dir); dic.it = it; dic.it_cls = it_cls; - - // scan over alias dirs - return GNUNET_DISK_directory_scan (dir, - &denomkeys_iterate_topdir_iter, - &dic); + ret = GNUNET_DISK_directory_scan (dir, + &denomkeys_iterate_topdir_iter, + &dic); + GNUNET_free (dir); + return ret; } diff --git a/src/mint/key_io.h b/src/mint/key_io.h index ae7f183e4..aa59213c3 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -19,9 +19,6 @@ * @author Florian Dold * @author Benedikt Mueller * @author Christian Grothoff - * - * TODO: - * - document better */ #ifndef KEY_IO_H #define KEY_IO_H @@ -30,59 +27,64 @@ #include "taler_signatures.h" /** - * + * Subdirectroy under the mint's base directory which contains + * the mint's signing keys. */ #define DIR_SIGNKEYS "signkeys" /** - * + * Subdirectory under the mint's base directory which contains + * the mint's denomination keys. */ #define DIR_DENOMKEYS "denomkeys" /** - * On disk format used for a mint signing key. - * Includes the private key followed by the signed - * issue message. + * On disk format used for a mint signing key. Signing keys are used + * by the mint to affirm its messages, but not to create coins. + * Includes the private key followed by the public information about + * the signing key. */ struct TALER_MINT_SignKeyIssuePriv { /** - * FIXME. + * Private key part of the mint's signing key. */ struct GNUNET_CRYPTO_EddsaPrivateKey signkey_priv; /** - * FIXME. + * Public information about a mint signing key. */ struct TALER_MINT_SignKeyIssue issue; }; /** - * FIXME. + * All information about a denomination key (which is used to + * sign coins into existence). */ struct TALER_MINT_DenomKeyIssuePriv { /** - * The private key of the denomination. Will be NULL if the private key is - * not available. + * The private key of the denomination. Will be NULL if the private + * key is not available (this is the case after the key has expired + * for signing coins, but is still valid for depositing coins). */ struct GNUNET_CRYPTO_rsa_PrivateKey *denom_priv; /** - * FIXME. + * Public information about a denomination key. */ struct TALER_MINT_DenomKeyIssue issue; }; /** - * Iterator for sign keys. + * Iterator over signing keys. * * @param cls closure * @param filename name of the file the key came from - * @param ski the sign key issue + * @param ski the sign key * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, * #GNUNET_SYSERR to abort iteration with error! @@ -94,10 +96,10 @@ typedef int /** - * Iterator for denomination keys. + * Iterator over denomination keys. * * @param cls closure - * @param dki the denomination key issue + * @param dki the denomination key * @param alias coin alias * @return #GNUNET_OK to continue to iterate, * #GNUNET_NO to stop iteration with no error, @@ -111,12 +113,16 @@ typedef int /** - * FIXME + * Call @a it for each signing key found in the @a mint_base_dir. * - * @param mint_base_dir - * @param it + * @param mint_base_dir base directory for the mint, + * the signing keys must be in the #DIR_SIGNKEYS + * subdirectory + * @param it function to call on each signing key * @param it_cls closure for @a it - * @return + * @return number of files found (may not match + * number of keys given to @a it as malformed + * files are simply skipped), -1 on error */ int TALER_MINT_signkeys_iterate (const char *mint_base_dir, @@ -125,12 +131,17 @@ TALER_MINT_signkeys_iterate (const char *mint_base_dir, /** - * FIXME + * Call @a it for each denomination key found in the @a mint_base_dir. * - * @param mint_base_dir - * @param it + * @param mint_base_dir base directory for the mint, + * the signing keys must be in the #DIR_DENOMKEYS + * subdirectory + * @param it function to call on each denomination key found * @param it_cls closure for @a it - * @return + * @return -1 on error, 0 if no files were found, otherwise + * a positive number (however, even with a positive + * number it is possible that @a it was never called + * as maybe none of the files were well-formed) */ int TALER_MINT_denomkeys_iterate (const char *mint_base_dir, @@ -139,7 +150,7 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, /** - * Exports a denomination key to the given file + * Exports a denomination key to the given file. * * @param filename the file where to write the denomination key * @param dki the denomination key @@ -151,10 +162,10 @@ TALER_MINT_write_denom_key (const char *filename, /** - * Import a denomination key from the given file + * Import a denomination key from the given file. * * @param filename the file to import the key from - * @param dki pointer to return the imported denomination key + * @param[OUT] dki set to the imported denomination key * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ int -- cgit v1.2.3 From 126cd5b3fff4a6d78400e16d121fd381c47e20af Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:08:04 +0100 Subject: identifying where key_io still needs to be adapted --- src/include/taler_signatures.h | 6 ++---- src/mint/key_io.c | 5 +++-- src/mint/key_io.h | 4 ++++ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index b1b578236..c8e42add1 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -356,16 +356,14 @@ struct TALER_MINT_DenomKeyIssue struct GNUNET_TIME_AbsoluteNBO start; struct GNUNET_TIME_AbsoluteNBO expire_withdraw; struct GNUNET_TIME_AbsoluteNBO expire_spend; - // FIXME: does not work like this: - struct GNUNET_CRYPTO_rsa_PublicKey * denom_pub; struct TALER_AmountNBO value; struct TALER_AmountNBO fee_withdraw; struct TALER_AmountNBO fee_deposit; struct TALER_AmountNBO fee_refresh; + // FIXME: does not work like this: + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; }; - - GNUNET_NETWORK_STRUCT_END #endif diff --git a/src/mint/key_io.c b/src/mint/key_io.c index ad06da62d..98c4f5fff 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -71,7 +71,7 @@ signkeys_iterate_dir_iter (void *cls, if (nread != sizeof (struct TALER_MINT_SignKeyIssuePriv)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid signkey file: `%s'\n", + "Invalid signkey file `%s': wrong size\n", filename); return GNUNET_OK; } @@ -137,6 +137,8 @@ TALER_MINT_read_denom_key (const char *filename, offset = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.signature); + /* FIXME: this is very wrong, does not support variable-size + encoding of RSA keys (private or public!) */ if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, @@ -319,7 +321,6 @@ TALER_MINT_denomkeys_iterate (const char *mint_base_dir, void *it_cls) { char *dir; - size_t len; struct DenomkeysIterateContext dic; int ret; diff --git a/src/mint/key_io.h b/src/mint/key_io.h index aa59213c3..2f3f5fead 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -39,6 +39,8 @@ #define DIR_DENOMKEYS "denomkeys" +GNUNET_NETWORK_STRUCT_BEGIN + /** * On disk format used for a mint signing key. Signing keys are used * by the mint to affirm its messages, but not to create coins. @@ -58,6 +60,8 @@ struct TALER_MINT_SignKeyIssuePriv struct TALER_MINT_SignKeyIssue issue; }; +GNUNET_NETWORK_STRUCT_END + /** * All information about a denomination key (which is used to -- cgit v1.2.3 From 7673ca0137358a2b52b8cc352a33a0ce3e01a1c3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:18:14 +0100 Subject: document structs better --- src/include/taler_signatures.h | 86 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index c8e42add1..ac8f78a85 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -332,34 +332,116 @@ struct RefreshMeltConfirmSignRequestBody /** - * FIXME + * Information about a signing key of the mint. Signing keys are used + * to sign mint messages other than coins, i.e. to confirm that a + * deposit was successful or that a refresh was accepted. */ struct TALER_MINT_SignKeyIssue { + /** + * Signature over the signing key (by the master key of the mint). + */ struct GNUNET_CRYPTO_EddsaSignature signature; + + /** + * Purpose is #TALER_SIGNATURE_MASTER_SIGNKEY. + */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Master public key of the mint corresponding to @e signature. + * This is the long-term offline master key of the mint. + */ struct GNUNET_CRYPTO_EddsaPublicKey master_pub; + + /** + * When does this signing key begin to be valid? + */ struct GNUNET_TIME_AbsoluteNBO start; + + /** + * When does this signing key expire? Note: This is + * currently when the Mint will definitively stop using it. + * This does not mean that all signatures with tkey key are + * afterwards invalid. + */ struct GNUNET_TIME_AbsoluteNBO expire; + + /** + * The public online signing key that the mint will use + * between @e start and @e expire. + */ struct GNUNET_CRYPTO_EddsaPublicKey signkey_pub; }; /** - * FIXME + * Information about a denomination key. Denomination keys + * are used to sign coins of a certain value into existence. */ struct TALER_MINT_DenomKeyIssue { + /** + * Signature over this struct to affirm the validity + * of the key. + */ struct GNUNET_CRYPTO_EddsaSignature signature; + + /** + * Purpose ist #TALER_SIGNATURE_MASTER_DENOM. + */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * The long-term offline master key of the mint that was + * used to create @e signature. + */ struct GNUNET_CRYPTO_EddsaPublicKey master; + + /** + * Start time of the validity period for this key. + */ struct GNUNET_TIME_AbsoluteNBO start; + + /** + * The mint will sign fresh coins between @e start and + * this time. + */ struct GNUNET_TIME_AbsoluteNBO expire_withdraw; + + /** + * Coins signed with the denomination key must be spent or refreshed + * between @e start and this expiration time. After this time, the + * mint will refuse transactions involving this key as it will + * "drop" the table with double-spending information (shortly after) + * this time. Note that wallets should refresh coins significantly + * before this time to be on the safe side. + */ struct GNUNET_TIME_AbsoluteNBO expire_spend; + + /** + * The value of the coins signed with this denomination key. + */ struct TALER_AmountNBO value; + + /** + * The fee the mint charges when a coin of this type is withdrawn. + * (can be zero). + */ struct TALER_AmountNBO fee_withdraw; + + /** + * The fee the mint charges when a coin of this type is deposited. + * (can be zero). + */ struct TALER_AmountNBO fee_deposit; + + /** + * The fee the mint charges when a coin of this type is refreshed. + * (can be zero). + */ struct TALER_AmountNBO fee_refresh; + // FIXME: does not work like this: struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; }; -- cgit v1.2.3 From 4d98a1200a4dc03a89968212913dfd47bc1749a8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:27:32 +0100 Subject: refactor denomination key structs to allow proper signing / serialization with new variable-size RSA keys --- src/include/taler_signatures.h | 7 +++++-- src/mint/key_io.h | 9 ++++++++- src/mint/taler-mint-httpd_keystate.c | 14 ++++++++------ src/mint/taler-mint-keyup.c | 4 +++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index ac8f78a85..b91639321 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -442,8 +442,11 @@ struct TALER_MINT_DenomKeyIssue */ struct TALER_AmountNBO fee_refresh; - // FIXME: does not work like this: - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + /** + * Hash code of the denomination public key. + */ + struct GNUNET_HashCode denom_hash; + }; GNUNET_NETWORK_STRUCT_END diff --git a/src/mint/key_io.h b/src/mint/key_io.h index 2f3f5fead..b204629a2 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -60,6 +60,7 @@ struct TALER_MINT_SignKeyIssuePriv struct TALER_MINT_SignKeyIssue issue; }; + GNUNET_NETWORK_STRUCT_END @@ -77,7 +78,13 @@ struct TALER_MINT_DenomKeyIssuePriv struct GNUNET_CRYPTO_rsa_PrivateKey *denom_priv; /** - * Public information about a denomination key. + * Decoded denomination public key (the hash of it is in + * @e issue, but we sometimes need the full public key as well). + */ + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + + /** + * Signed public information about a denomination key. */ struct TALER_MINT_DenomKeyIssue issue; }; diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index 405b4bec6..bf802f5b5 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -106,11 +106,13 @@ static int reload_pipe[2]; * Convert the public part of a denomination key issue to a JSON * object. * + * @param pk public key of the denomination key * @param dki the denomination key issue * @return a JSON object describing the denomination key isue (public part) */ static json_t * -denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) +denom_key_issue_to_json (struct GNUNET_CRYPTO_rsa_PublicKey *pk, + const struct TALER_MINT_DenomKeyIssue *dki) { return json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", @@ -124,7 +126,7 @@ denom_key_issue_to_json (const struct TALER_MINT_DenomKeyIssue *dki) "stamp_expire_deposit", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend)), "denom_pub", - TALER_JSON_from_rsa_public_key (dki->denom_pub), + TALER_JSON_from_rsa_public_key (pk), "value", TALER_JSON_from_amount (TALER_amount_ntoh (dki->value)), "fee_withdraw", @@ -202,9 +204,8 @@ reload_keys_denom_iter (void *cls, return GNUNET_OK; } - GNUNET_CRYPTO_hash (&dki->issue.denom_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), - &denom_key_hash); + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + &denom_key_hash); d2 = GNUNET_memdup (dki, sizeof (struct TALER_MINT_DenomKeyIssuePriv)); res = GNUNET_CONTAINER_multihashmap_put (ctx->denomkey_map, @@ -220,7 +221,8 @@ reload_keys_denom_iter (void *cls, return GNUNET_OK; } json_array_append_new (ctx->denom_keys_array, - denom_key_issue_to_json (&dki->issue)); + denom_key_issue_to_json (dki->denom_pub, + &dki->issue)); return GNUNET_OK; } diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index c4e153476..c5358b6cf 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -442,7 +442,9 @@ create_denomkey_issue (struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssuePriv *dki) { GNUNET_assert (NULL != (dki->denom_priv = GNUNET_CRYPTO_rsa_private_key_create (RSA_KEYSIZE))); - dki->issue.denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv); + dki->denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv); + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + &dki->issue.denom_hash); dki->issue.master = *master_pub; dki->issue.start = GNUNET_TIME_absolute_hton (params->anchor); dki->issue.expire_withdraw = -- cgit v1.2.3 From 464077c547806d050d0bf75b28514dd9a4c7798b Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:37:08 +0100 Subject: properly handle variable-size RSA keys in key_io.c --- src/mint/key_io.c | 67 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/src/mint/key_io.c b/src/mint/key_io.c index 98c4f5fff..d267ce2a2 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -20,9 +20,6 @@ * @author Benedikt Mueller * @author Sree Harsha Totakura * @author Christian Grothoff - * - * TODO: - * - revisit IO with respect to variable-size RSA keys! */ #include "platform.h" #include "key_io.h" @@ -120,7 +117,8 @@ TALER_MINT_signkeys_iterate (const char *mint_base_dir, * * @param filename the file to import the key from * @param[OUT] dki set to the imported denomination key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + * @return #GNUNET_OK upon success; + * #GNUNET_SYSERR upon failure */ int TALER_MINT_read_denom_key (const char *filename, @@ -130,45 +128,54 @@ TALER_MINT_read_denom_key (const char *filename, size_t offset; void *data; struct GNUNET_CRYPTO_rsa_PrivateKey *priv; - int ret; - ret = GNUNET_SYSERR; - data = NULL; - offset = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - - offsetof (struct TALER_MINT_DenomKeyIssuePriv, - issue.signature); - /* FIXME: this is very wrong, does not support variable-size - encoding of RSA keys (private or public!) */ if (GNUNET_OK != GNUNET_DISK_file_size (filename, &size, GNUNET_YES, GNUNET_YES)) - goto cleanup; + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Skipping inaccessable denomination key file `%s'\n", + filename); + return GNUNET_SYSERR; + } + offset = sizeof (struct TALER_MINT_DenomKeyIssue); if (size <= offset) { GNUNET_break (0); - goto cleanup; + return GNUNET_SYSERR; } data = GNUNET_malloc (size); - if (size != GNUNET_DISK_fn_read (filename, - data, - size)) - goto cleanup; - if (NULL == (priv = GNUNET_CRYPTO_rsa_private_key_decode (data + offset, - size - offset))) - goto cleanup; + if (size != + GNUNET_DISK_fn_read (filename, + data, + size)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "read", + filename); + GNUNET_free (data); + return GNUNET_SYSERR; + } + if (NULL == + (priv = GNUNET_CRYPTO_rsa_private_key_decode (data + offset, + size - offset))) + { + GNUNET_free (data); + return GNUNET_SYSERR; + } dki->denom_priv = priv; - memcpy (&dki->issue.signature, data, offset); - ret = GNUNET_OK; - - cleanup: - GNUNET_free_non_null (data); - return ret; + dki->denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); + memcpy (&dki->issue, + data, + offset); + GNUNET_free (data); + return GNUNET_OK; } /** - * Exports a denomination key to the given file + * Exports a denomination key to the given file. * * @param filename the file where to write the denomination key * @param dki the denomination key @@ -194,9 +201,7 @@ TALER_MINT_write_denom_key (const char *filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_TRUNCATE, GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE))) goto cleanup; - wsize = sizeof (struct TALER_MINT_DenomKeyIssuePriv) - - offsetof (struct TALER_MINT_DenomKeyIssuePriv, - issue.signature); + wsize = sizeof (struct TALER_MINT_DenomKeyIssue); if (GNUNET_SYSERR == (wrote = GNUNET_DISK_file_write (fh, &dki->issue.signature, wsize))) -- cgit v1.2.3 From dc0146ea688cc870b6f3bcb03793383ada2f5af6 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:40:32 +0100 Subject: note todo --- src/mint/Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index 211d3c8fd..8a392bc58 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -4,6 +4,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/pq/ $(POSTGRESQL_C lib_LTLIBRARIES = \ libtalermint_common.la +# Note: mint_db.c should become a plugin soon! (#3608) libtalermint_common_la_SOURCES = \ key_io.c key_io.h \ mint_db.c -- cgit v1.2.3 From b5e69f22e905924a1cb4e5be3891182f5a0fa748 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 18:49:26 +0100 Subject: -fix recently introduced ftbfs --- src/lib/mint_api.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/lib/mint_api.c b/src/lib/mint_api.c index 3edb722bf..af4f04956 100644 --- a/src/lib/mint_api.c +++ b/src/lib/mint_api.c @@ -332,6 +332,8 @@ parse_json_amount (json_t *amount_obj, struct TALER_Amount *amt) return GNUNET_SYSERR; } + +/* FIXME: avoid useless ** for _denom_key! */ static int parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, json_t *denom_key_obj, @@ -354,6 +356,7 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, struct TALER_Amount fee_deposit; struct TALER_Amount fee_refresh; struct TALER_MINT_DenomKeyIssue denom_key_issue; + struct GNUNET_CRYPTO_rsa_PublicKey *pk; struct GNUNET_CRYPTO_EddsaSignature sig; EXITIF (JSON_OBJECT != json_typeof (denom_key_obj)); @@ -387,10 +390,12 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, GNUNET_STRINGS_string_to_data (key_enc, strlen (key_enc), buf, buf_size)); - denom_key_issue.denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + pk = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); GNUNET_free (buf); - EXITIF (NULL == denom_key_issue.denom_pub); + EXITIF (NULL == pk); + GNUNET_CRYPTO_rsa_public_key_hash (pk, + &denom_key_issue.denom_hash); EXITIF (NULL == (obj = json_object_get (denom_key_obj, "value"))); EXITIF (GNUNET_SYSERR == parse_json_amount (obj, &value)); EXITIF (NULL == (obj = json_object_get (denom_key_obj, "fee_withdraw"))); @@ -417,7 +422,7 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, &sig, master_key)); denom_key = GNUNET_new (struct TALER_MINT_DenomPublicKey); - denom_key->key = denom_key_issue.denom_pub; + denom_key->key = pk; denom_key->valid_from = valid_from; denom_key->withdraw_valid_until = withdraw_valid_until; denom_key->deposit_valid_until = deposit_valid_until; -- cgit v1.2.3 From a6a68a6a9868db57b18d6a3cf19dcf476e35bc3c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 21:10:05 +0100 Subject: review and minor fixes for taler-mint-keycheck.c --- src/mint/taler-mint-keycheck.c | 167 +++++++++++++++++++++++++++-------------- 1 file changed, 111 insertions(+), 56 deletions(-) diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c index b8f40c580..65d5f2062 100644 --- a/src/mint/taler-mint-keycheck.c +++ b/src/mint/taler-mint-keycheck.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -13,25 +13,40 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file taler-mint-keycheck.c - * @brief Check mint keys for validity. + * @brief Check mint keys for validity. Reads the signing and denomination + * keys from the mint directory and checks to make sure they are + * well-formed. This is purely a diagnostic tool. * @author Florian Dold * @author Benedikt Mueller + * @author Christian Grothoff */ - #include #include -#include "taler_signatures.h" #include "key_io.h" - +/** + * Mint directory with the keys. + */ static char *mintdir; +/** + * Our configuration. + */ static struct GNUNET_CONFIGURATION_Handle *kcfg; +/** + * Function called on each signing key. + * + * @param cls closure (NULL) + * @param filename name of the file the key came from + * @param ski the sign key + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to stop iteration with no error, + * #GNUNET_SYSERR to abort iteration with error! + */ static int signkeys_iter (void *cls, const char *filename, @@ -39,63 +54,81 @@ signkeys_iter (void *cls, { struct GNUNET_TIME_Absolute start; - printf ("iterating over key for start time %s\n", - GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (ski->issue.start))); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Iterating over key `%s' for start time %s\n", + filename, + GNUNET_STRINGS_absolute_time_to_string + (GNUNET_TIME_absolute_ntoh (ski->issue.start))); start = GNUNET_TIME_absolute_ntoh (ski->issue.start); - if (ntohl (ski->issue.purpose.size) != - (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose))) + (sizeof (struct TALER_MINT_SignKeyIssue) - + offsetof (struct TALER_MINT_SignKeyIssue, purpose))) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Signkey with start %s has invalid purpose field (timestamp: %llu)\n", - GNUNET_STRINGS_absolute_time_to_string (start), - (long long) start.abs_value_us); + fprintf (stderr, + "Signing key `%s' has invalid purpose size\n", + filename); return GNUNET_SYSERR; } - - - if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY, - &ski->issue.purpose, - &ski->issue.signature, - &ski->issue.master_pub)) + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY, + &ski->issue.purpose, + &ski->issue.signature, + &ski->issue.master_pub)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Signkey with start %s has invalid signature (timestamp: %llu)\n", - GNUNET_STRINGS_absolute_time_to_string (start), - (long long) start.abs_value_us); + fprintf (stderr, + "Signing key `%s' has invalid signature\n", + filename); return GNUNET_SYSERR; } - /* FIXME: what about private key matching the public key? */ - printf ("key valid\n"); + printf ("Signing key `%s' valid\n", + filename); return GNUNET_OK; } +/** + * Check signing keys. + * + * @return #GNUNET_OK if the keys are OK + * #GNUNET_NO if not + */ static int mint_signkeys_check () { - if (0 > TALER_MINT_signkeys_iterate (mintdir, signkeys_iter, NULL)) + if (0 > TALER_MINT_signkeys_iterate (mintdir, + &signkeys_iter, + NULL)) return GNUNET_NO; return GNUNET_OK; } +/** + * Function called on each denomination key. + * + * @param cls closure (NULL) + * @param dki the denomination key + * @param alias coin alias + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to stop iteration with no error, + * #GNUNET_SYSERR to abort iteration with error! + */ static int denomkeys_iter (void *cls, const char *alias, const struct TALER_MINT_DenomKeyIssuePriv *dki) { struct GNUNET_TIME_Absolute start; + struct GNUNET_HashCode hc; start = GNUNET_TIME_absolute_ntoh (dki->issue.start); - if (ntohl (dki->issue.purpose.size) != - (sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.purpose))) + sizeof (struct TALER_MINT_DenomKeyIssue)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Denomkey for '%s' with start %s has invalid purpose field (timestamp: %llu)\n", - alias, - GNUNET_STRINGS_absolute_time_to_string (start), - (long long) start.abs_value_us); + fprintf (stderr, + "Denomination key for `%s' has invalid purpose size\n", + alias); return GNUNET_SYSERR; } @@ -105,38 +138,46 @@ denomkeys_iter (void *cls, &dki->issue.signature, &dki->issue.master)) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Denomkey for '%s'with start %s has invalid signature (timestamp: %llu)\n", - alias, - GNUNET_STRINGS_absolute_time_to_string (start), - (long long) start.abs_value_us); + fprintf (stderr, + "Denomination key for `%s' has invalid signature\n", + alias); return GNUNET_SYSERR; } - printf ("denom key valid\n"); + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + &hc); + if (0 != memcmp (&hc, + &dki->issue.denom_hash, + sizeof (struct GNUNET_HashCode))) + { + fprintf (stderr, + "Public key for `%s' does not match signature\n", + alias); + return GNUNET_SYSERR; + } + printf ("Denomination key `%s' is valid\n", + alias); return GNUNET_OK; } +/** + * Check denomination keys. + * + * @return #GNUNET_OK if the keys are OK + * #GNUNET_NO if not + */ static int mint_denomkeys_check () { if (0 > TALER_MINT_denomkeys_iterate (mintdir, - &denomkeys_iter, NULL)) + &denomkeys_iter, + NULL)) return GNUNET_NO; return GNUNET_OK; } -static int -mint_keys_check (void) -{ - if (GNUNET_OK != mint_signkeys_check ()) - return GNUNET_NO; - return mint_denomkeys_check (); -} - - /** * The main function of the keyup tool * @@ -148,30 +189,44 @@ int main (int argc, char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"), - {'d', "mint-dir", "DIR", - "mint directory with keys to update", 1, + GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keycheck OPTIONS"), + {'d', "directory", "DIRECTORY", + "mint directory with keys to check", 1, &GNUNET_GETOPT_set_filename, &mintdir}, GNUNET_GETOPT_OPTION_END }; - GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keycheck", "WARNING", NULL)); + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-mint-keycheck", + "WARNING", + NULL)); - if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-keycheck", + options, + argc, argv) < 0) return 1; if (NULL == mintdir) { - fprintf (stderr, "mint directory not given\n"); + fprintf (stderr, + "Mint directory not given\n"); return 1; } kcfg = TALER_config_load (mintdir); if (NULL == kcfg) { - fprintf (stderr, "can't load mint configuration\n"); + fprintf (stderr, + "Failed to load mint configuration\n"); return 1; } - if (GNUNET_OK != mint_keys_check ()) + if ( (GNUNET_OK != mint_signkeys_check ()) || + (GNUNET_OK != mint_denomkeys_check ()) ) + { + GNUNET_CONFIGURATION_destroy (kcfg); return 1; + } + GNUNET_CONFIGURATION_destroy (kcfg); return 0; } + +/* end of taler-mint-keycheck.c */ -- cgit v1.2.3 From 8e7f9c2939eaac24d8bd007437eaa45e81835f93 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 15 Mar 2015 22:33:28 +0100 Subject: misc minor indentation, logging, comment fixes --- src/mint/taler-mint-keycheck.c | 5 - src/mint/taler-mint-keyup.c | 494 ++++++++++++++++++++++++++++++++--------- 2 files changed, 395 insertions(+), 104 deletions(-) diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c index 65d5f2062..cb46c14e7 100644 --- a/src/mint/taler-mint-keycheck.c +++ b/src/mint/taler-mint-keycheck.c @@ -52,15 +52,12 @@ signkeys_iter (void *cls, const char *filename, const struct TALER_MINT_SignKeyIssuePriv *ski) { - struct GNUNET_TIME_Absolute start; - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iterating over key `%s' for start time %s\n", filename, GNUNET_STRINGS_absolute_time_to_string (GNUNET_TIME_absolute_ntoh (ski->issue.start))); - start = GNUNET_TIME_absolute_ntoh (ski->issue.start); if (ntohl (ski->issue.purpose.size) != (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose))) @@ -119,10 +116,8 @@ denomkeys_iter (void *cls, const char *alias, const struct TALER_MINT_DenomKeyIssuePriv *dki) { - struct GNUNET_TIME_Absolute start; struct GNUNET_HashCode hc; - start = GNUNET_TIME_absolute_ntoh (dki->issue.start); if (ntohl (dki->issue.purpose.size) != sizeof (struct TALER_MINT_DenomKeyIssue)) { diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index c5358b6cf..1b388a20a 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -13,7 +13,6 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file taler-mint-keyup.c * @brief Update the mint's keys for coins and signatures, @@ -21,11 +20,9 @@ * @author Florian Dold * @author Benedikt Mueller */ - #include #include #include "taler_util.h" -#include "taler_signatures.h" #include "key_io.h" /** @@ -33,6 +30,9 @@ */ #define RSA_KEYSIZE 2048 +/** + * + */ #define HASH_CUTOFF 20 /** @@ -43,27 +43,88 @@ GNUNET_NETWORK_STRUCT_BEGIN +/** + * + */ struct CoinTypeNBO { + /** + * + */ struct GNUNET_TIME_RelativeNBO duration_spend; + + /** + * + */ struct GNUNET_TIME_RelativeNBO duration_withdraw; + + /** + * + */ struct TALER_AmountNBO value; + + /** + * + */ struct TALER_AmountNBO fee_withdraw; + + /** + * + */ struct TALER_AmountNBO fee_deposit; + + /** + * + */ struct TALER_AmountNBO fee_refresh; }; GNUNET_NETWORK_STRUCT_END +/** + * + */ struct CoinTypeParams { + + /** + * + */ struct GNUNET_TIME_Relative duration_spend; + + /** + * + */ struct GNUNET_TIME_Relative duration_withdraw; + + /** + * + */ struct GNUNET_TIME_Relative duration_overlap; + + /** + * + */ struct TALER_Amount value; + + /** + * + */ struct TALER_Amount fee_withdraw; + + /** + * + */ struct TALER_Amount fee_deposit; + + /** + * + */ struct TALER_Amount fee_refresh; + + /** + * + */ struct GNUNET_TIME_Absolute anchor; }; @@ -110,37 +171,66 @@ static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub; static struct GNUNET_TIME_Absolute lookahead_sign_stamp; +/** + * + * + * @param section + * @param option + * @param denom + * @return + */ static int -config_get_denom (const char *section, const char *option, struct TALER_Amount *denom) +config_get_denom (const char *section, + const char *option, + struct TALER_Amount *denom) { char *str; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg, section, option, &str)) + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (kcfg, + section, + option, + &str)) return GNUNET_NO; - if (GNUNET_OK != TALER_string_to_amount (str, denom)) + if (GNUNET_OK != TALER_string_to_amount (str, + denom)) return GNUNET_SYSERR; return GNUNET_OK; } +/** + * + * + * @return + */ static char * get_signkey_dir () { char *dir; - size_t len; - len = GNUNET_asprintf (&dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS), mintdir); - GNUNET_assert (len > 0); + + GNUNET_asprintf (&dir, + "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, + mintdir); return dir; } +/** + * + * + * @param start + * @return + */ static char * get_signkey_file (struct GNUNET_TIME_Absolute start) { char *dir; - size_t len; - len = GNUNET_asprintf (&dir, ("%s" DIR_SEPARATOR_STR DIR_SIGNKEYS DIR_SEPARATOR_STR "%llu"), - mintdir, (long long) start.abs_value_us); - GNUNET_assert (len > 0); + + GNUNET_asprintf (&dir, + "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS DIR_SEPARATOR_STR "%llu", + mintdir, + (unsigned long long) start.abs_value_us); return dir; } @@ -149,13 +239,19 @@ get_signkey_file (struct GNUNET_TIME_Absolute start) * Hash the data defining the coin type. * Exclude information that may not be the same for all * instances of the coin type (i.e. the anchor, overlap). + * + * @param p + * @param hash */ static void -hash_coin_type (const struct CoinTypeParams *p, struct GNUNET_HashCode *hash) +hash_coin_type (const struct CoinTypeParams *p, + struct GNUNET_HashCode *hash) { struct CoinTypeNBO p_nbo; - memset (&p_nbo, 0, sizeof (struct CoinTypeNBO)); + memset (&p_nbo, + 0, + sizeof (struct CoinTypeNBO)); p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend); p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw); @@ -164,15 +260,22 @@ hash_coin_type (const struct CoinTypeParams *p, struct GNUNET_HashCode *hash) p_nbo.fee_deposit = TALER_amount_hton (p->fee_deposit); p_nbo.fee_refresh = TALER_amount_hton (p->fee_refresh); - GNUNET_CRYPTO_hash (&p_nbo, sizeof (struct CoinTypeNBO), hash); + GNUNET_CRYPTO_hash (&p_nbo, + sizeof (struct CoinTypeNBO), + hash); } +/** + * + * + * @param p + * @return + */ static const char * get_cointype_dir (const struct CoinTypeParams *p) { static char dir[4096]; - size_t len; struct GNUNET_HashCode hash; char *hash_str; char *val_str; @@ -190,26 +293,37 @@ get_cointype_dir (const struct CoinTypeParams *p) if (':' == val_str[i] || '.' == val_str[i]) val_str[i] = '_'; - len = GNUNET_snprintf (dir, sizeof (dir), - ("%s" DIR_SEPARATOR_STR DIR_DENOMKEYS DIR_SEPARATOR_STR "%s-%s"), - mintdir, val_str, hash_str); - GNUNET_assert (len > 0); + GNUNET_snprintf (dir, + sizeof (dir), + "%s" DIR_SEPARATOR_STR DIR_DENOMKEYS DIR_SEPARATOR_STR "%s-%s", + mintdir, + val_str, + hash_str); GNUNET_free (hash_str); return dir; } +/** + * + * + * @param p + * @param start + * @return + */ static const char * get_cointype_file (struct CoinTypeParams *p, struct GNUNET_TIME_Absolute start) { const char *dir; static char filename[4096]; - size_t len; + dir = get_cointype_dir (p); - len = GNUNET_snprintf (filename, sizeof (filename), ("%s" DIR_SEPARATOR_STR "%llu"), - dir, (unsigned long long) start.abs_value_us); - GNUNET_assert (len > 0); + GNUNET_snprintf (filename, + sizeof (filename), + "%s" DIR_SEPARATOR_STR "%llu", + dir, + (unsigned long long) start.abs_value_us); return filename; } @@ -227,23 +341,28 @@ static int get_anchor_iter (void *cls, const char *filename) { - struct GNUNET_TIME_Absolute stamp; struct GNUNET_TIME_Absolute *anchor = cls; + struct GNUNET_TIME_Absolute stamp; const char *base; char *end = NULL; base = GNUNET_STRINGS_get_short_name (filename); - stamp.abs_value_us = strtol (base, &end, 10); + stamp.abs_value_us = strtol (base, + &end, + 10); if ((NULL == end) || (0 != *end)) { - fprintf(stderr, "Ignoring unexpected file '%s'.\n", filename); + fprintf(stderr, + "Ignoring unexpected file '%s'.\n", + filename); return GNUNET_OK; } // TODO: check if it's actually a valid key file - if ((stamp.abs_value_us <= now.abs_value_us) && (stamp.abs_value_us > anchor->abs_value_us)) + if ( (stamp.abs_value_us <= now.abs_value_us) && + ( stamp.abs_value_us > anchor->abs_value_us) ) *anchor = stamp; return GNUNET_OK; @@ -267,21 +386,28 @@ get_anchor (const char *dir, { GNUNET_assert (0 == duration.rel_value_us % 1000000); GNUNET_assert (0 == overlap.rel_value_us % 1000000); - if (GNUNET_YES != GNUNET_DISK_directory_test (dir, GNUNET_YES)) + if (GNUNET_YES != + GNUNET_DISK_directory_test (dir, GNUNET_YES)) { *anchor = now; - printf ("Can't look for anchor (%s)\n", dir); + fprintf (stderr, + "Cannot look for anchor (%s)\n", + dir); return; } *anchor = GNUNET_TIME_UNIT_ZERO_ABS; - if (-1 == GNUNET_DISK_directory_scan (dir, &get_anchor_iter, anchor)) + if (-1 == + GNUNET_DISK_directory_scan (dir, + &get_anchor_iter, + anchor)) { *anchor = now; return; } - if ((GNUNET_TIME_absolute_add (*anchor, duration)).abs_value_us < now.abs_value_us) + if ((GNUNET_TIME_absolute_add (*anchor, + duration)).abs_value_us < now.abs_value_us) { // there's no good anchor, start from now // (existing keys are too old) @@ -297,6 +423,13 @@ get_anchor (const char *dir, } +/** + * + * + * @param start + * @param duration + * @param pi + */ static void create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration, @@ -306,17 +439,20 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, struct TALER_MINT_SignKeyIssue *issue = &pi->issue; priv = GNUNET_CRYPTO_eddsa_key_create (); - GNUNET_assert (NULL != priv); pi->signkey_priv = *priv; GNUNET_free (priv); issue->master_pub = *master_pub; issue->start = GNUNET_TIME_absolute_hton (start); - issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, duration)); + issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, + duration)); - GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv, &issue->signkey_pub); + GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv, + &issue->signkey_pub); issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY); - issue->purpose.size = htonl (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose)); + issue->purpose.size = htonl (sizeof (struct TALER_MINT_SignKeyIssue) - + offsetof (struct TALER_MINT_SignKeyIssue, + purpose)); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (master_priv, @@ -325,6 +461,12 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, } +/** + * + * + * @param signkey_filename + * @return + */ static int check_signkey_valid (const char *signkey_filename) { @@ -333,6 +475,11 @@ check_signkey_valid (const char *signkey_filename) } +/** + * + * + * @return + */ static int mint_keys_update_signkeys () { @@ -340,37 +487,60 @@ mint_keys_update_signkeys () struct GNUNET_TIME_Absolute anchor; char *signkey_dir; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_keys", "signkey_duration", &signkey_duration)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_keys", + "signkey_duration", + &signkey_duration)) { - fprintf (stderr, "Can't read config value mint_keys.signkey_duration\n"); + fprintf (stderr, + "Cannot read config value mint_keys.signkey_duration\n"); return GNUNET_SYSERR; } - ROUND_TO_SECS (signkey_duration, rel_value_us); + ROUND_TO_SECS (signkey_duration, + rel_value_us); signkey_dir = get_signkey_dir (); // make sure the directory exists - if (GNUNET_OK != GNUNET_DISK_directory_create (signkey_dir)) + if (GNUNET_OK != + GNUNET_DISK_directory_create (signkey_dir)) { - fprintf (stderr, "Cant create signkey dir\n"); + fprintf (stderr, + "Failed to create signing key directory\n"); return GNUNET_SYSERR; } - get_anchor (signkey_dir, signkey_duration, GNUNET_TIME_UNIT_ZERO, &anchor); + get_anchor (signkey_dir, + signkey_duration, + GNUNET_TIME_UNIT_ZERO, + &anchor); - while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) { + while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) + { char *skf; + skf = get_signkey_file (anchor); - if (GNUNET_YES != GNUNET_DISK_file_test (skf)) + if (GNUNET_YES != + GNUNET_DISK_file_test (skf)) { struct TALER_MINT_SignKeyIssuePriv signkey_issue; ssize_t nwrite; - printf ("Generating signing key for %s.\n", - GNUNET_STRINGS_absolute_time_to_string (anchor)); - create_signkey_issue_priv (anchor, signkey_duration, &signkey_issue); - nwrite = GNUNET_DISK_fn_write (skf, &signkey_issue, sizeof (struct TALER_MINT_SignKeyIssue), - (GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ)); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Generating signing key for %s.\n", + GNUNET_STRINGS_absolute_time_to_string (anchor)); + create_signkey_issue_priv (anchor, + signkey_duration, + &signkey_issue); + nwrite = GNUNET_DISK_fn_write (skf, + &signkey_issue, + sizeof (struct TALER_MINT_SignKeyIssue), + GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ); if (nwrite != sizeof (struct TALER_MINT_SignKeyIssue)) { - fprintf (stderr, "Can't write to file '%s'\n", skf); + fprintf (stderr, + "Failed to write to file `%s': %s\n", + skf, + STRERROR (errno)); return GNUNET_SYSERR; } } @@ -384,50 +554,99 @@ mint_keys_update_signkeys () } +/** + * + * + * @param ct + * @param params + * @return + */ static int -get_cointype_params (const char *ct, struct CoinTypeParams *params) +get_cointype_params (const char *ct, + struct CoinTypeParams *params) { const char *dir; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_withdraw", ct, ¶ms->duration_withdraw)) + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_denom_duration_withdraw", + ct, + ¶ms->duration_withdraw)) { - fprintf (stderr, "Withdraw duration not given for coin type '%s'\n", ct); + fprintf (stderr, + "Withdraw duration not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } - ROUND_TO_SECS (params->duration_withdraw, rel_value_us); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_spend", ct, ¶ms->duration_spend)) + ROUND_TO_SECS (params->duration_withdraw, + rel_value_us); + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_denom_duration_spend", + ct, + ¶ms->duration_spend)) { - fprintf (stderr, "Spend duration not given for coin type '%s'\n", ct); + fprintf (stderr, + "Spend duration not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_spend, rel_value_us); - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_overlap", ct, ¶ms->duration_overlap)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_denom_duration_overlap", + ct, + ¶ms->duration_overlap)) { - fprintf (stderr, "Overlap duration not given for coin type '%s'\n", ct); + fprintf (stderr, + "Overlap duration not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } - ROUND_TO_SECS (params->duration_overlap, rel_value_us); + ROUND_TO_SECS (params->duration_overlap, + rel_value_us); - if (GNUNET_OK != config_get_denom ("mint_denom_value", ct, ¶ms->value)) + if (GNUNET_OK != + config_get_denom ("mint_denom_value", + ct, + ¶ms->value)) { - fprintf (stderr, "Value not given for coin type '%s'\n", ct); + fprintf (stderr, + "Value not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } - if (GNUNET_OK != config_get_denom ("mint_denom_fee_withdraw", ct, ¶ms->fee_withdraw)) + if (GNUNET_OK != + config_get_denom ("mint_denom_fee_withdraw", + ct, + ¶ms->fee_withdraw)) { - fprintf (stderr, "Withdraw fee not given for coin type '%s'\n", ct); + fprintf (stderr, + "Withdraw fee not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } - if (GNUNET_OK != config_get_denom ("mint_denom_fee_deposit", ct, ¶ms->fee_deposit)) + if (GNUNET_OK != + config_get_denom ("mint_denom_fee_deposit", + ct, + ¶ms->fee_deposit)) { - fprintf (stderr, "Deposit fee not given for coin type '%s'\n", ct); + fprintf (stderr, + "Deposit fee not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } - if (GNUNET_OK != config_get_denom ("mint_denom_fee_refresh", ct, ¶ms->fee_refresh)) + if (GNUNET_OK != + config_get_denom ("mint_denom_fee_refresh", + ct, + ¶ms->fee_refresh)) { - fprintf (stderr, "Deposit fee not given for coin type '%s'\n", ct); + fprintf (stderr, + "Deposit fee not given for coin type '%s'\n", + ct); return GNUNET_SYSERR; } @@ -437,6 +656,12 @@ get_cointype_params (const char *ct, struct CoinTypeParams *params) } +/** + * + * + * @param params + * @param dki + */ static void create_denomkey_issue (struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssuePriv *dki) @@ -459,7 +684,9 @@ create_denomkey_issue (struct CoinTypeParams *params, dki->issue.fee_refresh = TALER_amount_hton (params->fee_refresh); dki->issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOM); - dki->issue.purpose.size = htonl (sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.purpose)); + dki->issue.purpose.size = htonl (sizeof (struct TALER_MINT_DenomKeyIssuePriv) - + offsetof (struct TALER_MINT_DenomKeyIssuePriv, + issue.purpose)); GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (master_priv, @@ -468,14 +695,28 @@ create_denomkey_issue (struct CoinTypeParams *params, } +/** + * + * + * @param filename + * @param params + * @return + */ static int -check_cointype_valid (const char *filename, struct CoinTypeParams *params) +check_cointype_valid (const char *filename, + struct CoinTypeParams *params) { // FIXME: add real checks return GNUNET_OK; } +/** + * + * + * @param coin_alias + * @return + */ static int mint_keys_update_cointype (const char *coin_alias) { @@ -489,24 +730,32 @@ mint_keys_update_cointype (const char *coin_alias) if (GNUNET_OK != GNUNET_DISK_directory_create (cointype_dir)) return GNUNET_SYSERR; - while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) { + while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) + { const char *dkf; + dkf = get_cointype_file (&p, p.anchor); if (GNUNET_YES != GNUNET_DISK_file_test (dkf)) { struct TALER_MINT_DenomKeyIssuePriv denomkey_issue; int ret; - printf ("Generating denomination key for type '%s', start %s.\n", - coin_alias, - GNUNET_STRINGS_absolute_time_to_string (p.anchor)); - printf ("Target path: %s\n", dkf); - create_denomkey_issue (&p, &denomkey_issue); - ret = TALER_MINT_write_denom_key (dkf, &denomkey_issue); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Generating denomination key for type '%s', start %s at %s\n", + coin_alias, + GNUNET_STRINGS_absolute_time_to_string (p.anchor), + dkf); + create_denomkey_issue (&p, + &denomkey_issue); + ret = TALER_MINT_write_denom_key (dkf, + &denomkey_issue); GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); if (GNUNET_OK != ret) { - fprintf (stderr, "Can't write to file '%s'\n", dkf); + fprintf (stderr, + "Failed to write to file `%s'\n", + dkf); return GNUNET_SYSERR; } } @@ -521,6 +770,11 @@ mint_keys_update_cointype (const char *coin_alias) } +/** + * + * + * @return + */ static int mint_keys_update_denomkeys () { @@ -528,9 +782,14 @@ mint_keys_update_denomkeys () char *ct; char *tok_ctx; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (kcfg, "mint_keys", "coin_types", &coin_types)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (kcfg, + "mint_keys", + "coin_types", + &coin_types)) { - fprintf (stderr, "mint_keys.coin_types not in configuration\n"); + fprintf (stderr, + "mint_keys.coin_types not in configuration\n"); return GNUNET_SYSERR; } @@ -549,23 +808,36 @@ mint_keys_update_denomkeys () } +/** + * + * @return + */ static int mint_keys_update () { int ret; struct GNUNET_TIME_Relative lookahead_sign; - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_keys", "lookahead_sign", &lookahead_sign)) + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_keys", + "lookahead_sign", + &lookahead_sign)) { - fprintf (stderr, "mint_keys.lookahead_sign not found\n"); + fprintf (stderr, + "mint_keys.lookahead_sign not found\n"); return GNUNET_SYSERR; } - if (lookahead_sign.rel_value_us == 0) + if (0 == lookahead_sign.rel_value_us) { - fprintf (stderr, "mint_keys.lookahead_sign must not be zero\n"); + fprintf (stderr, + "mint_keys.lookahead_sign must not be zero\n"); return GNUNET_SYSERR; } - ROUND_TO_SECS (lookahead_sign, rel_value_us); - lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, lookahead_sign); + ROUND_TO_SECS (lookahead_sign, + rel_value_us); + lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, + lookahead_sign); ret = mint_keys_update_signkeys (); if (GNUNET_OK != ret) @@ -599,21 +871,30 @@ main (int argc, char *const *argv) GNUNET_GETOPT_OPTION_END }; - GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keyup", "WARNING", NULL)); + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-mint-keyup", + "WARNING", + NULL)); - if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-keyup", + options, + argc, argv) < 0) return 1; if (NULL == mintdir) { - fprintf (stderr, "mint directory not given\n"); + fprintf (stderr, + "mint directory not given\n"); return 1; } if (NULL != pretend_time_str) { - if (GNUNET_OK != GNUNET_STRINGS_fancy_time_to_absolute (pretend_time_str, &now)) + if (GNUNET_OK != + GNUNET_STRINGS_fancy_time_to_absolute (pretend_time_str, + &now)) { - fprintf (stderr, "timestamp invalid\n"); + fprintf (stderr, + "timestamp invalid\n"); return 1; } } @@ -626,39 +907,52 @@ main (int argc, char *const *argv) kcfg = TALER_config_load (mintdir); if (NULL == kcfg) { - fprintf (stderr, "can't load mint configuration\n"); + fprintf (stderr, + "Failed to load mint configuration\n"); return 1; } if (NULL == masterkeyfile) { - fprintf (stderr, "master key file not given\n"); + fprintf (stderr, + "master key file not given\n"); return 1; } master_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile); if (NULL == master_priv) { - fprintf (stderr, "master key invalid\n"); + fprintf (stderr, + "Failed to initialize master key from file `%s'\n", + masterkeyfile); return 1; } master_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey); - GNUNET_CRYPTO_eddsa_key_get_public (master_priv, master_pub); + GNUNET_CRYPTO_eddsa_key_get_public (master_priv, + master_pub); // check if key from file matches the one from the configuration { struct GNUNET_CRYPTO_EddsaPublicKey master_pub_from_cfg; + if (GNUNET_OK != - GNUNET_CONFIGURATION_get_data (kcfg, "mint", "master_pub", + GNUNET_CONFIGURATION_get_data (kcfg, + "mint", + "master_pub", &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) { - fprintf (stderr, "master key missing in configuration (mint.master_pub)\n"); + fprintf (stderr, + "Master public key missing in configuration (mint.master_pub)\n"); return 1; } - if (0 != memcmp (master_pub, &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) + if (0 != + memcmp (master_pub, + &master_pub_from_cfg, + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) { - fprintf (stderr, "Mismatch between key from mint configuration and master private key file from command line.\n"); + fprintf (stderr, + "Mismatch between key from mint configuration and master private key file from command line.\n"); return 1; } } @@ -667,3 +961,5 @@ main (int argc, char *const *argv) return 1; return 0; } + +/* end of taler-mint-keyup.c */ -- cgit v1.2.3 From 7a417e1de07ccc6f8fdbe6519fa0041a5c1dbbb8 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Fri, 13 Mar 2015 19:22:30 +0100 Subject: db: update deposits table to support var length RSA denom keys --- src/mint/mint_db.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 50904df39..22d04c865 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -251,12 +251,13 @@ TALER_MINT_DB_create_tables (int temporary) SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " "( " " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)" - ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)" + ",denom_pub BYTEA NOT NULL" /* FIXME: Link this as a foreign key? */ + ",denom_sig BYTEA NOT NULL" ",transaction_id INT8 NOT NULL" ",amount_currency VARCHAR(4) NOT NULL" ",amount_value INT4 NOT NULL" ",amount_fraction INT4 NOT NULL" - ",merchant_pub BYTEA NOT NULL" + ",merchant_pub BYTEA NOT NULL CHECK (length(merchant_pub)=32)" ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)" ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)" ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)" -- cgit v1.2.3 From b7c6edb0e5218a3f09e11ca3c6455eccd958e959 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Sat, 14 Mar 2015 14:47:55 +0100 Subject: httpd: Use the right fee for deposit transaction --- src/mint/taler-mint-httpd_db.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 5e57e152d..df68b6570 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -74,7 +74,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, struct TALER_Amount spent; struct TALER_Amount value; struct TALER_Amount fee_deposit; - struct TALER_Amount fee_withdraw; struct TALER_Amount fee_refresh; struct MintKeyState *mks; struct TALER_MINT_DenomKeyIssuePriv *dki; @@ -113,7 +112,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, } tl = TALER_MINT_DB_get_coin_transactions (db_conn, &deposit->coin.coin_pub); - spent = fee_withdraw; /* fee for THIS transaction */ + spent = fee_deposit; /* fee for THIS transaction */ /* FIXME: need to deal better with integer overflows in the logic that follows! (change amount.c API! -- #3637) */ spent = TALER_amount_add (spent, -- cgit v1.2.3 From f8a77d3ca9f39e7ee07b5e536919d7344d8905a0 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Sat, 14 Mar 2015 15:01:53 +0100 Subject: util: Use TALER_CURRENCY_LEN instead of sizeof() --- src/util/amount.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/amount.c b/src/util/amount.c index 9bdc0fd93..0b77de82b 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -159,7 +159,7 @@ TALER_amount_ntoh (const struct TALER_AmountNBO dn) struct TALER_Amount d; d.value = ntohl (dn.value); d.fraction = ntohl (dn.fraction); - memcpy (d.currency, dn.currency, sizeof(dn.currency)); + memcpy (d.currency, dn.currency, TALER_CURRENCY_LEN); return d; } -- cgit v1.2.3 From 99af8083f5372da59b1d965c63f9be8e750c4aa9 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Sat, 14 Mar 2015 15:02:54 +0100 Subject: db: implement insert_deposit() --- src/mint/mint_db.c | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 22d04c865..1a8acaa5f 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -529,6 +529,7 @@ TALER_MINT_DB_prepare (PGconn *db_conn) "INSERT INTO deposits (" "coin_pub," "denom_pub," + "denom_sig," "transaction_id," "amount_value," "amount_fraction," @@ -539,9 +540,9 @@ TALER_MINT_DB_prepare (PGconn *db_conn) "coin_sig," "wire" ") VALUES (" - "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11" + "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12" ")", - 11, NULL); + 12, NULL); PREPARE ("get_deposit", "SELECT " "coin_pub," @@ -1324,35 +1325,55 @@ int TALER_MINT_DB_insert_deposit (PGconn *db_conn, const struct Deposit *deposit) { - // FIXME: check logic! + char *denom_pub_enc; + char *denom_sig_enc; + char *json_wire_enc; + PGresult *result; + struct TALER_AmountNBO amount_nbo; + size_t denom_pub_enc_size; + size_t denom_sig_enc_size; + int ret; + + ret = GNUNET_SYSERR; + denom_pub_enc_size = + GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub, + &denom_pub_enc); + denom_sig_enc_size = + GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig, + &denom_sig_enc); + json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); + amount_nbo = TALER_amount_hton (deposit->amount); struct TALER_DB_QueryParam params[]= { TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_pub), // FIXME! - TALER_DB_QUERY_PARAM_PTR (&deposit->coin.denom_sig), // FIXME! + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size), TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), - TALER_DB_QUERY_PARAM_PTR (&deposit->amount.value), - TALER_DB_QUERY_PARAM_PTR (&deposit->amount.fraction), - TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->amount.currency, - strlen (deposit->amount.currency)), + TALER_DB_QUERY_PARAM_PTR (&amount_nbo.value), + TALER_DB_QUERY_PARAM_PTR (&amount_nbo.fraction), + TALER_DB_QUERY_PARAM_PTR_SIZED (amount_nbo.currency, + TALER_CURRENCY_LEN - 1), TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract), TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire), TALER_DB_QUERY_PARAM_PTR (&deposit->csig), - TALER_DB_QUERY_PARAM_PTR_SIZED (deposit->wire, - strlen ("FIXME")), // FIXME! json! + TALER_DB_QUERY_PARAM_PTR_SIZED (json_wire_enc, + strlen (json_wire_enc)), TALER_DB_QUERY_PARAM_END }; - PGresult *result; - result = TALER_DB_exec_prepared (db_conn, "insert_deposit", params); if (PGRES_COMMAND_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; + goto cleanup; } + ret = GNUNET_OK; + + cleanup: PQclear (result); - return GNUNET_OK; + GNUNET_free_non_null (denom_pub_enc); + GNUNET_free_non_null (denom_sig_enc); + GNUNET_free_non_null (json_wire_enc); + return ret; } -- cgit v1.2.3 From d794a6d53a93970804469c74631b1f41254ac0b7 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Mon, 16 Mar 2015 11:01:01 +0100 Subject: db: implement have_deposit() --- src/mint/mint_db.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 1a8acaa5f..6ed7193e3 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -556,9 +556,11 @@ TALER_MINT_DB_prepare (PGconn *db_conn) "h_wire," "coin_sig" " FROM deposits WHERE (" - "coin_pub = $1" + "(coin_pub = $1) AND" + "(transaction_id = $2) AND" + "(merchant_pub = $3)" ")", - 1, NULL); + 3, NULL); return GNUNET_OK; #undef PREPARE } @@ -1286,13 +1288,16 @@ int TALER_MINT_DB_have_deposit (PGconn *db_conn, const struct Deposit *deposit) { - // FIXME: check logic! struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), // FIXME + TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), + TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), + TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), TALER_DB_QUERY_PARAM_END }; PGresult *result; + int ret; + ret = GNUNET_SYSERR; result = TALER_DB_exec_prepared (db_conn, "get_deposit", params); @@ -1300,16 +1305,19 @@ TALER_MINT_DB_have_deposit (PGconn *db_conn, PQresultStatus (result)) { BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; + goto cleanup; } if (0 == PQntuples (result)) { - PQclear (result); - return GNUNET_NO; + ret = GNUNET_NO; + goto cleanup; } - return GNUNET_YES; + ret = GNUNET_YES; + + cleanup: + PQclear (result); + return ret; } -- cgit v1.2.3 From b3e076b10a1ef630d03bf8ed123a4a64e34395b5 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Mon, 16 Mar 2015 11:01:33 +0100 Subject: db: testcases for insert_deposit and have_deposit --- src/mint/test_mint_db.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index c18ad2e8e..010416138 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -126,11 +126,23 @@ run (void *cls, char *const *args, const char *cfgfile, struct ReserveHistory *rh_head; struct BankTransfer *bt; struct CollectableBlindcoin *withdraw; + struct Deposit deposit; + struct Deposit deposit2; + struct json_t *wire; + const char * const json_wire_str = + "{ \"type\":\"SEPA\", \ +\"IBAN\":\"DE67830654080004822650\", \ +\"name\":\"GNUnet e.V.\", \ +\"bic\":\"GENODEF1SLR\", \ +\"edate\":\"1449930207000\", \ +\"r\":123456789, \ +\"address\": \"foobar\"}"; unsigned int cnt; db = NULL; dkp = NULL; rh = NULL; + wire = NULL; ZR_BLK (&cbc); ZR_BLK (&cbc2); if (GNUNET_OK != TALER_MINT_DB_init ("postgres:///taler")) @@ -217,9 +229,35 @@ run (void *cls, char *const *args, const char *cfgfile, } } FAILIF (3 != cnt); + /* Tests for deposits */ + RND_BLK (&deposit.coin.coin_pub); + deposit.coin.denom_pub = dkp->pub; + deposit.coin.denom_sig = cbc.sig; + RND_BLK (&deposit.csig); + RND_BLK (&deposit.merchant_pub); + RND_BLK (&deposit.h_contract); + RND_BLK (&deposit.h_wire); + wire = json_loads (json_wire_str, 0, NULL); + deposit.wire = wire; + deposit.transaction_id = + GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); + deposit.amount = amount; + FAILIF (GNUNET_OK != TALER_MINT_DB_insert_deposit (db, &deposit)); + FAILIF (GNUNET_YES != TALER_MINT_DB_have_deposit (db, &deposit)); + (void) memcpy (&deposit2, &deposit, sizeof (deposit)); + deposit2.transaction_id++; /* should fail if transaction id is different */ + FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); + deposit2.transaction_id = deposit.transaction_id; + RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */ + FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); + (void) memcpy (&deposit2.merchant_pub, &deposit.merchant_pub, sizeof (deposit.merchant_pub)); + RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */ + FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); result = 0; drop: + if (NULL != wire) + json_decref (wire); if (NULL != rh) TALER_MINT_DB_free_reserve_history (rh); rh = NULL; -- cgit v1.2.3 From 293b4018d1270fa3edc9f893d6a80a78b5f091a7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Mon, 16 Mar 2015 18:19:05 +0100 Subject: fix documentation and minor issues in DB tools --- src/mint/taler-mint-dbinit.c | 74 +++++++++------ src/mint/taler-mint-reservemod.c | 193 ++++++++++++++++++++++++++------------- 2 files changed, 180 insertions(+), 87 deletions(-) diff --git a/src/mint/taler-mint-dbinit.c b/src/mint/taler-mint-dbinit.c index 8106b54c4..838f98e25 100644 --- a/src/mint/taler-mint-dbinit.c +++ b/src/mint/taler-mint-dbinit.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, If not, see */ /** - * @file taler-mint-dbinit.c + * @file mint/taler-mint-dbinit.c * @brief Create tables for the mint database. * @author Florian Dold */ @@ -24,74 +24,96 @@ #include "taler_util.h" #include "mint_db.h" -#define break_db_err(result) do { \ - GNUNET_break(0); \ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Database failure: %s\n", PQresultErrorMessage (result)); \ - PQclear (result); \ - } while (0) - +/** + * Mint directory with the keys. + */ static char *mint_base_dir; -static struct GNUNET_CONFIGURATION_Handle *cfg; -static PGconn *db_conn; -static char *TALER_MINT_db_connection_cfg_str; +/** + * Our configuration. + */ +static struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * Database connection handle. + */ +static PGconn *db_conn; /** - * The main function of the serve tool + * The main function of the database initialization tool. + * Used to initialize the Taler Mint's database. * * @param argc number of arguments from the command line * @param argv command line arguments * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"), + GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-dbinit OPTIONS"), {'d', "mint-dir", "DIR", "mint directory", 1, &GNUNET_GETOPT_set_filename, &mint_base_dir}, GNUNET_GETOPT_OPTION_END }; + char *db_connection_cfg_str; - if (GNUNET_GETOPT_run ("taler-mint-serve", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-dbinit", + options, + argc, argv) < 0) return 1; - GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-dbinit", "INFO", NULL)); - + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-mint-dbinit", + "INFO", + NULL)); if (NULL == mint_base_dir) { - fprintf (stderr, "Mint base directory not given.\n"); + fprintf (stderr, + "Mint base directory not given.\n"); return 1; } cfg = TALER_config_load (mint_base_dir); if (NULL == cfg) { - fprintf (stderr, "Can't load mint configuration.\n"); + fprintf (stderr, + "Failed to load mint configuration.\n"); return 1; } - if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "mint", "db", &TALER_MINT_db_connection_cfg_str)) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint", + "db", + &db_connection_cfg_str)) { - fprintf (stderr, "Configuration 'mint.db' not found.\n"); - return 42; + fprintf (stderr, + "Configuration 'mint.db' not found.\n"); + return 1; } - db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str); + db_conn = PQconnectdb (db_connection_cfg_str); if (CONNECTION_OK != PQstatus (db_conn)) { - fprintf (stderr, "Database connection failed: %s\n", PQerrorMessage (db_conn)); + fprintf (stderr, + "Database connection failed: %s\n", + PQerrorMessage (db_conn)); + free (db_connection_cfg_str); return 1; } + free (db_connection_cfg_str); if (GNUNET_OK != TALER_MINT_DB_create_tables (GNUNET_NO)) { - fprintf (stderr, "Failed to initialize database.\n"); + fprintf (stderr, + "Failed to initialize database.\n"); return 1; } - return 0; } + +/* end of taler-mint-dbinit.c */ diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index e7795e67e..e805cacc1 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -13,14 +13,12 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file taler-mint-reservemod.c - * @brief Modify reserves. + * @brief Modify reserves. Allows manipulation of reserve balances for testing. * @author Florian Dold * @author Benedikt Mueller */ - #include "platform.h" #include #include @@ -29,47 +27,74 @@ #include "mint_db.h" #include "db_pq.h" -char *mintdir; +/** + * Director of the mint, containing the keys. + */ +static char *mintdir; + +/** + * Public key of the reserve to manipulate. + */ static struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub; -struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * Handle to the mint's configuration + */ +static struct GNUNET_CONFIGURATION_Handle *cfg; +/** + * Database connection handle. + */ static PGconn *db_conn; - /** - * Create a new or add to existing reserve. - * Fails if currencies do not match. + * Create a new or add to existing reserve. Fails if currencies do + * not match. * * @param denom denomination to add - * - * @return ... + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on error */ static int reservemod_add (struct TALER_Amount denom) { PGresult *result; - { - const void *param_values[] = { reserve_pub }; - int param_lengths[] = {sizeof(struct GNUNET_CRYPTO_EddsaPublicKey)}; - int param_formats[] = {1}; - result = PQexecParams (db_conn, - "select balance_value, balance_fraction, balance_currency from reserves where reserve_pub=$1 limit 1;", - 1, NULL, (const char * const *) param_values, param_lengths, param_formats, 1); - } + const void *param_values[] = { + reserve_pub + }; + int param_lengths[] = { + sizeof(struct GNUNET_CRYPTO_EddsaPublicKey) + }; + int param_formats[] = { + 1 + }; + struct TALER_Amount old_denom; + struct TALER_Amount new_denom; + struct TALER_AmountNBO new_denom_nbo; + result = PQexecParams (db_conn, + "SELECT balance_value, balance_fraction, balance_currency" + " FROM reserves" + " WHERE reserve_pub=$1" + " LIMIT 1;", + 1, + NULL, + (const char * const *) param_values, + param_lengths, + param_formats, + 1); if (PGRES_TUPLES_OK != PQresultStatus (result)) { - fprintf (stderr, "Select failed: %s\n", PQresultErrorMessage (result)); + fprintf (stderr, + "Select failed: %s\n", + PQresultErrorMessage (result)); return GNUNET_SYSERR; } if (0 == PQntuples (result)) { struct GNUNET_TIME_AbsoluteNBO exnbo; - exnbo = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add ( GNUNET_TIME_absolute_get (), GNUNET_TIME_UNIT_YEARS)); - uint32_t value = htonl (denom.value); uint32_t fraction = htonl (denom.fraction); const void *param_values[] = { @@ -77,33 +102,53 @@ reservemod_add (struct TALER_Amount denom) &value, &fraction, denom.currency, - &exnbo}; - int param_lengths[] = {32, 4, 4, strlen(denom.currency), 8}; - int param_formats[] = {1, 1, 1, 1, 1}; + &exnbo + }; + int param_lengths[] = { + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey), + sizeof (uint32_t), + sizeof (uint32_t), + strlen (denom.currency), + sizeof (struct GNUNET_TIME_AbsoluteNBO) + }; + int param_formats[] = { + 1, 1, 1, 1, 1 + }; + + exnbo = GNUNET_TIME_absolute_hton (GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_YEARS)); result = PQexecParams (db_conn, - "insert into reserves (reserve_pub, balance_value, balance_fraction, balance_currency, " - " expiration_date )" - "values ($1,$2,$3,$4,$5);", - 5, NULL, (const char **) param_values, param_lengths, param_formats, 1); + "INSERT INTO reserves (reserve_pub, balance_value, balance_fraction, balance_currency, expiration_date)" + " VALUES ($1,$2,$3,$4,$5);", + 5, + NULL, + (const char **) param_values, + param_lengths, + param_formats, + 1); if (PGRES_COMMAND_OK != PQresultStatus (result)) { - fprintf (stderr, "Insert failed: %s\n", PQresultErrorMessage (result)); + fprintf (stderr, + "Insert failed: %s\n", + PQresultErrorMessage (result)); return GNUNET_SYSERR; } } else { - struct TALER_Amount old_denom; - struct TALER_Amount new_denom; - struct TALER_AmountNBO new_denom_nbo; - int param_lengths[] = {4, 4, 32}; - int param_formats[] = {1, 1, 1}; const void *param_values[] = { &new_denom_nbo.value, &new_denom_nbo.fraction, reserve_pub }; + int param_lengths[] = { + sizeof (new_denom_nbo.value), + sizeof (new_denom_nbo.fraction), + sizeof (struct GNUNET_CRYPTO_EddsaPublicKey) + }; + int param_formats[] = { + 1, 1, 1 + }; GNUNET_assert (GNUNET_OK == TALER_DB_extract_amount (result, 0, @@ -111,28 +156,36 @@ reservemod_add (struct TALER_Amount denom) "balance_fraction", "balance_currency", &old_denom)); - new_denom = TALER_amount_add (old_denom, denom); + new_denom = TALER_amount_add (old_denom, + denom); new_denom_nbo = TALER_amount_hton (new_denom); result = PQexecParams (db_conn, - "UPDATE reserves " - "SET balance_value = $1, balance_fraction = $2, " - " status_sig = NULL, status_sign_pub = NULL " - "WHERE reserve_pub = $3 ", - 3, NULL, (const char **) param_values, param_lengths, param_formats, 1); + "UPDATE reserves" + " SET balance_value = $1, balance_fraction = $2, status_sig = NULL, status_sign_pub = NULL" + " WHERE reserve_pub = $3;", + 3, + NULL, + (const char **) param_values, + param_lengths, + param_formats, + 1); if (PGRES_COMMAND_OK != PQresultStatus (result)) { - fprintf (stderr, "Update failed: %s\n", PQresultErrorMessage (result)); + fprintf (stderr, + "Update failed: %s\n", + PQresultErrorMessage (result)); return GNUNET_SYSERR; } - - if (0 != strcmp ("1", PQcmdTuples (result))) + /* FIXME: strcmp!? There must be an API that returns an int! */ + if (0 != strcmp ("1", + PQcmdTuples (result))) { - fprintf (stderr, "Update failed (updated '%s' tupes instead of '1')\n", + fprintf (stderr, + "Update failed (updated `%s' tupes instead of '1')\n", PQcmdTuples (result)); return GNUNET_SYSERR; } - } return GNUNET_OK; } @@ -151,7 +204,7 @@ main (int argc, char *const *argv) static char *reserve_pub_str; static char *add_str; static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"), + GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-reservemod OPTIONS"), {'d', "mint-dir", "DIR", "mint directory with keys to update", 1, &GNUNET_GETOPT_set_filename, &mintdir}, @@ -165,13 +218,19 @@ main (int argc, char *const *argv) }; char *TALER_MINT_db_connection_cfg_str; - GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keycheck", "WARNING", NULL)); + GNUNET_assert (GNUNET_OK == + GNUNET_log_setup ("taler-mint-reservemod", + "WARNING", + NULL)); - if (GNUNET_GETOPT_run ("taler-mint-keyup", options, argc, argv) < 0) + if (GNUNET_GETOPT_run ("taler-mint-keyup", + options, + argc, argv) < 0) return 1; if (NULL == mintdir) { - fprintf (stderr, "mint directory not given\n"); + fprintf (stderr, + "Mint directory not given\n"); return 1; } @@ -183,14 +242,15 @@ main (int argc, char *const *argv) reserve_pub, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))) { - fprintf (stderr, "reserve key invalid\n"); + fprintf (stderr, + "Parsing reserve key invalid\n"); return 1; } - cfg = TALER_config_load (mintdir); if (NULL == cfg) { - fprintf (stderr, "can't load mint configuration\n"); + fprintf (stderr, + "Failed to load mint configuration\n"); return 1; } if (GNUNET_OK != @@ -199,29 +259,40 @@ main (int argc, char *const *argv) "db", &TALER_MINT_db_connection_cfg_str)) { - fprintf (stderr, "db configuration string not found\n"); - return 42; + fprintf (stderr, + "Database configuration string not found\n"); + return 1; } db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str); if (CONNECTION_OK != PQstatus (db_conn)) { - fprintf (stderr, "db connection failed: %s\n", PQerrorMessage (db_conn)); + fprintf (stderr, + "Database connection failed: %s\n", + PQerrorMessage (db_conn)); return 1; } - if (NULL != add_str) { struct TALER_Amount add_value; - if (GNUNET_OK != TALER_string_to_amount (add_str, &add_value)) + + if (GNUNET_OK != + TALER_string_to_amount (add_str, + &add_value)) { - fprintf (stderr, "could not read value\n"); + fprintf (stderr, + "Failed to parse currency amount `%s'\n", + add_str); return 1; } - if (GNUNET_OK != reservemod_add (add_value)) + if (GNUNET_OK != + reservemod_add (add_value)) { - fprintf (stderr, "adding value failed\n"); + fprintf (stderr, + "Failed to update reserve.\n"); return 1; } } return 0; } + +/* end taler-mint-reservemod.c */ -- cgit v1.2.3 From 0119f629b3603e9635932b691fc31967ff085f7e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 10:48:12 +0100 Subject: move TALER_CONFIG_get_denom into util lib --- src/include/taler_util.h | 14 +++++ src/mint/taler-mint-keyup.c | 131 ++++++++++++++++++-------------------------- src/util/util.c | 28 ++++++++++ 3 files changed, 94 insertions(+), 79 deletions(-) diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 74feb037a..3569bd782 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -84,5 +84,19 @@ struct GNUNET_CONFIGURATION_Handle * TALER_config_load (const char *base_dir); +/** + * Obtain denomination amount from configuration file. + * + * @param section section of the configuration to access + * @param option option of the configuration to access + * @param denom[OUT] set to the amount found in configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +TALER_config_get_denom (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + const char *option, + struct TALER_Amount *denom); + #endif diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 1b388a20a..8a645b589 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -44,37 +44,38 @@ GNUNET_NETWORK_STRUCT_BEGIN /** - * + * Struct with all of the key information for a kind of coin. Hashed + * to generate a unique directory name per coin type. */ struct CoinTypeNBO { /** - * + * How long can the coin be spend? */ struct GNUNET_TIME_RelativeNBO duration_spend; /** - * + * How long can the coin be withdrawn (generated)? */ struct GNUNET_TIME_RelativeNBO duration_withdraw; /** - * + * What is the value of the coin? */ struct TALER_AmountNBO value; /** - * + * What is the fee charged for withdrawl? */ struct TALER_AmountNBO fee_withdraw; /** - * + * What is the fee charged for deposits? */ struct TALER_AmountNBO fee_deposit; /** - * + * What is the fee charged for melting? */ struct TALER_AmountNBO fee_refresh; }; @@ -171,63 +172,22 @@ static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub; static struct GNUNET_TIME_Absolute lookahead_sign_stamp; -/** - * - * - * @param section - * @param option - * @param denom - * @return - */ -static int -config_get_denom (const char *section, - const char *option, - struct TALER_Amount *denom) -{ - char *str; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (kcfg, - section, - option, - &str)) - return GNUNET_NO; - if (GNUNET_OK != TALER_string_to_amount (str, - denom)) - return GNUNET_SYSERR; - return GNUNET_OK; -} - /** + * Obtain the name of the directory we use to store signing + * keys created at time @a start. * - * - * @return + * @param start time at which we create the signing key + * @return name of the directory we should use, basically "$MINTDIR/$TIME/"; + * (valid until next call to this function) */ -static char * -get_signkey_dir () -{ - char *dir; - - GNUNET_asprintf (&dir, - "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, - mintdir); - return dir; -} - - -/** - * - * - * @param start - * @return - */ -static char * +static const char * get_signkey_file (struct GNUNET_TIME_Absolute start) { - char *dir; + static char dir[4096]; - GNUNET_asprintf (&dir, + GNUNET_snprintf (dir, + sizeof (dir), "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS DIR_SEPARATOR_STR "%llu", mintdir, (unsigned long long) start.abs_value_us); @@ -236,12 +196,12 @@ get_signkey_file (struct GNUNET_TIME_Absolute start) /** - * Hash the data defining the coin type. - * Exclude information that may not be the same for all - * instances of the coin type (i.e. the anchor, overlap). + * Hash the data defining the coin type. Exclude information that may + * not be the same for all instances of the coin type (i.e. the + * anchor, overlap). * - * @param p - * @param hash + * @param p coin parameters to convert to a hash + * @param hash[OUT] set to the hash matching @a p */ static void hash_coin_type (const struct CoinTypeParams *p, @@ -267,10 +227,17 @@ hash_coin_type (const struct CoinTypeParams *p, /** + * Obtain the name of the directory we should use to store coins of + * the given type. The directory name has the format + * "$MINTDIR/$VALUE/$HASH/" where "$VALUE" represents the value of the + * coin and "$HASH" encodes all of the coin's parameters, generating a + * unique string for each type of coin. Note that the "$HASH" + * includes neither the absolute creation time nor the key of the + * coin, thus the files in the subdirectory really just refer to the + * same type of coins, not the same coin. * - * - * @param p - * @return + * @param p coin parameters to convert to a directory name + * @return directory name (valid until next call to this function) */ static const char * get_cointype_dir (const struct CoinTypeParams *p) @@ -499,7 +466,9 @@ mint_keys_update_signkeys () } ROUND_TO_SECS (signkey_duration, rel_value_us); - signkey_dir = get_signkey_dir (); + GNUNET_asprintf (&signkey_dir, + "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, + mintdir); // make sure the directory exists if (GNUNET_OK != GNUNET_DISK_directory_create (signkey_dir)) @@ -516,7 +485,7 @@ mint_keys_update_signkeys () while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) { - char *skf; + const char *skf; skf = get_signkey_file (anchor); if (GNUNET_YES != @@ -607,9 +576,10 @@ get_cointype_params (const char *ct, rel_value_us); if (GNUNET_OK != - config_get_denom ("mint_denom_value", - ct, - ¶ms->value)) + TALER_config_get_denom (kcfg, + "mint_denom_value", + ct, + ¶ms->value)) { fprintf (stderr, "Value not given for coin type '%s'\n", @@ -618,9 +588,10 @@ get_cointype_params (const char *ct, } if (GNUNET_OK != - config_get_denom ("mint_denom_fee_withdraw", - ct, - ¶ms->fee_withdraw)) + TALER_config_get_denom (kcfg, + "mint_denom_fee_withdraw", + ct, + ¶ms->fee_withdraw)) { fprintf (stderr, "Withdraw fee not given for coin type '%s'\n", @@ -629,9 +600,10 @@ get_cointype_params (const char *ct, } if (GNUNET_OK != - config_get_denom ("mint_denom_fee_deposit", - ct, - ¶ms->fee_deposit)) + TALER_config_get_denom (kcfg, + "mint_denom_fee_deposit", + ct, + ¶ms->fee_deposit)) { fprintf (stderr, "Deposit fee not given for coin type '%s'\n", @@ -640,9 +612,10 @@ get_cointype_params (const char *ct, } if (GNUNET_OK != - config_get_denom ("mint_denom_fee_refresh", - ct, - ¶ms->fee_refresh)) + TALER_config_get_denom (kcfg, + "mint_denom_fee_refresh", + ct, + ¶ms->fee_refresh)) { fprintf (stderr, "Deposit fee not given for coin type '%s'\n", diff --git a/src/util/util.c b/src/util/util.c index f2ff01d0f..5c1e5eb9a 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -29,6 +29,34 @@ #include +/** + * Obtain denomination amount from configuration file. + * + * @param section section of the configuration to access + * @param option option of the configuration to access + * @param denom[OUT] set to the amount found in configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +int +TALER_config_get_denom (struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + const char *option, + struct TALER_Amount *denom) +{ + char *str; + + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + option, + &str)) + return GNUNET_NO; + if (GNUNET_OK != TALER_string_to_amount (str, + denom)) + return GNUNET_SYSERR; + return GNUNET_OK; +} + /** * Load configuration by parsing all configuration -- cgit v1.2.3 From 4eeaff13557c507061872e2346bfb53af6d51f1e Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 11:37:21 +0100 Subject: documentation, comments --- src/mint/taler-mint-keyup.c | 251 +++++++++++++++++++++++--------------------- src/util/amount.c | 46 +++++--- 2 files changed, 166 insertions(+), 131 deletions(-) diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 8a645b589..ac5f7b1d6 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -19,6 +19,7 @@ * using the mint's offline master key. * @author Florian Dold * @author Benedikt Mueller + * @author Christian Grothoff */ #include #include @@ -26,17 +27,20 @@ #include "key_io.h" /** - * FIXME: allow user to specify (within reason). - */ -#define RSA_KEYSIZE 2048 - -/** - * + * When generating filenames from a cryptographic hash, we do not use + * all 512 bits but cut off after this number of characters (in + * base32-encoding). Base32 is 5 bit per character, and given that we + * have very few coin types we hash, at 100 bits the chance of + * collision (by accident over tiny set -- birthday paradox does not + * apply here!) is negligible. */ #define HASH_CUTOFF 20 /** * Macro to round microseconds to seconds in GNUNET_TIME_* structs. + * + * @param name value to round + * @param field rel_value_us or abs_value_us */ #define ROUND_TO_SECS(name,us_field) name.us_field -= name.us_field % (1000 * 1000); @@ -78,55 +82,71 @@ struct CoinTypeNBO * What is the fee charged for melting? */ struct TALER_AmountNBO fee_refresh; + + /** + * Key size in NBO. + */ + uint32_t rsa_keysize; }; GNUNET_NETWORK_STRUCT_END /** - * + * Set of all of the parameters that chracterize a coin. */ struct CoinTypeParams { /** - * + * How long can the coin be spend? Should be significantly + * larger than @e duration_withdraw (i.e. years). */ struct GNUNET_TIME_Relative duration_spend; /** - * + * How long can the coin be withdrawn (generated)? Should be small + * enough to limit how many coins will be signed into existence with + * the same key, but large enough to still provide a reasonable + * anonymity set. */ struct GNUNET_TIME_Relative duration_withdraw; /** - * + * How much should coin creation (@e duration_withdraw) duration + * overlap with the next coin? Basically, the starting time of two + * coins is always @e duration_withdraw - @e duration_overlap apart. */ struct GNUNET_TIME_Relative duration_overlap; /** - * + * What is the value of the coin? */ struct TALER_Amount value; /** - * + * What is the fee charged for withdrawl? */ struct TALER_Amount fee_withdraw; /** - * + * What is the fee charged for deposits? */ struct TALER_Amount fee_deposit; /** - * + * What is the fee charged for melting? */ struct TALER_Amount fee_refresh; /** - * + * Time at which this coin is supposed to become valid. */ struct GNUNET_TIME_Absolute anchor; + + /** + * Length of the RSA key in bits. + */ + uint32_t rsa_keysize; }; @@ -172,7 +192,6 @@ static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub; static struct GNUNET_TIME_Absolute lookahead_sign_stamp; - /** * Obtain the name of the directory we use to store signing * keys created at time @a start. @@ -212,14 +231,13 @@ hash_coin_type (const struct CoinTypeParams *p, memset (&p_nbo, 0, sizeof (struct CoinTypeNBO)); - p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend); p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw); p_nbo.value = TALER_amount_hton (p->value); p_nbo.fee_withdraw = TALER_amount_hton (p->fee_withdraw); p_nbo.fee_deposit = TALER_amount_hton (p->fee_deposit); p_nbo.fee_refresh = TALER_amount_hton (p->fee_refresh); - + p_nbo.rsa_keysize = htonl (p->rsa_keysize); GNUNET_CRYPTO_hash (&p_nbo, sizeof (struct CoinTypeNBO), hash); @@ -246,18 +264,19 @@ get_cointype_dir (const struct CoinTypeParams *p) struct GNUNET_HashCode hash; char *hash_str; char *val_str; - unsigned int i; + size_t i; hash_coin_type (p, &hash); hash_str = GNUNET_STRINGS_data_to_string_alloc (&hash, sizeof (struct GNUNET_HashCode)); - GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1); GNUNET_assert (NULL != hash_str); + GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1); hash_str[HASH_CUTOFF] = 0; val_str = TALER_amount_to_string (p->value); for (i = 0; i < strlen (val_str); i++) - if (':' == val_str[i] || '.' == val_str[i]) + if ( (':' == val_str[i]) || + ('.' == val_str[i]) ) val_str[i] = '_'; GNUNET_snprintf (dir, @@ -267,23 +286,27 @@ get_cointype_dir (const struct CoinTypeParams *p) val_str, hash_str); GNUNET_free (hash_str); + GNUNET_free (val_str); return dir; } /** + * Obtain the name of the file we would use to store the key + * information for a coin of the given type @a p and validity + * start time @a start * - * - * @param p - * @param start - * @return + * @param p parameters for the coin + * @param start when would the coin begin to be issued + * @return name of the file to use for this coin + * (valid until next call to this function) */ static const char * -get_cointype_file (struct CoinTypeParams *p, +get_cointype_file (const struct CoinTypeParams *p, struct GNUNET_TIME_Absolute start) { - const char *dir; static char filename[4096]; + const char *dir; dir = get_cointype_dir (p); GNUNET_snprintf (filename, @@ -296,13 +319,15 @@ get_cointype_file (struct CoinTypeParams *p, /** - * Get the latest key file from the past. + * Get the latest key file from a past run of the key generation + * tool. Used to calculate the starting time for the keys we + * generate during this invocation. * - * @param cls closure + * @param cls closure, a `struct GNUNET_TIME_Absolute *`, updated + * to contain the highest timestamp (below #now) + * that was found * @param filename complete filename (absolute path) - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! + * @return #GNUNET_OK (to continue to iterate) */ static int get_anchor_iter (void *cls, @@ -317,31 +342,28 @@ get_anchor_iter (void *cls, stamp.abs_value_us = strtol (base, &end, 10); - if ((NULL == end) || (0 != *end)) { fprintf(stderr, - "Ignoring unexpected file '%s'.\n", + "Ignoring unexpected file `%s'.\n", filename); return GNUNET_OK; } - - // TODO: check if it's actually a valid key file - - if ( (stamp.abs_value_us <= now.abs_value_us) && - ( stamp.abs_value_us > anchor->abs_value_us) ) - *anchor = stamp; - + // TODO: check if it's actually a valid key file? + if (stamp.abs_value_us <= now.abs_value_us) + *anchor = GNUNET_TIME_absolute_max (stamp, + *anchor); return GNUNET_OK; } /** * Get the timestamp where the first new key should be generated. - * Relies on correctly named key files. + * Relies on correctly named key files (as we do not parse them, + * but just look at the filenames to "guess" at their contents). * - * @param dir directory with the signed stuff - * @param duration how long is one key valid? + * @param dir directory that should contain the existing keys + * @param duration how long is one key valid (for signing)? * @param overlap what's the overlap between the keys validity period? * @param[out] anchor the timestamp where the first new key should be generated */ @@ -354,15 +376,14 @@ get_anchor (const char *dir, GNUNET_assert (0 == duration.rel_value_us % 1000000); GNUNET_assert (0 == overlap.rel_value_us % 1000000); if (GNUNET_YES != - GNUNET_DISK_directory_test (dir, GNUNET_YES)) + GNUNET_DISK_directory_test (dir, + GNUNET_YES)) { *anchor = now; - fprintf (stderr, - "Cannot look for anchor (%s)\n", - dir); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No existing keys found, starting with fresh key set.\n"); return; } - *anchor = GNUNET_TIME_UNIT_ZERO_ABS; if (-1 == GNUNET_DISK_directory_scan (dir, @@ -370,23 +391,30 @@ get_anchor (const char *dir, anchor)) { *anchor = now; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No existing keys found, starting with fresh key set.\n"); return; } + /* FIXME: this check is a bit dubious, as 'now' + may be way into the future if we want to generate + many keys... */ if ((GNUNET_TIME_absolute_add (*anchor, duration)).abs_value_us < now.abs_value_us) { - // there's no good anchor, start from now - // (existing keys are too old) + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Existing keys are way too old, starting with fresh key set.\n"); *anchor = now; } - else if (anchor->abs_value_us != now.abs_value_us) + else if (anchor->abs_value_us != now.abs_value_us) // Also odd... { - // we have a good anchor - *anchor = GNUNET_TIME_absolute_add (*anchor, duration); - *anchor = GNUNET_TIME_absolute_subtract (*anchor, overlap); + /* Real starting time is the last start time + duration - overlap */ + *anchor = GNUNET_TIME_absolute_add (*anchor, + duration); + *anchor = GNUNET_TIME_absolute_subtract (*anchor, + overlap); } - // anchor is now the stamp where we need to create a new key + /* anchor is now the stamp where we need to create a new key */ } @@ -395,7 +423,7 @@ get_anchor (const char *dir, * * @param start * @param duration - * @param pi + * @param pi[OUT] */ static void create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, @@ -431,21 +459,7 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, /** * * - * @param signkey_filename - * @return - */ -static int -check_signkey_valid (const char *signkey_filename) -{ - // FIXME: do real checks - return GNUNET_OK; -} - - -/** - * - * - * @return + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int mint_keys_update_signkeys () @@ -513,28 +527,27 @@ mint_keys_update_signkeys () return GNUNET_SYSERR; } } - else if (GNUNET_OK != check_signkey_valid (skf)) - { - return GNUNET_SYSERR; - } - anchor = GNUNET_TIME_absolute_add (anchor, signkey_duration); + anchor = GNUNET_TIME_absolute_add (anchor, + signkey_duration); } return GNUNET_OK; } /** + * Parse configuration for coin type parameters. Also determines + * our anchor by looking at the existing coins of the same type. * - * - * @param ct - * @param params - * @return + * @param ct section in the configuration file giving the coin type parameters + * @param params[OUT] set to the coin parameters from the configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR if the configuration is invalid */ static int get_cointype_params (const char *ct, struct CoinTypeParams *params) { const char *dir; + unsigned long long rsa_keysize; if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, @@ -560,7 +573,8 @@ get_cointype_params (const char *ct, ct); return GNUNET_SYSERR; } - ROUND_TO_SECS (params->duration_spend, rel_value_us); + ROUND_TO_SECS (params->duration_spend, + rel_value_us); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_overlap", @@ -574,7 +588,26 @@ get_cointype_params (const char *ct, } ROUND_TO_SECS (params->duration_overlap, rel_value_us); - + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (kcfg, + "mint_denom_rsa_keysize", + ct, + &rsa_keysize)) + { + fprintf (stderr, + "RSA keysize not given for coin type '%s'\n", + ct); + return GNUNET_SYSERR; + } + if ( (rsa_keysize > 4 * 2048) || + (rsa_keysize < 1024) ) + { + fprintf (stderr, + "Given RSA keysize %llu outside of permitted range\n", + rsa_keysize); + return GNUNET_SYSERR; + } + params->rsa_keysize = (unsigned int) rsa_keysize; if (GNUNET_OK != TALER_config_get_denom (kcfg, "mint_denom_value", @@ -586,7 +619,6 @@ get_cointype_params (const char *ct, ct); return GNUNET_SYSERR; } - if (GNUNET_OK != TALER_config_get_denom (kcfg, "mint_denom_fee_withdraw", @@ -598,7 +630,6 @@ get_cointype_params (const char *ct, ct); return GNUNET_SYSERR; } - if (GNUNET_OK != TALER_config_get_denom (kcfg, "mint_denom_fee_deposit", @@ -610,7 +641,6 @@ get_cointype_params (const char *ct, ct); return GNUNET_SYSERR; } - if (GNUNET_OK != TALER_config_get_denom (kcfg, "mint_denom_fee_refresh", @@ -624,22 +654,29 @@ get_cointype_params (const char *ct, } dir = get_cointype_dir (params); - get_anchor (dir, params->duration_spend, params->duration_overlap, ¶ms->anchor); + get_anchor (dir, + params->duration_spend, + params->duration_overlap, + ¶ms->anchor); return GNUNET_OK; } /** + * Initialize the private and public key information structure for + * signing coins into existence. Generates the private signing key + * and signes it together with the coin's meta data using the master + * signing key. * - * - * @param params - * @param dki + * @param params parameters used to initialize the @a dki + * @param dki[OUT] initialized according to @a params */ static void -create_denomkey_issue (struct CoinTypeParams *params, +create_denomkey_issue (const struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssuePriv *dki) { - GNUNET_assert (NULL != (dki->denom_priv = GNUNET_CRYPTO_rsa_private_key_create (RSA_KEYSIZE))); + GNUNET_assert (NULL != + (dki->denom_priv = GNUNET_CRYPTO_rsa_private_key_create (params->rsa_keysize))); dki->denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv); GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, &dki->issue.denom_hash); @@ -660,7 +697,6 @@ create_denomkey_issue (struct CoinTypeParams *params, dki->issue.purpose.size = htonl (sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.purpose)); - GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_eddsa_sign (master_priv, &dki->issue.purpose, @@ -669,26 +705,11 @@ create_denomkey_issue (struct CoinTypeParams *params, /** + * Generate new coin signing keys for the coin type of the given @a + * coin_alias. * - * - * @param filename - * @param params - * @return - */ -static int -check_cointype_valid (const char *filename, - struct CoinTypeParams *params) -{ - // FIXME: add real checks - return GNUNET_OK; -} - - -/** - * - * - * @param coin_alias - * @return + * @param coin_alias name of the coin's section in the configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ static int mint_keys_update_cointype (const char *coin_alias) @@ -732,10 +753,6 @@ mint_keys_update_cointype (const char *coin_alias) return GNUNET_SYSERR; } } - else if (GNUNET_OK != check_cointype_valid (dkf, &p)) - { - return GNUNET_SYSERR; - } p.anchor = GNUNET_TIME_absolute_add (p.anchor, p.duration_spend); p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, p.duration_overlap); } diff --git a/src/util/amount.c b/src/util/amount.c index 0b77de82b..b3e3b4217 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -30,8 +30,14 @@ #include "taler_util.h" #include +/** + * + */ #define AMOUNT_FRAC_BASE 1000000 +/** + * + */ #define AMOUNT_FRAC_LEN 6 @@ -47,34 +53,39 @@ int TALER_string_to_amount (const char *str, struct TALER_Amount *denom) { - unsigned int i; // pos in str + size_t i; // pos in str int n; // number tmp - unsigned int c; // currency pos + size_t c; // currency pos uint32_t b; // base for suffix - memset (denom, 0, sizeof (struct TALER_Amount)); - - i = n = c = 0; + memset (denom, + 0, + sizeof (struct TALER_Amount)); + i = 0; while (isspace(str[i])) i++; if (0 == str[i]) { - printf("null before currency\n"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "null before currency\n"); return GNUNET_SYSERR; } + c = 0; while (str[i] != ':') { if (0 == str[i]) { - printf("null before colon"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "null before colon"); return GNUNET_SYSERR; } if (c > 3) { - printf("currency too long\n"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "currency too long\n"); return GNUNET_SYSERR; } denom->currency[c] = str[i]; @@ -87,7 +98,8 @@ TALER_string_to_amount (const char *str, if (0 == str[i]) { - printf("null before value\n"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "null before value\n"); return GNUNET_SYSERR; } @@ -100,7 +112,10 @@ TALER_string_to_amount (const char *str, n = str[i] - '0'; if (n < 0 || n > 9) { - printf("invalid character '%c' before comma at %u\n", (char) n, i); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "invalid character '%c' before comma at %u\n", + (char) n, + i); return GNUNET_SYSERR; } denom->value = (denom->value * 10) + n; @@ -112,7 +127,8 @@ TALER_string_to_amount (const char *str, if (0 == str[i]) { - printf("null after dot"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "null after dot"); return GNUNET_SYSERR; } @@ -121,9 +137,10 @@ TALER_string_to_amount (const char *str, while (0 != str[i]) { n = str[i] - '0'; - if (b == 0 || n < 0 || n > 9) + if ( (0 == b) || (n < 0) || (n > 9) ) { - printf("error after comma"); + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "error after comma"); return GNUNET_SYSERR; } denom->fraction += n * b; @@ -293,7 +310,8 @@ TALER_amount_add (struct TALER_Amount a1, struct TALER_Amount TALER_amount_normalize (struct TALER_Amount amount) { - while (amount.value != UINT32_MAX && amount.fraction >= AMOUNT_FRAC_BASE) + while ( (amount.value != UINT32_MAX) && + (amount.fraction >= AMOUNT_FRAC_BASE) ) { amount.fraction -= AMOUNT_FRAC_BASE; amount.value += 1; -- cgit v1.2.3 From 2018a6b7138ac9bee21066c870f5de0f8bf9e285 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 12:17:42 +0100 Subject: use existing log functions more --- src/mint/taler-mint-keyup.c | 96 ++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index ac5f7b1d6..4d063aeb4 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -419,11 +419,12 @@ get_anchor (const char *dir, /** + * Create a mint signing key (for signing mint messages, not for coins) + * and assert its correctness by signing it with the master key. * - * - * @param start - * @param duration - * @param pi[OUT] + * @param start start time of the validity period for the key + * @param duration how long should the key be valid + * @param pi[OUT] set to the signing key information */ static void create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, @@ -440,10 +441,8 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, issue->start = GNUNET_TIME_absolute_hton (start); issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, duration)); - GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv, &issue->signkey_pub); - issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY); issue->purpose.size = htonl (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, @@ -474,8 +473,9 @@ mint_keys_update_signkeys () "signkey_duration", &signkey_duration)) { - fprintf (stderr, - "Cannot read config value mint_keys.signkey_duration\n"); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "signkey_duration"); return GNUNET_SYSERR; } ROUND_TO_SECS (signkey_duration, @@ -549,15 +549,16 @@ get_cointype_params (const char *ct, const char *dir; unsigned long long rsa_keysize; + /* FIXME: is 'ct' option or section name? */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, "mint_denom_duration_withdraw", ct, ¶ms->duration_withdraw)) { - fprintf (stderr, - "Withdraw duration not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_duration_withdraw"); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_withdraw, @@ -568,9 +569,9 @@ get_cointype_params (const char *ct, ct, ¶ms->duration_spend)) { - fprintf (stderr, - "Spend duration not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_duration_spend"); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_spend, @@ -581,9 +582,9 @@ get_cointype_params (const char *ct, ct, ¶ms->duration_overlap)) { - fprintf (stderr, - "Overlap duration not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_duration_overlap"); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_overlap, @@ -594,9 +595,9 @@ get_cointype_params (const char *ct, ct, &rsa_keysize)) { - fprintf (stderr, - "RSA keysize not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_rsa_keysize"); return GNUNET_SYSERR; } if ( (rsa_keysize > 4 * 2048) || @@ -614,9 +615,9 @@ get_cointype_params (const char *ct, ct, ¶ms->value)) { - fprintf (stderr, - "Value not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_value"); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -625,9 +626,9 @@ get_cointype_params (const char *ct, ct, ¶ms->fee_withdraw)) { - fprintf (stderr, - "Withdraw fee not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_fee_withdraw"); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -636,9 +637,9 @@ get_cointype_params (const char *ct, ct, ¶ms->fee_deposit)) { - fprintf (stderr, - "Deposit fee not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_fee_deposit"); return GNUNET_SYSERR; } if (GNUNET_OK != @@ -647,9 +648,9 @@ get_cointype_params (const char *ct, ct, ¶ms->fee_refresh)) { - fprintf (stderr, - "Deposit fee not given for coin type '%s'\n", - ct); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + ct, + "mint_denom_fee_refresh"); return GNUNET_SYSERR; } @@ -763,7 +764,7 @@ mint_keys_update_cointype (const char *coin_alias) /** * * - * @return + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int mint_keys_update_denomkeys () @@ -778,8 +779,9 @@ mint_keys_update_denomkeys () "coin_types", &coin_types)) { - fprintf (stderr, - "mint_keys.coin_types not in configuration\n"); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "coin_types"); return GNUNET_SYSERR; } @@ -800,7 +802,7 @@ mint_keys_update_denomkeys () /** * - * @return + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int mint_keys_update () @@ -814,14 +816,17 @@ mint_keys_update () "lookahead_sign", &lookahead_sign)) { - fprintf (stderr, - "mint_keys.lookahead_sign not found\n"); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "lookahead_sign"); return GNUNET_SYSERR; } if (0 == lookahead_sign.rel_value_us) { - fprintf (stderr, - "mint_keys.lookahead_sign must not be zero\n"); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "lookahead_sign", + _("must not be zero")); return GNUNET_SYSERR; } ROUND_TO_SECS (lookahead_sign, @@ -932,8 +937,9 @@ main (int argc, char *const *argv) &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) { - fprintf (stderr, - "Master public key missing in configuration (mint.master_pub)\n"); + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "master_pub"); return 1; } if (0 != @@ -941,8 +947,10 @@ main (int argc, char *const *argv) &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) { - fprintf (stderr, - "Mismatch between key from mint configuration and master private key file from command line.\n"); + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "mint", + "master_pub", + _("does not match with private key")); return 1; } } -- cgit v1.2.3 From 93d1fe6e6807a68b833f6c666e67d86958818e19 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 12:27:26 +0100 Subject: simplify --- src/mint/taler-mint-keyup.c | 88 ++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 50 deletions(-) diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 4d063aeb4..9c42e1489 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -800,48 +800,6 @@ mint_keys_update_denomkeys () } -/** - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -mint_keys_update () -{ - int ret; - struct GNUNET_TIME_Relative lookahead_sign; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "mint_keys", - "lookahead_sign", - &lookahead_sign)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint_keys", - "lookahead_sign"); - return GNUNET_SYSERR; - } - if (0 == lookahead_sign.rel_value_us) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "mint_keys", - "lookahead_sign", - _("must not be zero")); - return GNUNET_SYSERR; - } - ROUND_TO_SECS (lookahead_sign, - rel_value_us); - lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, - lookahead_sign); - - ret = mint_keys_update_signkeys (); - if (GNUNET_OK != ret) - return GNUNET_SYSERR; - - return mint_keys_update_denomkeys (); -} - - /** * The main function of the keyup tool * @@ -850,7 +808,8 @@ mint_keys_update () * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"), @@ -865,6 +824,7 @@ main (int argc, char *const *argv) &GNUNET_GETOPT_set_string, &pretend_time_str}, GNUNET_GETOPT_OPTION_END }; + struct GNUNET_TIME_Relative lookahead_sign; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keyup", @@ -878,10 +838,9 @@ main (int argc, char *const *argv) if (NULL == mintdir) { fprintf (stderr, - "mint directory not given\n"); + "Mint directory not given\n"); return 1; } - if (NULL != pretend_time_str) { if (GNUNET_OK != @@ -889,7 +848,8 @@ main (int argc, char *const *argv) &now)) { fprintf (stderr, - "timestamp invalid\n"); + "timestamp `%s' invalid\n", + pretend_time_str); return 1; } } @@ -906,11 +866,10 @@ main (int argc, char *const *argv) "Failed to load mint configuration\n"); return 1; } - if (NULL == masterkeyfile) { fprintf (stderr, - "master key file not given\n"); + "Master key file not given\n"); return 1; } master_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile); @@ -926,7 +885,7 @@ main (int argc, char *const *argv) GNUNET_CRYPTO_eddsa_key_get_public (master_priv, master_pub); - // check if key from file matches the one from the configuration + /* check if key from file matches the one from the configuration */ { struct GNUNET_CRYPTO_EddsaPublicKey master_pub_from_cfg; @@ -955,7 +914,36 @@ main (int argc, char *const *argv) } } - if (GNUNET_OK != mint_keys_update ()) + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_time (kcfg, + "mint_keys", + "lookahead_sign", + &lookahead_sign)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "lookahead_sign"); + return GNUNET_SYSERR; + } + if (0 == lookahead_sign.rel_value_us) + { + GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, + "mint_keys", + "lookahead_sign", + _("must not be zero")); + return GNUNET_SYSERR; + } + ROUND_TO_SECS (lookahead_sign, + rel_value_us); + lookahead_sign_stamp = GNUNET_TIME_absolute_add (now, + lookahead_sign); + + + /* finally, do actual work */ + if (GNUNET_OK != mint_keys_update_signkeys ()) + return 1; + + if (GNUNET_OK != mint_keys_update_denomkeys ()) return 1; return 0; } -- cgit v1.2.3 From b314f07431e28e4d44fac66f667ad3589f0a5dad Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 14:34:55 +0100 Subject: make keyup configuration structure more logical --- contrib/mint-template/config/mint-keyup.conf | 105 +++++++++++---------------- src/mint/taler-mint-keyup.c | 86 +++++++++++----------- 2 files changed, 85 insertions(+), 106 deletions(-) diff --git a/contrib/mint-template/config/mint-keyup.conf b/contrib/mint-template/config/mint-keyup.conf index 1542d1a63..b96ae4b95 100644 --- a/contrib/mint-template/config/mint-keyup.conf +++ b/contrib/mint-template/config/mint-keyup.conf @@ -15,65 +15,46 @@ lookahead_provide = 4 weeks 1 day coin_types = default_eur_ct_10 default_eur_5 default_eur_10 default_eur_1000 - -[mint_denom_duration_overlap] -default_eur_ct_10 = 5 minutes -default_eur_5 = 5 minutes -default_eur_10 = 5 minutes -default_eur_1000 = 5 minutes - - - -[mint_denom_value] -default_eur_ct_10 = EUR:0.10 -default_eur_5 = EUR:5 -default_eur_10 = EUR:10 -default_eur_1000 = EUR:1000 - - - -[mint_denom_duration_withdraw] -default_eur_ct_10 = 7 days -default_eur_5 = 7 days -default_eur_10 = 7 days -default_eur_1000 = 1 day - - - -[mint_denom_duration_spend] -default_eur_ct_10 = 30 days -default_eur_5 = 30 days -default_eur_10 = 30 days -default_eur_1000 = 30 day - - - -[mint_denom_fee_withdraw] -default_eur_ct_10 = EUR:0.01 -default_eur_5 = EUR:0.01 -default_eur_10 = EUR:0.01 -default_eur_1000 = EUR:0.01 - - -[mint_denom_fee_deposit] -default_eur_ct_10 = EUR:0.01 -default_eur_5 = EUR:0.01 -default_eur_10 = EUR:0.01 -default_eur_1000 = EUR:0.01 - - - -[mint_denom_fee_refresh] -default_eur_ct_10 = EUR:0.01 -default_eur_5 = EUR:0.01 -default_eur_10 = EUR:0.01 -default_eur_1000 = EUR:0.01 - - - -[mint_denom_kappa] -default_eur_ct_10 = 3 -default_eur_5 = 3 -default_eur_10 = 3 -default_eur_1000 = 5 - +[default_eur_ct_10] +value = EUR:0.10 +duration_overlap = 5 minutes +duration_withdraw = 7 days +duration_spend = 2 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.01 +rsa_keysize = 1024 +kappa = 3 + +[default_eur_5] +value = EUR:5 +duration_overlap = 5 minutes +duration_withdraw = 7 days +duration_spend = 2 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.01 +rsa_keysize = 1024 +kappa = 3 + +[default_eur_10] +value = EUR:10 +duration_overlap = 5 minutes +duration_withdraw = 7 days +duration_spend = 2 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.01 +rsa_keysize = 1024 +kappa = 3 + +[default_eur_1000] +value = EUR:1000 +duration_overlap = 5 minutes +duration_withdraw = 7 days +duration_spend = 2 years +fee_withdraw = EUR:0.01 +fee_deposit = EUR:0.01 +fee_refresh = EUR:0.01 +rsa_keysize = 2048 +kappa = 5 diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 9c42e1489..222e0f4d7 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -321,7 +321,9 @@ get_cointype_file (const struct CoinTypeParams *p, /** * Get the latest key file from a past run of the key generation * tool. Used to calculate the starting time for the keys we - * generate during this invocation. + * generate during this invocation. This function is used to + * handle both signing keys and coin keys, as in both cases + * the filenames correspond to the timestamps we need. * * @param cls closure, a `struct GNUNET_TIME_Absolute *`, updated * to contain the highest timestamp (below #now) @@ -349,7 +351,6 @@ get_anchor_iter (void *cls, filename); return GNUNET_OK; } - // TODO: check if it's actually a valid key file? if (stamp.abs_value_us <= now.abs_value_us) *anchor = GNUNET_TIME_absolute_max (stamp, *anchor); @@ -456,7 +457,8 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, /** - * + * Generate signing keys starting from the last key found to + * the lookahead time. * * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ @@ -483,7 +485,7 @@ mint_keys_update_signkeys () GNUNET_asprintf (&signkey_dir, "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, mintdir); - // make sure the directory exists + /* make sure the directory exists */ if (GNUNET_OK != GNUNET_DISK_directory_create (signkey_dir)) { @@ -494,38 +496,35 @@ mint_keys_update_signkeys () get_anchor (signkey_dir, signkey_duration, - GNUNET_TIME_UNIT_ZERO, + GNUNET_TIME_UNIT_ZERO /* no overlap for signing keys */, &anchor); while (anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) { const char *skf; + struct TALER_MINT_SignKeyIssuePriv signkey_issue; + ssize_t nwrite; skf = get_signkey_file (anchor); - if (GNUNET_YES != - GNUNET_DISK_file_test (skf)) + GNUNET_break (GNUNET_YES != + GNUNET_DISK_file_test (skf)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Generating signing key for %s.\n", + GNUNET_STRINGS_absolute_time_to_string (anchor)); + create_signkey_issue_priv (anchor, + signkey_duration, + &signkey_issue); + nwrite = GNUNET_DISK_fn_write (skf, + &signkey_issue, + sizeof (struct TALER_MINT_SignKeyIssue), + GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ); + if (nwrite != sizeof (struct TALER_MINT_SignKeyIssue)) { - struct TALER_MINT_SignKeyIssuePriv signkey_issue; - ssize_t nwrite; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Generating signing key for %s.\n", - GNUNET_STRINGS_absolute_time_to_string (anchor)); - create_signkey_issue_priv (anchor, - signkey_duration, - &signkey_issue); - nwrite = GNUNET_DISK_fn_write (skf, - &signkey_issue, - sizeof (struct TALER_MINT_SignKeyIssue), - GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ); - if (nwrite != sizeof (struct TALER_MINT_SignKeyIssue)) - { - fprintf (stderr, - "Failed to write to file `%s': %s\n", - skf, - STRERROR (errno)); - return GNUNET_SYSERR; - } + fprintf (stderr, + "Failed to write to file `%s': %s\n", + skf, + STRERROR (errno)); + return GNUNET_SYSERR; } anchor = GNUNET_TIME_absolute_add (anchor, signkey_duration); @@ -549,37 +548,36 @@ get_cointype_params (const char *ct, const char *dir; unsigned long long rsa_keysize; - /* FIXME: is 'ct' option or section name? */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, - "mint_denom_duration_withdraw", ct, + "duration_withdraw", ¶ms->duration_withdraw)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_duration_withdraw"); + "duration_withdraw"); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_withdraw, rel_value_us); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, - "mint_denom_duration_spend", ct, + "duration_spend", ¶ms->duration_spend)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_duration_spend"); + "duration_spend"); return GNUNET_SYSERR; } ROUND_TO_SECS (params->duration_spend, rel_value_us); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (kcfg, - "mint_denom_duration_overlap", ct, + "duration_overlap", ¶ms->duration_overlap)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, @@ -591,13 +589,13 @@ get_cointype_params (const char *ct, rel_value_us); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (kcfg, - "mint_denom_rsa_keysize", ct, + "rsa_keysize", &rsa_keysize)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_rsa_keysize"); + "rsa_keysize"); return GNUNET_SYSERR; } if ( (rsa_keysize > 4 * 2048) || @@ -611,46 +609,46 @@ get_cointype_params (const char *ct, params->rsa_keysize = (unsigned int) rsa_keysize; if (GNUNET_OK != TALER_config_get_denom (kcfg, - "mint_denom_value", ct, + "value", ¶ms->value)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_value"); + "value"); return GNUNET_SYSERR; } if (GNUNET_OK != TALER_config_get_denom (kcfg, - "mint_denom_fee_withdraw", ct, + "fee_withdraw", ¶ms->fee_withdraw)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_fee_withdraw"); + "fee_withdraw"); return GNUNET_SYSERR; } if (GNUNET_OK != TALER_config_get_denom (kcfg, - "mint_denom_fee_deposit", ct, + "fee_deposit", ¶ms->fee_deposit)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_fee_deposit"); + "fee_deposit"); return GNUNET_SYSERR; } if (GNUNET_OK != TALER_config_get_denom (kcfg, - "mint_denom_fee_refresh", ct, + "fee_refresh", ¶ms->fee_refresh)) { GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, ct, - "mint_denom_fee_refresh"); + "fee_refresh"); return GNUNET_SYSERR; } -- cgit v1.2.3 From e0ae4e12905e247c8325ba50cd2e9d4f8231a54d Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 14:45:31 +0100 Subject: conclude taler-mint-keyup initial review --- contrib/mint-template/config/mint-keyup.conf | 15 ++-- src/mint/taler-mint-keyup.c | 127 +++++++++++++-------------- 2 files changed, 69 insertions(+), 73 deletions(-) diff --git a/contrib/mint-template/config/mint-keyup.conf b/contrib/mint-template/config/mint-keyup.conf index b96ae4b95..9091c6c97 100644 --- a/contrib/mint-template/config/mint-keyup.conf +++ b/contrib/mint-template/config/mint-keyup.conf @@ -11,11 +11,12 @@ lookahead_sign = 32 weeks 1 day # ahead of time? lookahead_provide = 4 weeks 1 day -# what coin types do we have available? -coin_types = default_eur_ct_10 default_eur_5 default_eur_10 default_eur_1000 - -[default_eur_ct_10] +# Coin definitions are detected because the section +# name begins with "coin_". The rest of the +# name is free, but of course following the convention +# of "coin_$CURRENCY[_$SUBUNIT]_$VALUE" make sense. +[coin_eur_ct_10] value = EUR:0.10 duration_overlap = 5 minutes duration_withdraw = 7 days @@ -26,7 +27,7 @@ fee_refresh = EUR:0.01 rsa_keysize = 1024 kappa = 3 -[default_eur_5] +[coin_eur_5] value = EUR:5 duration_overlap = 5 minutes duration_withdraw = 7 days @@ -37,7 +38,7 @@ fee_refresh = EUR:0.01 rsa_keysize = 1024 kappa = 3 -[default_eur_10] +[coin_eur_10] value = EUR:10 duration_overlap = 5 minutes duration_withdraw = 7 days @@ -48,7 +49,7 @@ fee_refresh = EUR:0.01 rsa_keysize = 1024 kappa = 3 -[default_eur_1000] +[coin_eur_1000] value = EUR:1000 duration_overlap = 5 minutes duration_withdraw = 7 days diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 222e0f4d7..33bb87249 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -707,99 +707,94 @@ create_denomkey_issue (const struct CoinTypeParams *params, * Generate new coin signing keys for the coin type of the given @a * coin_alias. * + * @param cls a `int *`, to be set to #GNUNET_SYSERR on failure * @param coin_alias name of the coin's section in the configuration - * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ -static int -mint_keys_update_cointype (const char *coin_alias) +static void +mint_keys_update_cointype (void *cls, + const char *coin_alias) { + int *ret = cls; struct CoinTypeParams p; - const char *cointype_dir; + const char *dkf; + struct TALER_MINT_DenomKeyIssuePriv denomkey_issue; - if (GNUNET_OK != get_cointype_params (coin_alias, &p)) - return GNUNET_SYSERR; - - cointype_dir = get_cointype_dir (&p); - if (GNUNET_OK != GNUNET_DISK_directory_create (cointype_dir)) - return GNUNET_SYSERR; + if (0 != strncasecmp (coin_alias, + "coin_", + strlen ("coin_"))) + return; /* not a coin definition */ + if (GNUNET_OK != + get_cointype_params (coin_alias, + &p)) + { + *ret = GNUNET_SYSERR; + return; + } + if (GNUNET_OK != + GNUNET_DISK_directory_create (get_cointype_dir (&p))) + { + *ret = GNUNET_SYSERR; + return; + } while (p.anchor.abs_value_us < lookahead_sign_stamp.abs_value_us) { - const char *dkf; - - dkf = get_cointype_file (&p, p.anchor); - - if (GNUNET_YES != GNUNET_DISK_file_test (dkf)) + dkf = get_cointype_file (&p, + p.anchor); + GNUNET_break (GNUNET_YES != GNUNET_DISK_file_test (dkf)); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Generating denomination key for type `%s', start %s at %s\n", + coin_alias, + GNUNET_STRINGS_absolute_time_to_string (p.anchor), + dkf); + create_denomkey_issue (&p, + &denomkey_issue); + if (GNUNET_OK != + TALER_MINT_write_denom_key (dkf, + &denomkey_issue)) { - struct TALER_MINT_DenomKeyIssuePriv denomkey_issue; - int ret; - - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Generating denomination key for type '%s', start %s at %s\n", - coin_alias, - GNUNET_STRINGS_absolute_time_to_string (p.anchor), - dkf); - create_denomkey_issue (&p, - &denomkey_issue); - ret = TALER_MINT_write_denom_key (dkf, - &denomkey_issue); + fprintf (stderr, + "Failed to write denomination key information to file `%s'.\n", + dkf); + *ret = GNUNET_SYSERR; GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); - if (GNUNET_OK != ret) - { - fprintf (stderr, - "Failed to write to file `%s'\n", - dkf); - return GNUNET_SYSERR; - } + return; } - p.anchor = GNUNET_TIME_absolute_add (p.anchor, p.duration_spend); - p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, p.duration_overlap); + GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); + p.anchor = GNUNET_TIME_absolute_add (p.anchor, + p.duration_spend); + p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, + p.duration_overlap); } - return GNUNET_OK; } /** - * + * Update all of the denomination keys of the mint. * * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ static int mint_keys_update_denomkeys () { - char *coin_types; - char *ct; - char *tok_ctx; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (kcfg, - "mint_keys", - "coin_types", - &coin_types)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint_keys", - "coin_types"); - return GNUNET_SYSERR; - } + int ok; - for (ct = strtok_r (coin_types, " ", &tok_ctx); - ct != NULL; - ct = strtok_r (NULL, " ", &tok_ctx)) - { - if (GNUNET_OK != mint_keys_update_cointype (ct)) - { - GNUNET_free (coin_types); - return GNUNET_SYSERR; - } - } - GNUNET_free (coin_types); - return GNUNET_OK; + ok = GNUNET_OK; + GNUNET_CONFIGURATION_iterate_sections (kcfg, + &mint_keys_update_cointype, + &ok); + return ok; } /** - * The main function of the keyup tool + * The main function of the taler-mint-keyup tool. This tool is used + * to create the signing and denomination keys for the mint. It uses + * the long-term offline private key and writes the (additional) key + * files to the respective mint directory (from where they can then be + * copied to the online server). Note that we need (at least) the + * most recent generated previous keys so as to align the validity + * periods. * * @param argc number of arguments from the command line * @param argv command line arguments -- cgit v1.2.3 From 08958c73e8ba6ad30e98a30968077cdf55bc86e8 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 17 Mar 2015 14:54:04 +0100 Subject: add refs to bugtracker --- src/mint/mint_db.h | 5 ++--- src/mint/taler-mint-reservemod.c | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 9818172af..4a9ec1524 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -110,8 +110,7 @@ TALER_MINT_DB_rollback (PGconn *db_conn); /** - * Information we keep on a bank transfer that - * established a reserve. + * Information we keep on bank transfer(s) that established a reserve. */ struct BankTransfer { @@ -135,7 +134,7 @@ struct BankTransfer /* FIXME: add functions to add bank transfers to our DB - (and to test if we already did add one) (#3633) */ + (and to test if we already did add one) (#3633/#3717) */ /** * A summary of a Reserve diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index e805cacc1..dea59d6ee 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -15,7 +15,7 @@ */ /** * @file taler-mint-reservemod.c - * @brief Modify reserves. Allows manipulation of reserve balances for testing. + * @brief Modify reserves. Allows manipulation of reserve balances. * @author Florian Dold * @author Benedikt Mueller */ @@ -57,6 +57,11 @@ static PGconn *db_conn; * @return #GNUNET_OK on success, * #GNUNET_SYSERR on error */ +// FIXME: this should use the DB abstraction layer. (#3717) +// FIXME: this should be done by adding an inbound transaction +// to the table with the transactions for this reserve, +// not by modifying some 'total' value for the reserve! +// (we should in fact probably never modify, always just append!) (#3633) static int reservemod_add (struct TALER_Amount denom) { @@ -223,7 +228,7 @@ main (int argc, char *const *argv) "WARNING", NULL)); - if (GNUNET_GETOPT_run ("taler-mint-keyup", + if (GNUNET_GETOPT_run ("taler-mint-reservemod", options, argc, argv) < 0) return 1; -- cgit v1.2.3 From e6b13123d78c7da4fdcb2cf0e7eb5fafe1f62975 Mon Sep 17 00:00:00 2001 From: Sree Harsha Totakura Date: Wed, 18 Mar 2015 13:50:03 +0100 Subject: update reserve summary when withdraws are made through insert_collectible_blindcoin --- src/mint/mint_db.c | 22 +++++++++++++++++++++- src/mint/mint_db.h | 3 +++ src/mint/taler-mint-httpd_db.c | 1 + src/mint/test_mint_db.c | 9 +++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 6ed7193e3..250acf547 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1030,6 +1030,8 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, * * @param db_conn database connection to use * @param h_blind hash of the blinded message + * @param withdraw amount by which the reserve will be withdrawn with this + * transaction * @param collectable corresponding collectable coin (blind signature) * if a coin is found * @return #GNUNET_SYSERR on internal error @@ -1039,9 +1041,11 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, int TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, const struct GNUNET_HashCode *h_blind, + struct TALER_Amount withdraw, const struct CollectableBlindcoin *collectable) { PGresult *result; + struct Reserve reserve; char *denom_pub_enc = NULL; char *denom_sig_enc = NULL; size_t denom_pub_enc_size; @@ -1063,16 +1067,32 @@ TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig), TALER_DB_QUERY_PARAM_END }; + if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn)) + goto cleanup; result = TALER_DB_exec_prepared (db_conn, "insert_collectable_blindcoin", params); if (PGRES_COMMAND_OK != PQresultStatus (result)) { QUERY_ERR (result); + goto rollback; + } + reserve.pub = (struct GNUNET_CRYPTO_EddsaPublicKey *) + &collectable->reserve_pub; + if (GNUNET_OK != TALER_MINT_DB_reserve_get (db_conn, + &reserve)) + goto rollback; + reserve.balance = TALER_amount_subtract (reserve.balance, withdraw); + if (GNUNET_OK != reserves_update (db_conn, &reserve)) + goto rollback; + if (GNUNET_OK == TALER_MINT_DB_commit (db_conn)) + { + ret = GNUNET_OK; goto cleanup; } - ret = GNUNET_OK; + rollback: + TALER_MINT_DB_rollback(db_conn); cleanup: PQclear (result); GNUNET_free_non_null (denom_pub_enc); diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 4a9ec1524..cec243c99 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -252,6 +252,8 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, * * @param db_conn database connection to use * @param h_blind hash of the blinded message + * @param withdraw amount by which the reserve will be withdrawn with this + * transaction * @param collectable corresponding collectable coin (blind signature) * if a coin is found * @return #GNUNET_SYSERR on internal error @@ -261,6 +263,7 @@ TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, int TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, const struct GNUNET_HashCode *h_blind, + struct TALER_Amount withdraw, const struct CollectableBlindcoin *collectable); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index df68b6570..c5c121d58 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -386,6 +386,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, if (GNUNET_OK != TALER_MINT_DB_insert_collectable_blindcoin (db_conn, &h_blind, + amount_required, &collectable)) { GNUNET_break (0); diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index 010416138..6a55a1d35 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -194,9 +194,18 @@ run (void *cls, char *const *args, const char *cfgfile, cbc.denom_pub = dkp->pub; cbc.sig = GNUNET_CRYPTO_rsa_sign (dkp->priv, &h_blind, sizeof (h_blind)); (void) memcpy (&cbc.reserve_pub, &reserve_pub, sizeof (reserve_pub)); + amount.value--; + amount.fraction--; FAILIF (GNUNET_OK != TALER_MINT_DB_insert_collectable_blindcoin (db, &h_blind, + amount, &cbc)); + FAILIF (GNUNET_OK != check_reserve (db, + &reserve_pub, + amount.value, + amount.fraction, + amount.currency, + expiry.abs_value_us)); FAILIF (GNUNET_YES != TALER_MINT_DB_get_collectable_blindcoin (db, &h_blind, &cbc2)); -- cgit v1.2.3 From 23bf1eee74bed73cf98264c247ab44df8dadfcd9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 18 Mar 2015 18:55:41 +0100 Subject: fix #3716: make sure amount-API offers proper checks against overflow and other issues --- src/include/taler_amount_lib.h | 121 ++++++--- src/include/taler_json_lib.h | 2 +- src/lib/mint_api.c | 12 +- src/mint/mint_db.c | 25 +- src/mint/mint_db.h | 2 +- src/mint/taler-mint-httpd_db.c | 143 ++++++---- src/mint/taler-mint-httpd_deposit.c | 3 +- src/mint/taler-mint-httpd_keystate.c | 21 +- src/mint/taler-mint-httpd_parsing.c | 14 +- src/mint/taler-mint-httpd_refresh.c | 40 ++- src/mint/taler-mint-httpd_responses.c | 68 +++-- src/mint/taler-mint-keyup.c | 27 +- src/mint/taler-mint-reservemod.c | 8 +- src/util/amount.c | 492 +++++++++++++++++++++------------- src/util/json.c | 21 +- 15 files changed, 660 insertions(+), 339 deletions(-) diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h index 8bea0256c..e64ff4d92 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -25,10 +25,27 @@ /** * Number of characters (plus 1 for 0-termination) we use to * represent currency names (i.e. EUR, USD, etc.). We use - * 8 for alignment (!). + * 4 for alignment as 3 characters are typical and we need a + * 0-terminator. So do not change this. */ #define TALER_CURRENCY_LEN 4 +/** + * The "fraction" value in a `struct TALER_Amount` represents which + * fraction of the "main" value? + * + * Note that we need sub-cent precision here as transaction fees might + * be that low, and as we want to support microdonations. + */ +#define TALER_AMOUNT_FRAC_BASE 1000000 + +/** + * How many digits behind the comma are required to represent the + * fractional value in human readable decimal format? Must match + * lg(#TALER_AMOUNT_FRAC_BASE). + */ +#define TALER_AMOUNT_FRAC_LEN 6 + GNUNET_NETWORK_STRUCT_BEGIN @@ -41,12 +58,12 @@ struct TALER_AmountNBO /** * Value in the main currency, in NBO. */ - uint32_t value; + uint64_t value GNUNET_PACKED; /** * Additinal fractional value, in NBO. */ - uint32_t fraction; + uint32_t fraction GNUNET_PACKED; /** * Type of the currency being represented. @@ -65,7 +82,7 @@ struct TALER_Amount /** * Value (numerator of fraction) */ - uint32_t value; + uint64_t value; /** * Fraction (denominator of fraction) @@ -73,7 +90,8 @@ struct TALER_Amount uint32_t fraction; /** - * Currency string, left adjusted and padded with zeros. + * Currency string, left adjusted and padded with zeros. All zeros + * for "invalid" values. */ char currency[TALER_CURRENCY_LEN]; }; @@ -92,82 +110,123 @@ TALER_string_to_amount (const char *str, struct TALER_Amount *denom); +/** + * Get the value of "zero" in a particular currency. + * + * @param cur currency description + * @param denom denomination to write the result to + * @return #GNUNET_OK if @a cur is a valid currency specification, + * #GNUNET_SYSERR if it is invalid. + */ +int +TALER_amount_get_zero (const char *cur, + struct TALER_Amount *denom); + + /** * Convert amount from host to network representation. * + * @param res where to store amount in network representation * @param d amount in host representation - * @return amount in network representation */ -struct TALER_AmountNBO -TALER_amount_hton (const struct TALER_Amount d); +void +TALER_amount_hton (struct TALER_AmountNBO *res, + const struct TALER_Amount *d); /** * Convert amount from network to host representation. * + * @param res where to store amount in host representation * @param d amount in network representation - * @return amount in host representation */ -struct TALER_Amount -TALER_amount_ntoh (const struct TALER_AmountNBO dn); +void +TALER_amount_ntoh (struct TALER_Amount *res, + const struct TALER_AmountNBO *dn); /** - * Compare the value/fraction of two amounts. Does not compare the currency, - * i.e. comparing amounts with the same value and fraction but different - * currency would return 0. + * Compare the value/fraction of two amounts. Does not compare the currency. + * Comparing amounts of different currencies will cause the program to abort(). + * If unsure, check with #TALER_amount_cmp_currency() first to be sure that + * the currencies of the two amounts are identical. * * @param a1 first amount * @param a2 second amount * @return result of the comparison */ int -TALER_amount_cmp (struct TALER_Amount a1, - struct TALER_Amount a2); +TALER_amount_cmp (const struct TALER_Amount *a1, + const struct TALER_Amount *a2); + + +/** + * Test if @a a1 and @a a2 are the same currency. + * + * @param a1 amount to test + * @param a2 amount to test + * @return #GNUNET_YES if @a a1 and @a a2 are the same currency + * #GNUNET_NO if the currencies are different + * #GNUNET_SYSERR if either amount is invalid + */ +int +TALER_amount_cmp_currency (const struct TALER_Amount *a1, + const struct TALER_Amount *a2); /** * Perform saturating subtraction of amounts. * + * @param diff where to store (@a a1 - @a a2), or invalid if @a a2 > @a a1 * @param a1 amount to subtract from * @param a2 amount to subtract - * @return (a1-a2) or 0 if a2>=a1 + * @return #GNUNET_OK if the subtraction worked, + * #GNUNET_NO if @a a1 = @a a2 + * #GNUNET_SYSERR if @a a2 > @a a1 or currencies are incompatible; + * @a diff is set to invalid */ -struct TALER_Amount -TALER_amount_subtract (struct TALER_Amount a1, - struct TALER_Amount a2); +int +TALER_amount_subtract (struct TALER_Amount *diff, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2); /** - * Perform saturating addition of amounts + * Perform addition of amounts. * + * @param sum where to store @a a1 + @a a2, set to "invalid" on overflow * @param a1 first amount to add * @param a2 second amount to add - * @return sum of a1 and a2 + * @return #GNUNET_OK if the addition worked, + * #GNUNET_SYSERR on overflow */ -struct TALER_Amount -TALER_amount_add (struct TALER_Amount a1, - struct TALER_Amount a2); +int +TALER_amount_add (struct TALER_Amount *sum, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2); /** * Normalize the given amount. * - * @param amout amount to normalize - * @return normalized amount + * @param amount amount to normalize + * @return #GNUNET_OK if normalization worked + * #GNUNET_NO if value was already normalized + * #GNUNET_SYSERR if value was invalid or could not be normalized */ -struct TALER_Amount -TALER_amount_normalize (struct TALER_Amount amount); +int +TALER_amount_normalize (struct TALER_Amount *amount); /** * Convert amount to string. * * @param amount amount to convert to string - * @return freshly allocated string representation + * @return freshly allocated string representation, + * NULL if the @a amount was invalid */ char * -TALER_amount_to_string (struct TALER_Amount amount); +TALER_amount_to_string (const struct TALER_Amount *amount); #endif diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 1048b89f6..c5515966f 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -39,7 +39,7 @@ * @return a json object describing the amount */ json_t * -TALER_JSON_from_amount (struct TALER_Amount amount); +TALER_JSON_from_amount (const struct TALER_Amount *amount); /** diff --git a/src/lib/mint_api.c b/src/lib/mint_api.c index af4f04956..eb2697a2e 100644 --- a/src/lib/mint_api.c +++ b/src/lib/mint_api.c @@ -412,10 +412,14 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, denom_key_issue.start = GNUNET_TIME_absolute_hton (valid_from); denom_key_issue.expire_withdraw = GNUNET_TIME_absolute_hton (withdraw_valid_until); denom_key_issue.expire_spend = GNUNET_TIME_absolute_hton (deposit_valid_until); - denom_key_issue.value = TALER_amount_hton (value); - denom_key_issue.fee_withdraw = TALER_amount_hton (fee_withdraw); - denom_key_issue.fee_deposit = TALER_amount_hton (fee_deposit); - denom_key_issue.fee_refresh = TALER_amount_hton (fee_refresh); + TALER_amount_hton (&denom_key_issue.value, + &value); + TALER_amount_hton (&denom_key_issue.fee_withdraw, + &fee_withdraw); + TALER_amount_hton (&denom_key_issue.fee_deposit, + &fee_deposit); + TALER_amount_hton (&denom_key_issue.fee_refresh, + &fee_refresh); EXITIF (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOM, &denom_key_issue.purpose, diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 6ed7193e3..545a5252b 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -807,7 +807,8 @@ reserves_update (PGconn *db, TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), TALER_DB_QUERY_PARAM_END }; - balance_nbo = TALER_amount_hton (reserve->balance); + TALER_amount_hton (&balance_nbo, + &reserve->balance); expiry_nbo = GNUNET_TIME_absolute_hton (reserve->expiry); result = TALER_DB_exec_prepared (db, "update_reserve", @@ -837,7 +838,7 @@ reserves_update (PGconn *db, int TALER_MINT_DB_reserves_in_insert (PGconn *db, struct Reserve *reserve, - const struct TALER_Amount balance, + const struct TALER_Amount *balance, const struct GNUNET_TIME_Absolute expiry) { struct TALER_AmountNBO balance_nbo; @@ -862,7 +863,8 @@ TALER_MINT_DB_reserves_in_insert (PGconn *db, TALER_MINT_DB_rollback (db); return GNUNET_SYSERR; } - balance_nbo = TALER_amount_hton (balance); + TALER_amount_hton (&balance_nbo, + balance); expiry_nbo = GNUNET_TIME_absolute_hton (expiry); if (GNUNET_NO == reserve_exists) { @@ -907,19 +909,27 @@ TALER_MINT_DB_reserves_in_insert (PGconn *db, QUERY_ERR (result); goto rollback; } - PQclear (result); result = NULL; + PQclear (result); + result = NULL; if (GNUNET_NO == reserve_exists) { if (GNUNET_OK != TALER_MINT_DB_commit (db)) return GNUNET_SYSERR; - reserve->balance = balance; + reserve->balance = *balance; reserve->expiry = expiry; return GNUNET_OK; } /* Update reserve */ struct Reserve updated_reserve; updated_reserve.pub = reserve->pub; - updated_reserve.balance = TALER_amount_add (reserve->balance, balance); + + if (GNUNET_OK != + TALER_amount_add (&updated_reserve.balance, + &reserve->balance, + balance)) + { + return GNUNET_SYSERR; + } updated_reserve.expiry = GNUNET_TIME_absolute_max (expiry, reserve->expiry); if (GNUNET_OK != reserves_update (db, &updated_reserve)) goto rollback; @@ -1350,7 +1360,8 @@ TALER_MINT_DB_insert_deposit (PGconn *db_conn, GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig, &denom_sig_enc); json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); - amount_nbo = TALER_amount_hton (deposit->amount); + TALER_amount_hton (&amount_nbo, + &deposit->amount); struct TALER_DB_QueryParam params[]= { TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h index 4a9ec1524..9312f548a 100644 --- a/src/mint/mint_db.h +++ b/src/mint/mint_db.h @@ -224,7 +224,7 @@ TALER_MINT_DB_reserve_get (PGconn *db, int TALER_MINT_DB_reserves_in_insert (PGconn *db, struct Reserve *reserve, - const struct TALER_Amount balance, + const struct TALER_Amount *balance, const struct GNUNET_TIME_Absolute expiry); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index df68b6570..05c2a48a7 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -34,26 +34,6 @@ #include "taler-mint-httpd_keystate.h" -/** - * Get an amount in the mint's currency that is zero. - * - * @return zero amount in the mint's currency - */ -static struct TALER_Amount -mint_amount_native_zero () -{ - struct TALER_Amount amount; - - memset (&amount, - 0, - sizeof (amount)); - memcpy (amount.currency, - MINT_CURRENCY, - strlen (MINT_CURRENCY) + 1); - return amount; -} - - /** * Execute a deposit. The validity of the coin and signature * have already been checked. The database must now check that @@ -99,9 +79,12 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, mks = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (mks, deposit->coin.denom_pub); - value = TALER_amount_ntoh (dki->issue.value); - fee_deposit = TALER_amount_ntoh (dki->issue.fee_deposit); - fee_refresh = TALER_amount_ntoh (dki->issue.fee_refresh); + TALER_amount_ntoh (&value, + &dki->issue.value); + TALER_amount_ntoh (&fee_deposit, + &dki->issue.fee_deposit); + TALER_amount_ntoh (&fee_refresh, + &dki->issue.fee_refresh); TALER_MINT_key_state_release (mks); if (GNUNET_OK != @@ -113,26 +96,49 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, tl = TALER_MINT_DB_get_coin_transactions (db_conn, &deposit->coin.coin_pub); spent = fee_deposit; /* fee for THIS transaction */ - /* FIXME: need to deal better with integer overflows - in the logic that follows! (change amount.c API! -- #3637) */ - spent = TALER_amount_add (spent, - deposit->amount); + if (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &deposit->amount)) + { + GNUNET_break (0); + TALER_MINT_DB_free_coin_transaction_list (tl); + return TALER_MINT_reply_internal_db_error (connection); + } for (pos = tl; NULL != pos; pos = pos->next) { switch (pos->type) { case TALER_MINT_DB_TT_DEPOSIT: - spent = TALER_amount_add (spent, - pos->details.deposit->amount); - spent = TALER_amount_add (spent, - fee_deposit); + if ( (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &pos->details.deposit->amount)) || + (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &fee_deposit)) ) + { + GNUNET_break (0); + TALER_MINT_DB_free_coin_transaction_list (tl); + return TALER_MINT_reply_internal_db_error (connection); + } break; case TALER_MINT_DB_TT_REFRESH_MELT: - spent = TALER_amount_add (spent, - pos->details.melt->amount); - spent = TALER_amount_add (spent, - fee_refresh); + if ( (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &pos->details.melt->amount)) || + (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &fee_refresh)) ) + { + GNUNET_break (0); + TALER_MINT_DB_free_coin_transaction_list (tl); + return TALER_MINT_reply_internal_db_error (connection); + } break; case TALER_MINT_DB_TT_LOCK: /* should check if lock is still active, @@ -146,11 +152,12 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, } } - if (0 < TALER_amount_cmp (spent, value)) + if (0 < TALER_amount_cmp (&spent, + &value)) { TALER_MINT_DB_rollback (db_conn); ret = TALER_MINT_reply_deposit_insufficient_funds (connection, - tl); + tl); TALER_MINT_DB_free_coin_transaction_list (tl); return ret; } @@ -251,6 +258,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, struct TALER_Amount withdraw_total; struct TALER_Amount balance; struct TALER_Amount value; + struct TALER_Amount fee_withdraw; struct GNUNET_HashCode h_blind; int res; @@ -318,8 +326,20 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, } /* calculate amount required including fees */ - amount_required = TALER_amount_add (TALER_amount_ntoh (dki->issue.value), - TALER_amount_ntoh (dki->issue.fee_withdraw)); + TALER_amount_ntoh (&value, + &dki->issue.value); + TALER_amount_ntoh (&fee_withdraw, + &dki->issue.fee_withdraw); + + if (GNUNET_OK != + TALER_amount_add (&amount_required, + &value, + &fee_withdraw)) + { + TALER_MINT_DB_rollback (db_conn); + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_internal_db_error (connection); + } /* calculate balance of the reserve */ res = 0; @@ -331,29 +351,45 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, if (0 == (res & 1)) deposit_total = pos->details.bank->amount; else - deposit_total = TALER_amount_add (deposit_total, - pos->details.bank->amount); + if (GNUNET_OK != + TALER_amount_add (&deposit_total, + &deposit_total, + &pos->details.bank->amount)) + { + TALER_MINT_DB_rollback (db_conn); + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_internal_db_error (connection); + } res |= 1; break; case TALER_MINT_DB_RO_WITHDRAW_COIN: tdki = TALER_MINT_get_denom_key (key_state, pos->details.withdraw->denom_pub); - value = TALER_amount_ntoh (tdki->issue.value); + TALER_amount_ntoh (&value, + &tdki->issue.value); if (0 == (res & 2)) withdraw_total = value; else - withdraw_total = TALER_amount_add (withdraw_total, - value); + if (GNUNET_OK != + TALER_amount_add (&withdraw_total, + &withdraw_total, + &value)) + { + TALER_MINT_DB_rollback (db_conn); + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_internal_db_error (connection); + } res |= 2; break; } } - GNUNET_break (0 > TALER_amount_cmp (withdraw_total, - deposit_total)); - balance = TALER_amount_subtract (deposit_total, - withdraw_total); - if (0 < TALER_amount_cmp (amount_required, - balance)) + /* All reserve balances should be non-negative */ + GNUNET_break (GNUNET_SYSERR != + TALER_amount_subtract (&balance, + &deposit_total, + &withdraw_total)); + if (0 < TALER_amount_cmp (&amount_required, + &balance)) { TALER_MINT_key_state_release (key_state); TALER_MINT_DB_rollback (db_conn); @@ -450,7 +486,8 @@ refresh_accept_melts (struct MHD_Connection *connection, "denom not found")) ? GNUNET_NO : GNUNET_SYSERR; - coin_value = TALER_amount_ntoh (dki->value); + TALER_amount_ntoh (&coin_value, + &dki->value); tl = TALER_MINT_DB_get_coin_transactions (db_conn, &coin_public_info->coin_pub); /* FIXME: #3636: compute how much value is left with this coin and @@ -459,8 +496,8 @@ refresh_accept_melts (struct MHD_Connection *connection, /* Refuse to refresh when the coin does not have enough money left to * pay the refreshing fees of the coin. */ - if (TALER_amount_cmp (coin_residual, - coin_details->melt_amount) < 0) + if (TALER_amount_cmp (&coin_residual, + &coin_details->melt_amount) < 0) { res = (MHD_YES == TALER_MINT_reply_refresh_melt_insufficient_funds (connection, diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index d37e69e40..37d6d23d5 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -65,7 +65,8 @@ verify_and_execute_deposit (struct MHD_Connection *connection, dr.h_contract = deposit->h_contract; dr.h_wire = deposit->h_wire; dr.transaction_id = GNUNET_htonll (deposit->transaction_id); - dr.amount = TALER_amount_hton (deposit->amount); + TALER_amount_hton (&dr.amount, + &deposit->amount); dr.coin_pub = deposit->coin.coin_pub; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_WALLET_DEPOSIT, diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index bf802f5b5..ca802e2d3 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -114,6 +114,19 @@ static json_t * denom_key_issue_to_json (struct GNUNET_CRYPTO_rsa_PublicKey *pk, const struct TALER_MINT_DenomKeyIssue *dki) { + struct TALER_Amount value; + struct TALER_Amount fee_withdraw; + struct TALER_Amount fee_deposit; + struct TALER_Amount fee_refresh; + + TALER_amount_ntoh (&value, + &dki->value); + TALER_amount_ntoh (&fee_withdraw, + &dki->fee_withdraw); + TALER_amount_ntoh (&fee_deposit, + &dki->fee_deposit); + TALER_amount_ntoh (&fee_refresh, + &dki->fee_refresh); return json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o, s:o}", "master_sig", @@ -128,13 +141,13 @@ denom_key_issue_to_json (struct GNUNET_CRYPTO_rsa_PublicKey *pk, "denom_pub", TALER_JSON_from_rsa_public_key (pk), "value", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->value)), + TALER_JSON_from_amount (&value), "fee_withdraw", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_withdraw)), + TALER_JSON_from_amount (&fee_withdraw), "fee_deposit", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_deposit)), + TALER_JSON_from_amount (&fee_deposit), "fee_refresh", - TALER_JSON_from_amount (TALER_amount_ntoh (dki->fee_refresh))); + TALER_JSON_from_amount (&fee_refresh)); } diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index 6c5f72b32..b8bc043ec 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -878,8 +878,10 @@ TALER_MINT_parse_amount_json (struct MHD_Connection *connection, json_int_t value; json_int_t fraction; const char *currency; - struct TALER_Amount a; + memset (amount, + 0, + sizeof (struct TALER_Amount)); if (-1 == json_unpack (f, "{s:I, s:I, s:s}", "value", &value, @@ -897,7 +899,7 @@ TALER_MINT_parse_amount_json (struct MHD_Connection *connection, } if ( (value < 0) || (fraction < 0) || - (value > UINT32_MAX) || + (value > UINT64_MAX) || (fraction > UINT32_MAX) ) { LOG_WARNING ("Amount specified not in allowed range\n"); @@ -922,11 +924,11 @@ TALER_MINT_parse_amount_json (struct MHD_Connection *connection, return GNUNET_SYSERR; return GNUNET_NO; } - a.value = (uint32_t) value; - a.fraction = (uint32_t) fraction; + amount->value = (uint64_t) value; + amount->fraction = (uint32_t) fraction; GNUNET_assert (strlen (MINT_CURRENCY) < TALER_CURRENCY_LEN); - strcpy (a.currency, MINT_CURRENCY); - *amount = TALER_amount_normalize (a); + strcpy (amount->currency, MINT_CURRENCY); + TALER_amount_normalize (amount); return GNUNET_OK; } diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index c7bda5a79..e62521ef4 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -82,6 +82,8 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct TALER_Amount cost; struct TALER_Amount total_cost; struct TALER_Amount melt; + struct TALER_Amount value; + struct TALER_Amount fee_withdraw; struct TALER_Amount total_melt; /* check that signature from the session public key is ok */ @@ -107,7 +109,8 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); body.melt_hash = melt_hash; - body.amount = TALER_amount_hton (coin_melt_details->melt_amount); + TALER_amount_hton (&body.amount, + &coin_melt_details->melt_amount); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, &body.purpose, @@ -130,11 +133,22 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, { dki = &TALER_MINT_get_denom_key (key_state, denom_pubs[i])->issue; - cost = TALER_amount_add (TALER_amount_ntoh (dki->value), - TALER_amount_ntoh (dki->fee_withdraw)); + TALER_amount_ntoh (&value, + &dki->value); + TALER_amount_ntoh (&fee_withdraw, + &dki->fee_withdraw); // FIXME: #3637 - total_cost = TALER_amount_add (cost, - total_cost); + if ( (GNUNET_OK != + TALER_amount_add (&cost, + &value, + &fee_withdraw)) || + (GNUNET_OK != + TALER_amount_add (&total_cost, + &cost, + &total_cost)) ) + { + // FIXME... + } } // FIXME: badness, use proper way to set to zero... @@ -146,13 +160,18 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, // melt = coin_values[i]; // FIXME: #3636! // FIXME: #3637 - total_melt = TALER_amount_add (melt, - total_melt); + if (GNUNET_OK != + TALER_amount_add (&total_melt, + &melt, + &total_melt)) + { + // FIXME ... + } } TALER_MINT_key_state_release (key_state); if (0 != - TALER_amount_cmp (total_cost, - total_melt) ) + TALER_amount_cmp (&total_cost, + &total_melt) ) { /* We require total value of coins being melted and total value of coins being generated to match! */ @@ -269,7 +288,8 @@ verify_coin_public_info (struct MHD_Connection *connection, body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); body.melt_hash = *melt_hash; - body.amount = TALER_amount_hton (r_melt_detail->melt_amount); + TALER_amount_hton (&body.amount, + &r_melt_detail->melt_amount); body.coin_pub = r_public_info->coin_pub; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN, diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index 3d827b118..a4b442152 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -299,7 +299,8 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, dc.h_contract = *h_contract; dc.h_wire = *h_wire; dc.transaction_id = GNUNET_htonll (transaction_id); - dc.amount = TALER_amount_hton (*amount); + TALER_amount_hton (&dc.amount, + amount); dc.coin_pub = *coin_pub; dc.merchant = *merchant; TALER_MINT_keys_sign (&dc.purpose, @@ -346,7 +347,8 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) dr.h_contract = deposit->h_contract; dr.h_wire = deposit->h_wire; dr.transaction_id = GNUNET_htonll (deposit->transaction_id); - dr.amount = TALER_amount_hton (deposit->amount); + TALER_amount_hton (&dr.amount, + &deposit->amount); dr.coin_pub = deposit->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&dr.purpose, &deposit->csig); @@ -362,7 +364,8 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); ms.melt_hash = melt->melt_hash; - ms.amount = TALER_amount_hton (melt->amount); + TALER_amount_hton (&ms.amount, + &melt->amount); ms.coin_pub = melt->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, &melt->coin_sig); @@ -382,7 +385,7 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) json_array_append_new (history, json_pack ("{s:s, s:o}", "type", type, - "amount", TALER_JSON_from_amount (value), + "amount", TALER_JSON_from_amount (&value), "signature", transaction)); } return history; @@ -419,7 +422,7 @@ TALER_MINT_reply_deposit_insufficient_funds (struct MHD_Connection *connection, * * @param rh reserve history to JSON-ify * @param balance[OUT] set to current reserve balance - * @return json representation of the @a rh + * @return json representation of the @a rh, NULL on error */ static json_t * compile_reserve_history (const struct ReserveHistory *rh, @@ -446,14 +449,20 @@ compile_reserve_history (const struct ReserveHistory *rh, if (0 == ret) deposit_total = pos->details.bank->amount; else - deposit_total = TALER_amount_add (deposit_total, - pos->details.bank->amount); + if (GNUNET_OK != + TALER_amount_add (&deposit_total, + &deposit_total, + &pos->details.bank->amount)) + { + json_decref (json_history); + return NULL; + } ret = 1; json_array_append_new (json_history, json_pack ("{s:s, s:o, s:o}", "type", "DEPOSIT", "wire", pos->details.bank->wire, - "amount", TALER_JSON_from_amount (pos->details.bank->amount))); + "amount", TALER_JSON_from_amount (&pos->details.bank->amount))); break; case TALER_MINT_DB_RO_WITHDRAW_COIN: break; @@ -472,12 +481,20 @@ compile_reserve_history (const struct ReserveHistory *rh, dki = TALER_MINT_get_denom_key (key_state, pos->details.withdraw->denom_pub); - value = TALER_amount_ntoh (dki->issue.value); + TALER_amount_ntoh (&value, + &dki->issue.value); if (0 == ret) withdraw_total = value; else - withdraw_total = TALER_amount_add (withdraw_total, - value); + if (GNUNET_OK != + TALER_amount_add (&withdraw_total, + &withdraw_total, + &value)) + { + TALER_MINT_key_state_release (key_state); + json_decref (json_history); + return NULL; + } ret = 1; wr.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW); wr.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest)); @@ -493,15 +510,22 @@ compile_reserve_history (const struct ReserveHistory *rh, json_pack ("{s:s, s:o, s:o}", "type", "WITHDRAW", "signature", transaction, - "amount", TALER_JSON_from_amount (value))); + "amount", TALER_JSON_from_amount (&value))); break; } } TALER_MINT_key_state_release (key_state); - *balance = TALER_amount_subtract (deposit_total, - withdraw_total); + if (GNUNET_SYSERR == + TALER_amount_subtract (balance, + &deposit_total, + &withdraw_total)) + { + GNUNET_break (0); + json_decref (json_history); + return NULL; + } return json_history; } @@ -524,7 +548,10 @@ TALER_MINT_reply_withdraw_status_success (struct MHD_Connection *connection, json_history = compile_reserve_history (rh, &balance); - json_balance = TALER_JSON_from_amount (balance); + if (NULL == json_history) + return TALER_MINT_reply_internal_error (connection, + "balance calculation failure"); + json_balance = TALER_JSON_from_amount (&balance); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, "{s:o, s:o}", @@ -556,7 +583,10 @@ TALER_MINT_reply_withdraw_sign_insufficient_funds (struct MHD_Connection *connec json_history = compile_reserve_history (rh, &balance); - json_balance = TALER_JSON_from_amount (balance); + if (NULL == json_history) + return TALER_MINT_reply_internal_error (connection, + "balance calculation failure"); + json_balance = TALER_JSON_from_amount (&balance); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_PAYMENT_REQUIRED, "{s:s, s:o, s:o}", @@ -625,9 +655,9 @@ TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connect "error", "insufficient funds", "coin-pub", TALER_JSON_from_data (coin_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)), - "original-value", TALER_JSON_from_amount (coin_value), - "residual-value", TALER_JSON_from_amount (residual), - "requested-value", TALER_JSON_from_amount (requested), + "original-value", TALER_JSON_from_amount (&coin_value), + "residual-value", TALER_JSON_from_amount (&residual), + "requested-value", TALER_JSON_from_amount (&requested), "history", history); } diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 33bb87249..759e7c1b3 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -233,10 +233,14 @@ hash_coin_type (const struct CoinTypeParams *p, sizeof (struct CoinTypeNBO)); p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend); p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw); - p_nbo.value = TALER_amount_hton (p->value); - p_nbo.fee_withdraw = TALER_amount_hton (p->fee_withdraw); - p_nbo.fee_deposit = TALER_amount_hton (p->fee_deposit); - p_nbo.fee_refresh = TALER_amount_hton (p->fee_refresh); + TALER_amount_hton (&p_nbo.value, + &p->value); + TALER_amount_hton (&p_nbo.fee_withdraw, + &p->fee_withdraw); + TALER_amount_hton (&p_nbo.fee_deposit, + &p->fee_deposit); + TALER_amount_hton (&p_nbo.fee_refresh, + &p->fee_refresh); p_nbo.rsa_keysize = htonl (p->rsa_keysize); GNUNET_CRYPTO_hash (&p_nbo, sizeof (struct CoinTypeNBO), @@ -273,7 +277,7 @@ get_cointype_dir (const struct CoinTypeParams *p) GNUNET_assert (HASH_CUTOFF <= strlen (hash_str) + 1); hash_str[HASH_CUTOFF] = 0; - val_str = TALER_amount_to_string (p->value); + val_str = TALER_amount_to_string (&p->value); for (i = 0; i < strlen (val_str); i++) if ( (':' == val_str[i]) || ('.' == val_str[i]) ) @@ -687,11 +691,14 @@ create_denomkey_issue (const struct CoinTypeParams *params, dki->issue.expire_spend = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, params->duration_spend)); - dki->issue.value = TALER_amount_hton (params->value); - dki->issue.fee_withdraw = TALER_amount_hton (params->fee_withdraw); - dki->issue.fee_deposit = TALER_amount_hton (params->fee_deposit); - dki->issue.fee_refresh = TALER_amount_hton (params->fee_refresh); - + TALER_amount_hton (&dki->issue.value, + ¶ms->value); + TALER_amount_hton (&dki->issue.fee_withdraw, + ¶ms->fee_withdraw); + TALER_amount_hton (&dki->issue.fee_deposit, + ¶ms->fee_deposit); + TALER_amount_hton (&dki->issue.fee_refresh, + ¶ms->fee_refresh); dki->issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_DENOM); dki->issue.purpose.size = htonl (sizeof (struct TALER_MINT_DenomKeyIssuePriv) - offsetof (struct TALER_MINT_DenomKeyIssuePriv, diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index dea59d6ee..df3f0cd5d 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -161,9 +161,11 @@ reservemod_add (struct TALER_Amount denom) "balance_fraction", "balance_currency", &old_denom)); - new_denom = TALER_amount_add (old_denom, - denom); - new_denom_nbo = TALER_amount_hton (new_denom); + TALER_amount_add (&new_denom, + &old_denom, + &denom); + TALER_amount_hton (&new_denom_nbo, + &new_denom); result = PQexecParams (db_conn, "UPDATE reserves" " SET balance_value = $1, balance_fraction = $2, status_sig = NULL, status_sign_pub = NULL" diff --git a/src/util/amount.c b/src/util/amount.c index b3e3b4217..5e7f69fd9 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -30,16 +30,6 @@ #include "taler_util.h" #include -/** - * - */ -#define AMOUNT_FRAC_BASE 1000000 - -/** - * - */ -#define AMOUNT_FRAC_LEN 6 - /** * Parse money amount description, in the format "A:B.C". @@ -53,159 +43,260 @@ int TALER_string_to_amount (const char *str, struct TALER_Amount *denom) { - size_t i; // pos in str - int n; // number tmp - size_t c; // currency pos - uint32_t b; // base for suffix + size_t i; + int n; + uint32_t b; + const char *colon; + const char *value; memset (denom, 0, sizeof (struct TALER_Amount)); - - i = 0; - while (isspace(str[i])) - i++; - - if (0 == str[i]) + /* skip leading whitespace */ + while (isspace(str[0])) + str++; + if ('\0' == str[0]) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "null before currency\n"); + "Null before currency\n"); return GNUNET_SYSERR; } - - c = 0; - while (str[i] != ':') + /* parse currency */ + colon = strchr (str, (int) ':'); + if ( (NULL == colon) || + ((colon - str) >= TALER_CURRENCY_LEN) ) { - if (0 == str[i]) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "null before colon"); - return GNUNET_SYSERR; - } - if (c > 3) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "currency too long\n"); - return GNUNET_SYSERR; - } - denom->currency[c] = str[i]; - c++; - i++; + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid currency specified before colon: `%s'", + str); + goto fail; } - - // skip colon - i++; - - if (0 == str[i]) + memcpy (denom->currency, + str, + colon - str); + /* skip colon */ + value = colon + 1; + if ('\0' == value[0]) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "null before value\n"); - return GNUNET_SYSERR; + "Null before value\n"); + goto fail; } - while (str[i] != '.') + /* parse value */ + i = 0; + while ('.' != value[i]) { - if (0 == str[i]) + if ('\0' == value[i]) { return GNUNET_OK; } + if ( (str[i] < '0') || (str[i] > '9') ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Invalid character `%c'\n", + str[i]); + goto fail; + } n = str[i] - '0'; - if (n < 0 || n > 9) + if (denom->value * 10 + n < denom->value) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "invalid character '%c' before comma at %u\n", - (char) n, - i); - return GNUNET_SYSERR; + "Value too large\n"); + goto fail; } denom->value = (denom->value * 10) + n; i++; } - // skip the dot + /* skip the dot */ i++; - if (0 == str[i]) + /* parse fraction */ + if ('\0' == str[i]) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "null after dot"); - return GNUNET_SYSERR; + "Null after dot"); + goto fail; } - - b = 100000; - - while (0 != str[i]) + b = TALER_AMOUNT_FRAC_BASE / 10; + while ('\0' != str[i]) { - n = str[i] - '0'; - if ( (0 == b) || (n < 0) || (n > 9) ) + if (0 == b) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "error after comma"); - return GNUNET_SYSERR; + "Fractional value too small (only %u digits supported)", + (unsigned int) TALER_AMOUNT_FRAC_LEN); + goto fail; + } + if ( (str[i] < '0') || (str[i] > '9') ) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Error after comma"); + goto fail; } + n = str[i] - '0'; denom->fraction += n * b; b /= 10; i++; } - return GNUNET_OK; + + fail: + /* set currency to 'invalid' to prevent accidental use */ + memset (denom->currency, + 0, + TALER_CURRENCY_LEN); + return GNUNET_SYSERR; +} + + +/** + * Convert amount from host to network representation. + * + * @param res where to store amount in network representation + * @param d amount in host representation + */ +void +TALER_amount_hton (struct TALER_AmountNBO *res, + const struct TALER_Amount *d) +{ + res->value = GNUNET_htonll (d->value); + res->fraction = htonl (d->fraction); + memcpy (res->currency, + d->currency, + TALER_CURRENCY_LEN); +} + + +/** + * Convert amount from network to host representation. + * + * @param res where to store amount in host representation + * @param d amount in network representation + */ +void +TALER_amount_ntoh (struct TALER_Amount *res, + const struct TALER_AmountNBO *dn) +{ + res->value = GNUNET_ntohll (dn->value); + res->fraction = ntohl (dn->fraction); + memcpy (res->currency, + dn->currency, + TALER_CURRENCY_LEN); } /** - * FIXME + * Get the value of "zero" in a particular currency. + * + * @param cur currency description + * @param denom denomination to write the result to + * @return #GNUNET_OK if @a cur is a valid currency specification, + * #GNUNET_SYSERR if it is invalid. */ -struct TALER_AmountNBO -TALER_amount_hton (const struct TALER_Amount d) +int +TALER_amount_get_zero (const char *cur, + struct TALER_Amount *denom) { - struct TALER_AmountNBO dn; - dn.value = htonl (d.value); - dn.fraction = htonl (d.fraction); - memcpy (dn.currency, d.currency, TALER_CURRENCY_LEN); + size_t slen; - return dn; + slen = strlen (cur); + if (slen >= TALER_CURRENCY_LEN) + return GNUNET_SYSERR; + memset (denom, + 0, + sizeof (struct TALER_Amount)); + memcpy (denom->currency, + cur, + slen); + return GNUNET_OK; } /** - * FIXME + * Set @a a to "invalid". + * + * @param a amount to set to invalid */ -struct TALER_Amount -TALER_amount_ntoh (const struct TALER_AmountNBO dn) +static void +invalidate (struct TALER_Amount *a) { - struct TALER_Amount d; - d.value = ntohl (dn.value); - d.fraction = ntohl (dn.fraction); - memcpy (d.currency, dn.currency, TALER_CURRENCY_LEN); + memset (a, + 0, + sizeof (struct TALER_Amount)); +} + - return d; +/** + * Test if @a a is valid + * + * @param a amount to test + * @return #GNUNET_YES if valid, + * #GNUNET_NO if invalid + */ +static int +test_valid (const struct TALER_Amount *a) +{ + return ('\0' != a->currency[0]); +} + + +/** + * Test if @a a1 and @a a2 are the same currency. + * + * @param a1 amount to test + * @param a2 amount to test + * @return #GNUNET_YES if @a a1 and @a a2 are the same currency + * #GNUNET_NO if the currencies are different, + * #GNUNET_SYSERR if either amount is invalid + */ +int +TALER_amount_cmp_currency (const struct TALER_Amount *a1, + const struct TALER_Amount *a2) +{ + if ( (GNUNET_NO == test_valid (a1)) || + (GNUNET_NO == test_valid (a2)) ) + return GNUNET_SYSERR; + if (0 == strcmp (a1->currency, + a2->currency)) + return GNUNET_YES; + return GNUNET_NO; } /** - * Compare the value/fraction of two amounts. Does not compare the currency, - * i.e. comparing amounts with the same value and fraction but different - * currency would return 0. + * Compare the value/fraction of two amounts. Does not compare the currency. + * Comparing amounts of different currencies will cause the program to abort(). + * If unsure, check with #TALER_amount_cmp_currency() first to be sure that + * the currencies of the two amounts are identical. * * @param a1 first amount * @param a2 second amount * @return result of the comparison */ int -TALER_amount_cmp (struct TALER_Amount a1, - struct TALER_Amount a2) +TALER_amount_cmp (const struct TALER_Amount *a1, + const struct TALER_Amount *a2) { - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); - if (a1.value == a2.value) + struct TALER_Amount n1; + struct TALER_Amount n2; + + GNUNET_assert (GNUNET_YES == + TALER_amount_cmp_currency (a1, a2)); + n1 = *a1; + n2 = *a2; + TALER_amount_normalize (&n1); + TALER_amount_normalize (&n2); + if (n1.value == n2.value) { - if (a1.fraction < a2.fraction) + if (n1.fraction < n2.fraction) return -1; - if (a1.fraction > a2.fraction) + if (n1.fraction > n2.fraction) return 1; return 0; } - if (a1.value < a2.value) + if (n1.value < n2.value) return -1; return 1; } @@ -214,109 +305,142 @@ TALER_amount_cmp (struct TALER_Amount a1, /** * Perform saturating subtraction of amounts. * + * @param diff where to store (@a a1 - @a a2), or invalid if @a a2 > @a a1 * @param a1 amount to subtract from * @param a2 amount to subtract - * @return (a1-a2) or 0 if a2>=a1 + * @return #GNUNET_OK if the subtraction worked, + * #GNUNET_NO if @a a1 = @a a2 + * #GNUNET_SYSERR if @a a2 > @a a1 or currencies are incompatible; + * @a diff is set to invalid */ -struct TALER_Amount -TALER_amount_subtract (struct TALER_Amount a1, - struct TALER_Amount a2) +int +TALER_amount_subtract (struct TALER_Amount *diff, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2) { - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); + struct TALER_Amount n1; + struct TALER_Amount n2; - if (a1.value < a2.value) + if (GNUNET_YES != + TALER_amount_cmp_currency (a1, a2)) { - a1.value = 0; - a1.fraction = 0; - return a1; + invalidate (diff); + return GNUNET_SYSERR; } + n1 = *a1; + n2 = *a2; + TALER_amount_normalize (&n1); + TALER_amount_normalize (&n2); - if (a1.fraction < a2.fraction) + if (n1.fraction < n2.fraction) { - if (0 == a1.value) + if (0 == n1.value) { - a1.fraction = 0; - return a1; + invalidate (diff); + return GNUNET_SYSERR; } - a1.fraction += AMOUNT_FRAC_BASE; - a1.value -= 1; + n1.fraction += TALER_AMOUNT_FRAC_BASE; + n1.value--; } - - a1.fraction -= a2.fraction; - a1.value -= a2.value; - - return a1; + if (n1.value < n2.value) + { + invalidate (diff); + return GNUNET_SYSERR; + } + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (a1->currency, + diff)); + GNUNET_assert (n1.fraction >= n2.fraction); + diff->fraction = n1.fraction - n2.fraction; + GNUNET_assert (n1.value >= n2.value); + diff->value = n1.value - n2.value; + if ( (0 == diff->fraction) && + (0 == diff->value) ) + return GNUNET_NO; + return GNUNET_OK; } /** - * Perform saturating addition of amounts. + * Perform addition of amounts. * + * @param sum where to store @a a1 + @a a2, set to "invalid" on overflow * @param a1 first amount to add * @param a2 second amount to add - * @return sum of a1 and a2 + * @return #GNUNET_OK if the addition worked, + * #GNUNET_SYSERR on overflow */ -struct TALER_Amount -TALER_amount_add (struct TALER_Amount a1, - struct TALER_Amount a2) +int +TALER_amount_add (struct TALER_Amount *sum, + const struct TALER_Amount *a1, + const struct TALER_Amount *a2) { - a1 = TALER_amount_normalize (a1); - a2 = TALER_amount_normalize (a2); - - a1.value += a2.value; - a1.fraction += a2.fraction; + struct TALER_Amount n1; + struct TALER_Amount n2; - if (0 == a1.currency[0]) + if (GNUNET_YES != + TALER_amount_cmp_currency (a1, a2)) { - memcpy (a2.currency, - a1.currency, - TALER_CURRENCY_LEN); - } - - if (0 == a2.currency[0]) - { - memcpy (a1.currency, - a2.currency, - TALER_CURRENCY_LEN); + invalidate (sum); + return GNUNET_SYSERR; } - - if ( (0 != a1.currency[0]) && - (0 != memcmp (a1.currency, - a2.currency, - TALER_CURRENCY_LEN)) ) + n1 = *a1; + n2 = *a2; + TALER_amount_normalize (&n1); + TALER_amount_normalize (&n2); + + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (a1->currency, + sum)); + sum->value = n1.value + n2.value; + if (sum->value < n1.value) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "adding mismatching currencies\n"); + /* integer overflow */ + invalidate (sum); + return GNUNET_SYSERR; } - - if (a1.value < a2.value) + sum->fraction = n1.fraction + n2.fraction; + if (GNUNET_SYSERR == + TALER_amount_normalize (sum)) { - a1.value = UINT32_MAX; - a2.value = UINT32_MAX; - return a1; + /* integer overflow via carry from fraction */ + invalidate (sum); + return GNUNET_SYSERR; } - - return TALER_amount_normalize (a1); + return GNUNET_OK; } /** * Normalize the given amount. * - * @param amout amount to normalize - * @return normalized amount + * @param amount amount to normalize + * @return #GNUNET_OK if normalization worked + * #GNUNET_NO if value was already normalized + * #GNUNET_SYSERR if value was invalid or could not be normalized */ -struct TALER_Amount -TALER_amount_normalize (struct TALER_Amount amount) +int +TALER_amount_normalize (struct TALER_Amount *amount) { - while ( (amount.value != UINT32_MAX) && - (amount.fraction >= AMOUNT_FRAC_BASE) ) + int ret; + + if (GNUNET_YES != test_valid (amount)) + return GNUNET_SYSERR; + ret = GNUNET_NO; + while ( (amount->value != UINT64_MAX) && + (amount->fraction >= TALER_AMOUNT_FRAC_BASE) ) { - amount.fraction -= AMOUNT_FRAC_BASE; - amount.value += 1; + amount->fraction -= TALER_AMOUNT_FRAC_BASE; + amount->value++; + ret = GNUNET_OK; } - return amount; + if (amount->fraction >= TALER_AMOUNT_FRAC_BASE) + { + /* failed to normalize, adding up fractions caused + main value to overflow! */ + return GNUNET_SYSERR; + } + return ret; } @@ -327,40 +451,40 @@ TALER_amount_normalize (struct TALER_Amount amount) * @return freshly allocated string representation */ char * -TALER_amount_to_string (struct TALER_Amount amount) +TALER_amount_to_string (const struct TALER_Amount *amount) { - char tail[AMOUNT_FRAC_LEN + 1] = { 0 }; - char curr[TALER_CURRENCY_LEN + 1] = { 0 }; - char *result = NULL; - int len; - - memcpy (curr, amount.currency, TALER_CURRENCY_LEN); - - amount = TALER_amount_normalize (amount); - if (0 != amount.fraction) + char *result; + uint32_t n; + char tail[TALER_AMOUNT_FRAC_LEN + 1]; + unsigned int i; + struct TALER_Amount norm; + + if (GNUNET_YES != test_valid (amount)) + return NULL; + norm = *amount; + GNUNET_break (GNUNET_SYSERR != + TALER_amount_normalize (&norm)); + if (0 != (n = norm.fraction)) { - unsigned int i; - uint32_t n = amount.fraction; - for (i = 0; (i < AMOUNT_FRAC_LEN) && (n != 0); i++) + for (i = 0; (i < TALER_AMOUNT_FRAC_LEN) && (0 != n); i++) { - tail[i] = '0' + (n / (AMOUNT_FRAC_BASE / 10)); - n = (n * 10) % (AMOUNT_FRAC_BASE); + tail[i] = '0' + (n / (TALER_AMOUNT_FRAC_BASE / 10)); + n = (n * 10) % (TALER_AMOUNT_FRAC_BASE); } - tail[i] = 0; - len = GNUNET_asprintf (&result, - "%s:%lu.%s", - curr, - (unsigned long) amount.value, - tail); + tail[i] = '\0'; + GNUNET_asprintf (&result, + "%s:%llu.%s", + norm.currency, + (unsigned long long) norm.value, + tail); } else { - len = GNUNET_asprintf (&result, - "%s:%lu", - curr, - (unsigned long) amount.value); + GNUNET_asprintf (&result, + "%s:%llu", + norm.currency, + (unsigned long long) norm.value); } - GNUNET_assert (len > 0); return result; } diff --git a/src/util/json.c b/src/util/json.c index 84fac4c98..7390eb474 100644 --- a/src/util/json.c +++ b/src/util/json.c @@ -48,14 +48,25 @@ * @return a json object describing the amount */ json_t * -TALER_JSON_from_amount (struct TALER_Amount amount) +TALER_JSON_from_amount (const struct TALER_Amount *amount) { json_t *j; - j = json_pack ("{s: s, s:I, s:I}", - "currency", amount.currency, - "value", (json_int_t) amount.value, - "fraction", (json_int_t) amount.fraction); + if ( (amount->value != (uint64_t) ((json_int_t) amount->value)) || + (0 > ((json_int_t) amount->value)) ) + { + /* Theoretically, json_int_t can be a 32-bit "long", or we might + have a 64-bit value which converted to a 63-bit signed long + long causes problems here. So we check. Note that depending + on the platform, the compiler may be able to statically tell + that at least the first check is always false. */ + GNUNET_break (0); + return NULL; + } + j = json_pack ("{s:s, s:I, s:I}", + "currency", amount->currency, + "value", (json_int_t) amount->value, + "fraction", (json_int_t) amount->fraction); GNUNET_assert (NULL != j); return j; } -- cgit v1.2.3 From 6ba63aab8472aefe85f4b96dd7bab895a46a0889 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 18 Mar 2015 18:56:48 +0100 Subject: fix #3716: make sure amount-API offers proper checks against overflow and other issues --- src/mint/mint_db.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c index 556d32af2..6832cdac9 100644 --- a/src/mint/mint_db.c +++ b/src/mint/mint_db.c @@ -1092,7 +1092,11 @@ TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, if (GNUNET_OK != TALER_MINT_DB_reserve_get (db_conn, &reserve)) goto rollback; - reserve.balance = TALER_amount_subtract (reserve.balance, withdraw); + if (GNUNET_SYSERR == + TALER_amount_subtract (&reserve.balance, + &reserve.balance, + &withdraw)) + goto rollback; if (GNUNET_OK != reserves_update (db_conn, &reserve)) goto rollback; if (GNUNET_OK == TALER_MINT_DB_commit (db_conn)) -- cgit v1.2.3 From 10f75510c003c8d176b6ce990c6afd0f21e02235 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Wed, 18 Mar 2015 18:57:36 +0100 Subject: fix #3716: make sure amount-API offers proper checks against overflow and other issues --- src/mint/test_mint_db.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index 6a55a1d35..2bb25aa6a 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -170,7 +170,7 @@ run (void *cls, char *const *args, const char *cfgfile, result = 4; FAILIF (GNUNET_OK != TALER_MINT_DB_reserves_in_insert (db, &reserve, - amount, + &amount, expiry)); FAILIF (GNUNET_OK != check_reserve (db, &reserve_pub, @@ -180,7 +180,7 @@ run (void *cls, char *const *args, const char *cfgfile, expiry.abs_value_us)); FAILIF (GNUNET_OK != TALER_MINT_DB_reserves_in_insert (db, &reserve, - amount, + &amount, expiry)); FAILIF (GNUNET_OK != check_reserve (db, &reserve_pub, -- cgit v1.2.3 From fe0a75eaa0da1cbb40e26a932f983e8be1903fb9 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 19 Mar 2015 14:23:43 +0100 Subject: use new GNUnet APIs to convert ECDSA to ECDHE keys --- src/mint/taler-mint-httpd_db.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index df525eecb..0c3675d38 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -739,6 +739,8 @@ check_commitment (struct MHD_Connection *connection, int res; struct TALER_LinkSecret last_shared_secret; int secret_initialized = GNUNET_NO; + struct GNUNET_CRYPTO_EcdhePublicKey coin_ecdhe; + struct GNUNET_CRYPTO_EcdhePrivateKey transfer_ecdhe; for (j = 0; j < num_oldcoins; j++) { @@ -779,18 +781,22 @@ check_commitment (struct MHD_Connection *connection, /* We're converting key types here, which is not very nice * but necessary and harmless (keys will be thrown away later). */ - /* FIXME: ECDHE/ECDSA-key type confusion! Can we reduce/avoid this? */ + GNUNET_CRYPTO_ecdsa_public_to_ecdhe (&melts[j].coin.coin_pub, + &coin_ecdhe); + GNUNET_CRYPTO_ecdsa_private_to_ecdhe (&transfer_privs[j], + &transfer_ecdhe); if (GNUNET_OK != - GNUNET_CRYPTO_ecc_ecdh ((const struct GNUNET_CRYPTO_EcdhePrivateKey *) &transfer_privs[j], - (const struct GNUNET_CRYPTO_EcdhePublicKey *) &melts[j].coin.coin_pub, + GNUNET_CRYPTO_ecc_ecdh (&transfer_ecdhe, + &coin_ecdhe, &transfer_secret.key)) { GNUNET_break (0); + GNUNET_CRYPTO_ecdhe_key_clear (&transfer_ecdhe); return (MHD_YES == TALER_MINT_reply_internal_error (connection, "ECDH error")) ? GNUNET_NO : GNUNET_SYSERR; } - + GNUNET_CRYPTO_ecdhe_key_clear (&transfer_ecdhe); if (GNUNET_OK != TALER_transfer_decrypt (&commit_link.shared_secret_enc, &transfer_secret, -- cgit v1.2.3 From 0414fb51a9f219c37afc06ad2b309711e360c485 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Thu, 19 Mar 2015 21:52:11 +0100 Subject: -link against libjansson --- src/mint/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index 8a392bc58..2436d7f37 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -128,4 +128,4 @@ test_mint_db_LDADD = \ libtalermint_common.la \ $(top_srcdir)/src/util/libtalerutil.la \ $(top_srcdir)/src/pq/libtalerpq.la \ - -lgnunetutil + -lgnunetutil -ljansson -- cgit v1.2.3 From 7d9a40327587ed99fb20f4c4a5669069c7a51e48 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 20 Mar 2015 23:51:28 +0100 Subject: first stab at establishing proper plugin API, main HTTP code compiles, other binaries FTBFS right now --- INSTALL | 12 +- configure.ac | 7 + src/include/taler_util.h | 12 + src/mint/Makefile.am | 21 +- src/mint/mint_db.c | 2241 --------------------------------- src/mint/mint_db.h | 976 --------------- src/mint/plugin.c | 183 +++ src/mint/plugin.h | 77 ++ src/mint/plugin_mintdb_postgres.c | 2316 +++++++++++++++++++++++++++++++++++ src/mint/taler-mint-dbinit.c | 2 +- src/mint/taler-mint-httpd.c | 13 +- src/mint/taler-mint-httpd_db.c | 324 +++-- src/mint/taler-mint-httpd_db.h | 2 +- src/mint/taler-mint-httpd_deposit.c | 2 +- src/mint/taler-mint-httpd_refresh.c | 2 +- src/mint/taler-mint-reservemod.c | 2 +- src/mint/taler_mintdb_plugin.h | 1002 +++++++++++++++ src/util/Makefile.am | 3 +- src/util/os_installation.c | 701 +++++++++++ 19 files changed, 4519 insertions(+), 3379 deletions(-) delete mode 100644 src/mint/mint_db.c delete mode 100644 src/mint/mint_db.h create mode 100644 src/mint/plugin.c create mode 100644 src/mint/plugin.h create mode 100644 src/mint/plugin_mintdb_postgres.c create mode 100644 src/mint/taler_mintdb_plugin.h create mode 100644 src/util/os_installation.c diff --git a/INSTALL b/INSTALL index a1e89e18a..209984075 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Installation Instructions ************************* -Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, +Copyright (C) 1994-1996, 1999-2002, 2004-2013 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, @@ -12,8 +12,8 @@ without warranty of any kind. Basic Installation ================== - Briefly, the shell commands `./configure; make; make install' should -configure, build, and install this package. The following + Briefly, the shell command `./configure && make && make install' +should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented @@ -309,9 +309,10 @@ causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to -an Autoconf bug. Until the bug is fixed you can use this workaround: +an Autoconf limitation. Until the limitation is lifted, you can use +this workaround: - CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== @@ -367,4 +368,3 @@ operates. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. - diff --git a/configure.ac b/configure.ac index 5835cb635..f69bcefd2 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,13 @@ AS_IF([test $libgnunetutil != 1], *** ]])]) +TALER_LIB_LDFLAGS="-export-dynamic -no-undefined" +TALER_PLUGIN_LDFLAGS="-export-dynamic -avoid-version -module -no-undefined" + +AC_SUBST(TALER_LIB_LDFLAGS) +AC_SUBST(TALER_PLUGIN_LDFLAGS) + + # check for libmicrohttpd microhttpd=0 AC_MSG_CHECKING([for microhttpd]) diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 3569bd782..e46583989 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -99,4 +99,16 @@ TALER_config_get_denom (struct GNUNET_CONFIGURATION_Handle *cfg, struct TALER_Amount *denom); +/** + * Get the path to a specific Taler installation directory or, with + * #GNUNET_OS_IPK_SELF_PREFIX, the current running apps installation + * directory. + * + * @param dirkind what kind of directory is desired? + * @return a pointer to the dir path (to be freed by the caller) + */ +char * +TALER_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind); + + #endif diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index 2436d7f37..c4f99af63 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -1,18 +1,31 @@ # This Makefile.am is in the public domain AM_CPPFLAGS = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/pq/ $(POSTGRESQL_CPPFLAGS) +plugindir = $(libdir)/taler + +plugin_LTLIBRARIES = \ + libtaler_plugin_mintdb_postgres.la + +libtaler_plugin_mintdb_postgres_la_SOURCES = \ + plugin_mintdb_postgres.c +libtaler_plugin_mintdb_postgres_la_LIBADD = \ + $(LTLIBINTL) +libtaler_plugin_mintdb_postgres_la_LDFLAGS = \ + $(TALER_PLUGIN_LDFLAGS) \ + -lpq \ + -lgnunetutil + lib_LTLIBRARIES = \ libtalermint_common.la -# Note: mint_db.c should become a plugin soon! (#3608) libtalermint_common_la_SOURCES = \ key_io.c key_io.h \ - mint_db.c + plugin.c plugin.h \ + taler_mintdb_plugin.h libtalermint_common_la_LIBADD = \ $(top_builddir)/src/util/libtalerutil.la \ - -lgnunetutil \ - -lpq + -lgnunetutil libtalermint_common_la_LDFLAGS = \ $(POSTGRESQL_LDFLAGS) \ diff --git a/src/mint/mint_db.c b/src/mint/mint_db.c deleted file mode 100644 index 6832cdac9..000000000 --- a/src/mint/mint_db.c +++ /dev/null @@ -1,2241 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) - - 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, If not, see -*/ - -/** - * @file mint_db.c - * @brief Low-level (statement-level) database access for the mint - * @author Florian Dold - * @author Christian Grothoff - * @author Sree Harsha Totakura - * - * TODO: - * - The mint_db.h-API should ideally be what we need to port - * when using other databases; so here we should enable - * alternative implementations by returning - * a more opaque DB handle. - */ -#include "platform.h" -#include "db_pq.h" -#include "taler_signatures.h" -#include "taler-mint-httpd_responses.h" -#include "mint_db.h" -#include - - -/** - * Thread-local database connection. - * Contains a pointer to PGconn or NULL. - */ -static pthread_key_t db_conn_threadlocal; - - -#define QUERY_ERR(result) \ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed at %s:%u: %s\n", __FILE__, __LINE__, PQresultErrorMessage (result)) - -/** - * Database connection string, as read from - * the configuration. - */ -static char *TALER_MINT_db_connection_cfg_str; - -#define BREAK_DB_ERR(result) do { \ - GNUNET_break(0); \ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Database failure: %s\n", PQresultErrorMessage (result)); \ - } while (0) - -/** - * Shorthand for exit jumps. - */ -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - - -#define SQLEXEC_(conn, sql, result) \ - do { \ - result = PQexec (conn, sql); \ - if (PGRES_COMMAND_OK != PQresultStatus (result)) \ - { \ - BREAK_DB_ERR (result); \ - PQclear (result); result = NULL; \ - goto SQLEXEC_fail; \ - } \ - PQclear (result); result = NULL; \ - } while (0) - -/** - * This the length of the currency strings (without 0-termination) we use. Note - * that we need to use this at the DB layer instead of TALER_CURRENCY_LEN as the - * DB only needs to store 3 bytes instead of 8 bytes. - */ -#define TALER_DB_CURRENCY_LEN 3 - -/** - * Set the given connection to use a temporary schema - * - * @param db the database connection - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon error - */ -static int -set_temporary_schema (PGconn *db) -{ - PGresult *result; - - SQLEXEC_(db, - "CREATE SCHEMA IF NOT EXISTS " TALER_TEMP_SCHEMA_NAME ";" - "SET search_path to " TALER_TEMP_SCHEMA_NAME ";", - result); - return GNUNET_OK; - SQLEXEC_fail: - return GNUNET_SYSERR; -} - - -/** - * Drop the temporary taler schema. This is only useful for testcases - * - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_drop_temporary (PGconn *db) -{ - PGresult *result; - - SQLEXEC_ (db, - "DROP SCHEMA " TALER_TEMP_SCHEMA_NAME " CASCADE;", - result); - return GNUNET_OK; - SQLEXEC_fail: - return GNUNET_SYSERR; -} - - -/** - * Create the necessary tables if they are not present - * - * @param temporary should we use a temporary schema - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_create_tables (int temporary) -{ - PGresult *result; - PGconn *conn; - - result = NULL; - conn = PQconnectdb (TALER_MINT_db_connection_cfg_str); - if (CONNECTION_OK != PQstatus (conn)) - { - LOG_ERROR ("Database connection failed: %s\n", - PQerrorMessage (conn)); - GNUNET_break (0); - return GNUNET_SYSERR; - } - if ((GNUNET_YES == temporary) - && (GNUNET_SYSERR == set_temporary_schema (conn))) - { - PQfinish (conn); - return GNUNET_SYSERR; - } -#define SQLEXEC(sql) SQLEXEC_(conn, sql, result); - /* reserves table is for summarization of a reserve. It is updated when new - funds are added and existing funds are withdrawn */ - SQLEXEC ("CREATE TABLE IF NOT EXISTS reserves" - "(" - " reserve_pub BYTEA PRIMARY KEY" - ",current_balance_value INT4 NOT NULL" - ",current_balance_fraction INT4 NOT NULL" - ",balance_currency VARCHAR(4) NOT NULL" - ",expiration_date INT8 NOT NULL" - ")"); - /* reserves_in table collects the transactions which transfer funds into the - reserve. The amount and expiration date for the corresponding reserve are - updated when new transfer funds are added. The rows of this table - correspond to each incoming transaction. */ - SQLEXEC("CREATE TABLE IF NOT EXISTS reserves_in" - "(" - " reserve_pub BYTEA REFERENCES reserves (reserve_pub) ON DELETE CASCADE" - ",balance_value INT4 NOT NULL" - ",balance_fraction INT4 NOT NULL" - ",balance_currency VARCHAR(4) NOT NULL" - ",expiration_date INT8 NOT NULL" - ");"); - /* Create an index on the foreign key as it is not created automatically by PSQL */ - SQLEXEC ("CREATE INDEX reserves_in_reserve_pub_index" - " ON reserves_in (reserve_pub);"); - SQLEXEC ("CREATE TABLE IF NOT EXISTS collectable_blindcoins" - "(" - "blind_ev BYTEA PRIMARY KEY" - ",denom_pub BYTEA NOT NULL" /* FIXME: Make this a foreign key? */ - ",denom_sig BYTEA NOT NULL" - ",reserve_pub BYTEA REFERENCES reserves (reserve_pub) ON DELETE CASCADE" - ",reserve_sig BYTEA NOT NULL" - ");"); - SQLEXEC ("CREATE INDEX collectable_blindcoins_reserve_pub_index ON" - " collectable_blindcoins (reserve_pub)"); - SQLEXEC("CREATE TABLE IF NOT EXISTS known_coins " - "(" - " coin_pub BYTEA NOT NULL PRIMARY KEY" - ",denom_pub BYTEA NOT NULL" - ",denom_sig BYTEA NOT NULL" - ",expended_value INT4 NOT NULL" - ",expended_fraction INT4 NOT NULL" - ",expended_currency VARCHAR(4) NOT NULL" - ",refresh_session_pub BYTEA" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions " - "(" - " session_pub BYTEA PRIMARY KEY CHECK (length(session_pub) = 32)" - ",session_melt_sig BYTEA" - ",session_commit_sig BYTEA" - ",noreveal_index INT2 NOT NULL" - // non-zero if all reveals were ok - // and the new coin signatures are ready - ",reveal_ok BOOLEAN NOT NULL DEFAULT false" - ") "); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_order " - "( " - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" - ",newcoin_index INT2 NOT NULL " - ",denom_pub BYTEA NOT NULL " - ",PRIMARY KEY (session_pub, newcoin_index)" - ") "); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link" - "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" - ",transfer_pub BYTEA NOT NULL" - ",link_secret_enc BYTEA NOT NULL" - // index of the old coin in the customer's request - ",oldcoin_index INT2 NOT NULL" - // index for cut and choose, - // ranges from 0 to kappa-1 - ",cnc_index INT2 NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_coin" - "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " - ",link_vector_enc BYTEA NOT NULL" - // index of the new coin in the customer's request - ",newcoin_index INT2 NOT NULL" - // index for cut and choose, - ",cnc_index INT2 NOT NULL" - ",coin_ev BYTEA NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_melt" - "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " - ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) " - ",denom_pub BYTEA NOT NULL " - ",oldcoin_index INT2 NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_collectable" - "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " - ",ev_sig BYTEA NOT NULL" - ",newcoin_index INT2 NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " - "( " - " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)" - ",denom_pub BYTEA NOT NULL" /* FIXME: Link this as a foreign key? */ - ",denom_sig BYTEA NOT NULL" - ",transaction_id INT8 NOT NULL" - ",amount_currency VARCHAR(4) NOT NULL" - ",amount_value INT4 NOT NULL" - ",amount_fraction INT4 NOT NULL" - ",merchant_pub BYTEA NOT NULL CHECK (length(merchant_pub)=32)" - ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)" - ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)" - ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)" - ",wire TEXT NOT NULL" - ")"); -#undef SQLEXEC - PQfinish (conn); - return GNUNET_OK; - - SQLEXEC_fail: - PQfinish (conn); - return GNUNET_SYSERR; -} - - -/** - * Setup prepared statements. - * - * @param db_conn connection handle to initialize - * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure - */ -int -TALER_MINT_DB_prepare (PGconn *db_conn) -{ - PGresult *result; - -#define PREPARE(name, sql, ...) \ - do { \ - result = PQprepare (db_conn, name, sql, __VA_ARGS__); \ - if (PGRES_COMMAND_OK != PQresultStatus (result)) \ - { \ - BREAK_DB_ERR (result); \ - PQclear (result); result = NULL; \ - return GNUNET_SYSERR; \ - } \ - PQclear (result); result = NULL; \ - } while (0); - - PREPARE ("get_reserve", - "SELECT " - "current_balance_value" - ",current_balance_fraction" - ",balance_currency " - ",expiration_date " - "FROM reserves " - "WHERE reserve_pub=$1 " - "LIMIT 1; ", - 1, NULL); - PREPARE ("create_reserve", - "INSERT INTO reserves (" - " reserve_pub," - " current_balance_value," - " current_balance_fraction," - " balance_currency," - " expiration_date) VALUES (" - "$1, $2, $3, $4, $5);", - 5, NULL); - PREPARE ("update_reserve", - "UPDATE reserves " - "SET" - " current_balance_value=$2 " - ",current_balance_fraction=$3 " - ",expiration_date=$4 " - "WHERE reserve_pub=$1 ", - 4, NULL); - PREPARE ("create_reserves_in_transaction", - "INSERT INTO reserves_in (" - " reserve_pub," - " balance_value," - " balance_fraction," - " balance_currency," - " expiration_date) VALUES (" - " $1, $2, $3, $4, $5);", - 5, NULL); - PREPARE ("get_reserves_in_transactions", - "SELECT" - " balance_value" - ",balance_fraction" - ",balance_currency" - ",expiration_date" - " FROM reserves_in WHERE reserve_pub=$1", - 1, NULL); - PREPARE ("insert_collectable_blindcoin", - "INSERT INTO collectable_blindcoins ( " - " blind_ev" - ",denom_pub, denom_sig" - ",reserve_pub, reserve_sig) " - "VALUES ($1, $2, $3, $4, $5)", - 5, NULL); - PREPARE ("get_collectable_blindcoin", - "SELECT " - " denom_pub, denom_sig" - ",reserve_sig, reserve_pub " - "FROM collectable_blindcoins " - "WHERE blind_ev = $1", - 1, NULL); - PREPARE ("get_reserves_blindcoins", - "select" - " blind_ev" - ",denom_pub, denom_sig" - ",reserve_sig" - " FROM collectable_blindcoins" - " WHERE reserve_pub=$1;", - 1, NULL); - - /* FIXME: does it make sense to store these computed values in the DB? */ -#if 0 - PREPARE ("get_refresh_session", - "SELECT " - " (SELECT count(*) FROM refresh_melt WHERE session_pub = $1)::INT2 as num_oldcoins " - ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_pub = $1 and cnc_index = 0)::INT2 as num_newcoins " - ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_pub = $1 and newcoin_index = 0)::INT2 as kappa " - ",noreveal_index" - ",session_commit_sig " - ",reveal_ok " - "FROM refresh_sessions " - "WHERE session_pub = $1", - 1, NULL); -#endif - - PREPARE ("get_known_coin", - "SELECT " - " coin_pub, denom_pub, denom_sig " - ",expended_value, expended_fraction, expended_currency " - ",refresh_session_pub " - "FROM known_coins " - "WHERE coin_pub = $1", - 1, NULL); - PREPARE ("update_known_coin", - "UPDATE known_coins " - "SET " - " denom_pub = $2 " - ",denom_sig = $3 " - ",expended_value = $4 " - ",expended_fraction = $5 " - ",expended_currency = $6 " - ",refresh_session_pub = $7 " - "WHERE " - " coin_pub = $1 ", - 7, NULL); - PREPARE ("insert_known_coin", - "INSERT INTO known_coins (" - " coin_pub" - ",denom_pub" - ",denom_sig" - ",expended_value" - ",expended_fraction" - ",expended_currency" - ",refresh_session_pub" - ")" - "VALUES ($1,$2,$3,$4,$5,$6,$7)", - 7, NULL); - PREPARE ("get_refresh_commit_link", - "SELECT " - " transfer_pub " - ",link_secret_enc " - "FROM refresh_commit_link " - "WHERE session_pub = $1 AND cnc_index = $2 AND oldcoin_index = $3", - 3, NULL); - PREPARE ("get_refresh_commit_coin", - "SELECT " - " link_vector_enc " - ",coin_ev " - "FROM refresh_commit_coin " - "WHERE session_pub = $1 AND cnc_index = $2 AND newcoin_index = $3", - 3, NULL); - PREPARE ("insert_refresh_order", - "INSERT INTO refresh_order ( " - " newcoin_index " - ",session_pub " - ",denom_pub " - ") " - "VALUES ($1, $2, $3) ", - 3, NULL); - PREPARE ("insert_refresh_melt", - "INSERT INTO refresh_melt ( " - " session_pub " - ",oldcoin_index " - ",coin_pub " - ",denom_pub " - ") " - "VALUES ($1, $2, $3, $4) ", - 3, NULL); - PREPARE ("get_refresh_order", - "SELECT denom_pub " - "FROM refresh_order " - "WHERE session_pub = $1 AND newcoin_index = $2", - 2, NULL); - PREPARE ("get_refresh_collectable", - "SELECT ev_sig " - "FROM refresh_collectable " - "WHERE session_pub = $1 AND newcoin_index = $2", - 2, NULL); - PREPARE ("get_refresh_melt", - "SELECT coin_pub " - "FROM refresh_melt " - "WHERE session_pub = $1 AND oldcoin_index = $2", - 2, NULL); - PREPARE ("insert_refresh_session", - "INSERT INTO refresh_sessions ( " - " session_pub " - ",noreveal_index " - ") " - "VALUES ($1, $2) ", - 2, NULL); - PREPARE ("insert_refresh_commit_link", - "INSERT INTO refresh_commit_link ( " - " session_pub " - ",transfer_pub " - ",cnc_index " - ",oldcoin_index " - ",link_secret_enc " - ") " - "VALUES ($1, $2, $3, $4, $5) ", - 5, NULL); - PREPARE ("insert_refresh_commit_coin", - "INSERT INTO refresh_commit_coin ( " - " session_pub " - ",coin_ev " - ",cnc_index " - ",newcoin_index " - ",link_vector_enc " - ") " - "VALUES ($1, $2, $3, $4, $5) ", - 5, NULL); - PREPARE ("insert_refresh_collectable", - "INSERT INTO refresh_collectable ( " - " session_pub " - ",newcoin_index " - ",ev_sig " - ") " - "VALUES ($1, $2, $3) ", - 3, NULL); - PREPARE ("set_reveal_ok", - "UPDATE refresh_sessions " - "SET reveal_ok = TRUE " - "WHERE session_pub = $1 ", - 1, NULL); - PREPARE ("get_link", - "SELECT link_vector_enc, ro.denom_pub, ev_sig " - "FROM refresh_melt rm " - " JOIN refresh_order ro USING (session_pub) " - " JOIN refresh_commit_coin rcc USING (session_pub) " - " JOIN refresh_sessions rs USING (session_pub) " - " JOIN refresh_collectable rc USING (session_pub) " - "WHERE rm.coin_pub = $1 " - "AND ro.newcoin_index = rcc.newcoin_index " - "AND ro.newcoin_index = rc.newcoin_index " - "AND rcc.cnc_index = rs.noreveal_index % ( " - " SELECT count(*) FROM refresh_commit_coin rcc2 " - " WHERE rcc2.newcoin_index = 0 AND rcc2.session_pub = rs.session_pub " - " ) ", - 1, NULL); - PREPARE ("get_transfer", - "SELECT transfer_pub, link_secret_enc " - "FROM refresh_melt rm " - " JOIN refresh_commit_link rcl USING (session_pub) " - " JOIN refresh_sessions rs USING (session_pub) " - "WHERE rm.coin_pub = $1 " - "AND rm.oldcoin_index = rcl.oldcoin_index " - "AND rcl.cnc_index = rs.noreveal_index % ( " - " SELECT count(*) FROM refresh_commit_coin rcc2 " - " WHERE newcoin_index = 0 AND rcc2.session_pub = rm.session_pub " - " ) ", - 1, NULL); - PREPARE ("insert_deposit", - "INSERT INTO deposits (" - "coin_pub," - "denom_pub," - "denom_sig," - "transaction_id," - "amount_value," - "amount_fraction," - "amount_currency," - "merchant_pub," - "h_contract," - "h_wire," - "coin_sig," - "wire" - ") VALUES (" - "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12" - ")", - 12, NULL); - PREPARE ("get_deposit", - "SELECT " - "coin_pub," - "denom_pub," - "transaction_id," - "amount_value," - "amount_fraction," - "amount_currency," - "merchant_pub," - "h_contract," - "h_wire," - "coin_sig" - " FROM deposits WHERE (" - "(coin_pub = $1) AND" - "(transaction_id = $2) AND" - "(merchant_pub = $3)" - ")", - 3, NULL); - return GNUNET_OK; -#undef PREPARE -} - - -/** - * Close thread-local database connection when a thread is destroyed. - * - * @param closure we get from pthreads (the db handle) - */ -static void -db_conn_destroy (void *cls) -{ - PGconn *db_conn = cls; - - if (NULL != db_conn) - PQfinish (db_conn); -} - - -/** - * Initialize database subsystem. - * - * @param connection_cfg configuration to use to talk to DB - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_init (const char *connection_cfg) -{ - if (0 != pthread_key_create (&db_conn_threadlocal, - &db_conn_destroy)) - { - LOG_ERROR ("Cannnot create pthread key.\n"); - return GNUNET_SYSERR; - } - TALER_MINT_db_connection_cfg_str = GNUNET_strdup (connection_cfg); - return GNUNET_OK; -} - - -/** - * Get the thread-local database-handle. - * Connect to the db if the connection does not exist yet. - * - * @param temporary #GNUNET_YES to use a temporary schema; #GNUNET_NO to use the - * database default one - * @return the database connection, or NULL on error - */ -PGconn * -TALER_MINT_DB_get_connection (int temporary) -{ - PGconn *db_conn; - - if (NULL != (db_conn = pthread_getspecific (db_conn_threadlocal))) - return db_conn; - db_conn = PQconnectdb (TALER_MINT_db_connection_cfg_str); - if (CONNECTION_OK != - PQstatus (db_conn)) - { - LOG_ERROR ("Database connection failed: %s\n", - PQerrorMessage (db_conn)); - GNUNET_break (0); - return NULL; - } - if ((GNUNET_YES == temporary) - && (GNUNET_SYSERR == set_temporary_schema(db_conn))) - { - GNUNET_break (0); - return NULL; - } - if (GNUNET_OK != - TALER_MINT_DB_prepare (db_conn)) - { - GNUNET_break (0); - return NULL; - } - if (0 != pthread_setspecific (db_conn_threadlocal, - db_conn)) - { - GNUNET_break (0); - return NULL; - } - return db_conn; -} - - -/** - * Start a transaction. - * - * @param db_conn the database connection - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_transaction (PGconn *db_conn) -{ - PGresult *result; - - result = PQexec (db_conn, - "BEGIN"); - if (PGRES_COMMAND_OK != - PQresultStatus (result)) - { - LOG_ERROR ("Failed to start transaction: %s\n", - PQresultErrorMessage (result)); - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Roll back the current transaction of a database connection. - * - * @param db_conn the database connection - * @return #GNUNET_OK on success - */ -void -TALER_MINT_DB_rollback (PGconn *db_conn) -{ - PGresult *result; - - result = PQexec (db_conn, - "ROLLBACK"); - GNUNET_break (PGRES_COMMAND_OK == - PQresultStatus (result)); - PQclear (result); -} - - -/** - * Commit the current transaction of a database connection. - * - * @param db_conn the database connection - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_commit (PGconn *db_conn) -{ - PGresult *result; - - result = PQexec (db_conn, - "COMMIT"); - if (PGRES_COMMAND_OK != - PQresultStatus (result)) - { - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Get the summary of a reserve. - * - * @param db the database connection handle - * @param reserve the reserve data. The public key of the reserve should be set - * in this structure; it is used to query the database. The balance - * and expiration are then filled accordingly. - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_reserve_get (PGconn *db, - struct Reserve *reserve) -{ - PGresult *result; - uint64_t expiration_date_nbo; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(reserve->pub), - TALER_DB_QUERY_PARAM_END - }; - - if (NULL == reserve->pub) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - result = TALER_DB_exec_prepared (db, - "get_reserve", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("expiration_date", &expiration_date_nbo), - TALER_DB_RESULT_SPEC_END - }; - EXITIF (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)); - EXITIF (GNUNET_OK != - TALER_DB_extract_amount (result, 0, - "current_balance_value", - "current_balance_fraction", - "balance_currency", - &reserve->balance)); - reserve->expiry.abs_value_us = GNUNET_ntohll (expiration_date_nbo); - PQclear (result); - return GNUNET_OK; - - EXITIF_exit: - PQclear (result); - return GNUNET_SYSERR; -} - - -/** - * Updates a reserve with the data from the given reserve structure. - * - * @param db the database connection - * @param reserve the reserve structure whose data will be used to update the - * corresponding record in the database. - * @return #GNUNET_OK upon successful update; #GNUNET_SYSERR upon any error - */ -int -reserves_update (PGconn *db, - struct Reserve *reserve) -{ - PGresult *result; - struct TALER_AmountNBO balance_nbo; - struct GNUNET_TIME_AbsoluteNBO expiry_nbo; - int ret; - - if ((NULL == reserve) || (NULL == reserve->pub)) - return GNUNET_SYSERR; - ret = GNUNET_OK; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), - TALER_DB_QUERY_PARAM_END - }; - TALER_amount_hton (&balance_nbo, - &reserve->balance); - expiry_nbo = GNUNET_TIME_absolute_hton (reserve->expiry); - result = TALER_DB_exec_prepared (db, - "update_reserve", - params); - if (PGRES_COMMAND_OK != PQresultStatus(result)) - { - QUERY_ERR (result); - ret = GNUNET_SYSERR; - } - PQclear (result); - return ret; -} - - -/** - * Insert a incoming transaction into reserves. New reserves are also created - * through this function. - * - * @param db the database connection handle - * @param reserve the reserve structure. The public key of the reserve should - * be set here. Upon successful execution of this function, the - * balance and expiration of the reserve will be updated. - * @param balance the amount that has to be added to the reserve - * @param expiry the new expiration time for the reserve - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failures - */ -int -TALER_MINT_DB_reserves_in_insert (PGconn *db, - struct Reserve *reserve, - const struct TALER_Amount *balance, - const struct GNUNET_TIME_Absolute expiry) -{ - struct TALER_AmountNBO balance_nbo; - struct GNUNET_TIME_AbsoluteNBO expiry_nbo; - PGresult *result; - int reserve_exists; - - result = NULL; - if (NULL == reserve) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != TALER_MINT_DB_transaction (db)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - reserve_exists = TALER_MINT_DB_reserve_get (db, reserve); - if (GNUNET_SYSERR == reserve_exists) - { - TALER_MINT_DB_rollback (db); - return GNUNET_SYSERR; - } - TALER_amount_hton (&balance_nbo, - balance); - expiry_nbo = GNUNET_TIME_absolute_hton (expiry); - if (GNUNET_NO == reserve_exists) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Reserve does not exist; creating a new one\n"); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_DB_QUERY_PARAM_PTR_SIZED (balance_nbo.currency, - TALER_DB_CURRENCY_LEN), - TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db, - "create_reserve", - params); - if (PGRES_COMMAND_OK != PQresultStatus(result)) - { - QUERY_ERR (result); - goto rollback; - } - } - if (NULL != result) - PQclear (result); - result = NULL; - /* create new incoming transaction */ - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_DB_QUERY_PARAM_PTR_SIZED (&balance_nbo.currency, - TALER_DB_CURRENCY_LEN), - TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db, - "create_reserves_in_transaction", - params); - if (PGRES_COMMAND_OK != PQresultStatus(result)) - { - QUERY_ERR (result); - goto rollback; - } - PQclear (result); - result = NULL; - if (GNUNET_NO == reserve_exists) - { - if (GNUNET_OK != TALER_MINT_DB_commit (db)) - return GNUNET_SYSERR; - reserve->balance = *balance; - reserve->expiry = expiry; - return GNUNET_OK; - } - /* Update reserve */ - struct Reserve updated_reserve; - updated_reserve.pub = reserve->pub; - - if (GNUNET_OK != - TALER_amount_add (&updated_reserve.balance, - &reserve->balance, - balance)) - { - return GNUNET_SYSERR; - } - updated_reserve.expiry = GNUNET_TIME_absolute_max (expiry, reserve->expiry); - if (GNUNET_OK != reserves_update (db, &updated_reserve)) - goto rollback; - if (GNUNET_OK != TALER_MINT_DB_commit (db)) - return GNUNET_SYSERR; - reserve->balance = updated_reserve.balance; - reserve->expiry = updated_reserve.expiry; - return GNUNET_OK; - - rollback: - PQclear (result); - TALER_MINT_DB_rollback (db); - return GNUNET_SYSERR; -} - - -/** - * Locate the response for a /withdraw request under the - * key of the hash of the blinded message. - * - * @param db_conn database connection to use - * @param h_blind hash of the blinded message - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return #GNUNET_SYSERR on internal error - * #GNUNET_NO if the collectable was not found - * #GNUNET_YES on success - */ -int -TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, - const struct GNUNET_HashCode *h_blind, - struct CollectableBlindcoin *collectable) -{ - PGresult *result; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (h_blind), - TALER_DB_QUERY_PARAM_END - }; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - struct GNUNET_CRYPTO_rsa_Signature *denom_sig; - char *denom_pub_enc; - char *denom_sig_enc; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; - int ret; - - ret = GNUNET_SYSERR; - denom_pub = NULL; - denom_pub_enc = NULL; - denom_sig_enc = NULL; - result = TALER_DB_exec_prepared (db_conn, - "get_collectable_blindcoin", - params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - goto cleanup; - } - if (0 == PQntuples (result)) - { - ret = GNUNET_NO; - goto cleanup; - } - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR("denom_pub", &denom_pub_enc, &denom_pub_enc_size), - TALER_DB_RESULT_SPEC_VAR("denom_sig", &denom_sig_enc, &denom_sig_enc_size), - TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig), - TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) - { - GNUNET_break (0); - goto cleanup; - } - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, - denom_pub_enc_size); - denom_sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, - denom_sig_enc_size); - if ((NULL == denom_pub) || (NULL == denom_sig)) - { - GNUNET_break (0); - goto cleanup; - } - collectable->denom_pub = denom_pub; - collectable->sig = denom_sig; - ret = GNUNET_YES; - - cleanup: - PQclear (result); - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); - if (GNUNET_YES != ret) - { if (NULL != denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (denom_pub); - if (NULL != denom_sig) - GNUNET_CRYPTO_rsa_signature_free (denom_sig); - } - return ret; -} - - -/** - * Store collectable bit coin under the corresponding - * hash of the blinded message. - * - * @param db_conn database connection to use - * @param h_blind hash of the blinded message - * @param withdraw amount by which the reserve will be withdrawn with this - * transaction - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return #GNUNET_SYSERR on internal error - * #GNUNET_NO if the collectable was not found - * #GNUNET_YES on success - */ -int -TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, - const struct GNUNET_HashCode *h_blind, - struct TALER_Amount withdraw, - const struct CollectableBlindcoin *collectable) -{ - PGresult *result; - struct Reserve reserve; - char *denom_pub_enc = NULL; - char *denom_sig_enc = NULL; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; - int ret; - - ret = GNUNET_SYSERR; - denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub, - &denom_pub_enc); - denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, - &denom_sig_enc); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (h_blind), - TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size - 1), - TALER_DB_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size - 1), /* DB doesn't like the trailing \0 */ - TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub), - TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig), - TALER_DB_QUERY_PARAM_END - }; - if (GNUNET_OK != TALER_MINT_DB_transaction (db_conn)) - goto cleanup; - result = TALER_DB_exec_prepared (db_conn, - "insert_collectable_blindcoin", - params); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - goto rollback; - } - reserve.pub = (struct GNUNET_CRYPTO_EddsaPublicKey *) - &collectable->reserve_pub; - if (GNUNET_OK != TALER_MINT_DB_reserve_get (db_conn, - &reserve)) - goto rollback; - if (GNUNET_SYSERR == - TALER_amount_subtract (&reserve.balance, - &reserve.balance, - &withdraw)) - goto rollback; - if (GNUNET_OK != reserves_update (db_conn, &reserve)) - goto rollback; - if (GNUNET_OK == TALER_MINT_DB_commit (db_conn)) - { - ret = GNUNET_OK; - goto cleanup; - } - - rollback: - TALER_MINT_DB_rollback(db_conn); - cleanup: - PQclear (result); - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); - return ret; -} - - -/** - * Get all of the transaction history associated with the specified - * reserve. - * - * @param db_conn connection to use - * @param reserve_pub public key of the reserve - * @return known transaction history (NULL if reserve is unknown) - */ -struct ReserveHistory * -TALER_MINT_DB_get_reserve_history (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) -{ - PGresult *result; - struct ReserveHistory *rh; - struct ReserveHistory *rh_head; - int rows; - int ret; - - result = NULL; - rh = NULL; - rh_head = NULL; - ret = GNUNET_SYSERR; - { - struct BankTransfer *bt; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve_pub), - TALER_DB_QUERY_PARAM_END - }; - - result = TALER_DB_exec_prepared (db_conn, - "get_reserves_in_transactions", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - goto cleanup; - } - if (0 == (rows = PQntuples (result))) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Asked to fetch history for an unknown reserve.\n"); - goto cleanup; - } - while (0 < rows) - { - bt = GNUNET_new (struct BankTransfer); - if (GNUNET_OK != TALER_DB_extract_amount (result, - --rows, - "balance_value", - "balance_fraction", - "balance_currency", - &bt->amount)) - { - GNUNET_free (bt); - GNUNET_break (0); - goto cleanup; - } - (void) memcpy (&bt->reserve_pub, reserve_pub, sizeof (bt->reserve_pub)); - if (NULL != rh_head) - { - rh_head->next = GNUNET_new (struct ReserveHistory); - rh_head = rh_head->next; - } - else - { - rh_head = GNUNET_new (struct ReserveHistory); - rh = rh_head; - } - rh_head->type = TALER_MINT_DB_RO_BANK_TO_MINT; - rh_head->details.bank = bt; - } - } - PQclear (result); - result = NULL; - { - struct GNUNET_HashCode blind_ev; - struct GNUNET_CRYPTO_EddsaSignature reserve_sig; - struct CollectableBlindcoin *cbc; - char *denom_pub_enc; - char *denom_sig_enc; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; - - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve_pub), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, - "get_reserves_blindcoins", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - goto cleanup; - } - if (0 == (rows = PQntuples (result))) - { - ret = GNUNET_OK; /* Its OK if there are no withdrawls yet */ - goto cleanup; - } - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC ("blind_ev", &blind_ev), - TALER_DB_RESULT_SPEC_VAR ("denom_pub", &denom_pub_enc, &denom_pub_enc_size), - TALER_DB_RESULT_SPEC_VAR ("denom_sig", &denom_sig_enc, &denom_sig_enc_size), - TALER_DB_RESULT_SPEC ("reserve_sig", &reserve_sig), - TALER_DB_RESULT_SPEC_END - }; - GNUNET_assert (NULL != rh); - GNUNET_assert (NULL != rh_head); - GNUNET_assert (NULL == rh_head->next); - while (0 < rows) - { - if (GNUNET_YES != TALER_DB_extract_result (result, rs, --rows)) - { - GNUNET_break (0); - goto cleanup; - } - cbc = GNUNET_new (struct CollectableBlindcoin); - cbc->sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, - denom_sig_enc_size); - GNUNET_free (denom_sig_enc); - denom_sig_enc = NULL; - cbc->denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, - denom_pub_enc_size); - GNUNET_free (denom_pub_enc); - denom_pub_enc = NULL; - if ((NULL == cbc->sig) || (NULL == cbc->denom_pub)) - { - if (NULL != cbc->sig) - GNUNET_CRYPTO_rsa_signature_free (cbc->sig); - if (NULL != cbc->denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); - GNUNET_free (cbc); - GNUNET_break (0); - goto cleanup; - } - (void) memcpy (&cbc->h_coin_envelope, &blind_ev, sizeof (blind_ev)); - (void) memcpy (&cbc->reserve_pub, reserve_pub, sizeof (cbc->reserve_pub)); - (void) memcpy (&cbc->reserve_sig, &reserve_sig, sizeof (cbc->reserve_sig)); - rh_head->next = GNUNET_new (struct ReserveHistory); - rh_head = rh_head->next; - rh_head->type = TALER_MINT_DB_RO_WITHDRAW_COIN; - rh_head->details.withdraw = cbc; - } - } - ret = GNUNET_OK; - - cleanup: - if (NULL != result) - PQclear (result); - if (GNUNET_SYSERR == ret) - { - TALER_MINT_DB_free_reserve_history (rh); - rh = NULL; - } - return rh; -} - - -/** - * Free memory associated with the given reserve history. - * - * @param rh history to free. - */ -void -TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh) -{ - struct BankTransfer *bt; - struct CollectableBlindcoin *cbc; - struct ReserveHistory *backref; - - while (NULL != rh) - { - switch(rh->type) - { - case TALER_MINT_DB_RO_BANK_TO_MINT: - bt = rh->details.bank; - if (NULL != bt->wire) - json_decref ((json_t *) bt->wire); /* FIXME: avoid cast? */ - GNUNET_free (bt); - break; - case TALER_MINT_DB_RO_WITHDRAW_COIN: - cbc = rh->details.withdraw; - GNUNET_CRYPTO_rsa_signature_free (cbc->sig); - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); - GNUNET_free (cbc); - break; - } - backref = rh; - rh = rh->next; - GNUNET_free (backref); - } -} - - -/** - * Check if we have the specified deposit already in the database. - * - * @param db_conn database connection - * @param deposit deposit to search for - * @return #GNUNET_YES if we know this operation, - * #GNUNET_NO if this deposit is unknown to us - */ -int -TALER_MINT_DB_have_deposit (PGconn *db_conn, - const struct Deposit *deposit) -{ - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), - TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), - TALER_DB_QUERY_PARAM_END - }; - PGresult *result; - int ret; - - ret = GNUNET_SYSERR; - result = TALER_DB_exec_prepared (db_conn, - "get_deposit", - params); - if (PGRES_TUPLES_OK != - PQresultStatus (result)) - { - BREAK_DB_ERR (result); - goto cleanup; - } - - if (0 == PQntuples (result)) - { - ret = GNUNET_NO; - goto cleanup; - } - ret = GNUNET_YES; - - cleanup: - PQclear (result); - return ret; -} - - -/** - * Insert information about deposited coin into the - * database. - * - * @param db_conn connection to the database - * @param deposit deposit information to store - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_insert_deposit (PGconn *db_conn, - const struct Deposit *deposit) -{ - char *denom_pub_enc; - char *denom_sig_enc; - char *json_wire_enc; - PGresult *result; - struct TALER_AmountNBO amount_nbo; - size_t denom_pub_enc_size; - size_t denom_sig_enc_size; - int ret; - - ret = GNUNET_SYSERR; - denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub, - &denom_pub_enc); - denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig, - &denom_sig_enc); - json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); - TALER_amount_hton (&amount_nbo, - &deposit->amount); - struct TALER_DB_QueryParam params[]= { - TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), - TALER_DB_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size), - TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), - TALER_DB_QUERY_PARAM_PTR (&amount_nbo.value), - TALER_DB_QUERY_PARAM_PTR (&amount_nbo.fraction), - TALER_DB_QUERY_PARAM_PTR_SIZED (amount_nbo.currency, - TALER_CURRENCY_LEN - 1), - TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), - TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract), - TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire), - TALER_DB_QUERY_PARAM_PTR (&deposit->csig), - TALER_DB_QUERY_PARAM_PTR_SIZED (json_wire_enc, - strlen (json_wire_enc)), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, "insert_deposit", params); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - goto cleanup; - } - ret = GNUNET_OK; - - cleanup: - PQclear (result); - GNUNET_free_non_null (denom_pub_enc); - GNUNET_free_non_null (denom_sig_enc); - GNUNET_free_non_null (json_wire_enc); - return ret; -} - - -/** - * Lookup refresh session data under the given public key. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use for the lookup - * @param session[OUT] where to store the result - * @return #GNUNET_YES on success, - * #GNUNET_NO if not found, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_get_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - struct RefreshSession *session) -{ - // FIXME: check logic! - int res; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_session", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Query failed: %s\n", - PQresultErrorMessage (result)); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - return GNUNET_NO; - - GNUNET_assert (1 == PQntuples (result)); - - /* We're done if the caller is only interested in - * whether the session exists or not */ - - if (NULL == session) - return GNUNET_YES; - - memset (session, 0, sizeof (struct RefreshSession)); - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("num_oldcoins", &session->num_oldcoins), - TALER_DB_RESULT_SPEC("num_newcoins", &session->num_newcoins), - TALER_DB_RESULT_SPEC("kappa", &session->kappa), - TALER_DB_RESULT_SPEC("noreveal_index", &session->noreveal_index), - TALER_DB_RESULT_SPEC_END - }; - - res = TALER_DB_extract_result (result, rs, 0); - - if (GNUNET_OK != res) - { - GNUNET_break (0); - PQclear (result); - return GNUNET_SYSERR; - } - - session->num_oldcoins = ntohs (session->num_oldcoins); - session->num_newcoins = ntohs (session->num_newcoins); - session->kappa = ntohs (session->kappa); - session->noreveal_index = ntohs (session->noreveal_index); - - PQclear (result); - return GNUNET_YES; -} - - -/** - * Store new refresh session data under the given public key. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param session session data to store - * @return #GNUNET_YES on success, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_create_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct RefreshSession *session) -{ - // FIXME: actually store session data! - uint16_t noreveal_index; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), - TALER_DB_QUERY_PARAM_PTR(&noreveal_index), - TALER_DB_QUERY_PARAM_END - }; - - noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15); - noreveal_index = htonl (noreveal_index); - - PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_session", params); - - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Store the given /refresh/melt request in the database. - * - * @param db_conn database connection - * @param session session key of the melt operation - * @param oldcoin_index index of the coin to store - * @param melt melt operation - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session, - uint16_t oldcoin_index, - const struct RefreshMelt *melt) -{ - // FIXME: check logic! - uint16_t oldcoin_index_nbo = htons (oldcoin_index); - char *buf; - size_t buf_size; - PGresult *result; - - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub, - &buf); - { - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session), - TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&melt->coin.coin_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, "insert_refresh_melt", params); - } - GNUNET_free (buf); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - PQclear (result); - return GNUNET_OK; -} - - -/** - * Get information about melted coin details from the database. - * - * @param db_conn database connection - * @param session session key of the melt operation - * @param oldcoin_index index of the coin to retrieve - * @param melt melt data to fill in - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_get_refresh_melt (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session, - uint16_t oldcoin_index, - struct RefreshMelt *melt) -{ - // FIXME: check logic! - GNUNET_break (0); - return GNUNET_SYSERR; -} - - -/** - * Store in the database which coin(s) we want to create - * in a given refresh operation. - * - * @param db_conn database connection - * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) -{ - // FIXME: check logic - uint16_t newcoin_index_nbo = htons (newcoin_index); - char *buf; - size_t buf_size; - PGresult *result; - - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, - &buf); - - { - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR (session_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED (buf, buf_size), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, - "insert_refresh_order", - params); - } - GNUNET_free (buf); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - if (0 != strcmp ("1", PQcmdTuples (result))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - PQclear (result); - return GNUNET_OK; -} - - -/** - * Lookup in the database the @a newcoin_index coin that we want to - * create in the given refresh operation. - * - * @param db_conn database connection - * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return NULL on error (not found or internal error) - */ -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_MINT_DB_get_refresh_order (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index) -{ - // FIXME: check logic - char *buf; - size_t buf_size; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - uint16_t newcoin_index_nbo = htons (newcoin_index); - - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), - TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_order", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return NULL; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - /* FIXME: may want to distinguish between different error cases! */ - return NULL; - } - GNUNET_assert (1 == PQntuples (result)); - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR ("denom_pub", &buf, &buf_size), - TALER_DB_RESULT_SPEC_END - }; - if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_break (0); - return NULL; - } - PQclear (result); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); - GNUNET_free (buf); - return denom_pub; -} - - - -/** - * Store information about the commitment of the - * given coin for the given refresh session in the database. - * - * @param db_conn database connection to use - * @param refresh_session_pub refresh session this commitment belongs to - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin coin commitment to store - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_insert_refresh_commit_coin (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitCoin *commit_coin) -{ - // FIXME: check logic! - uint16_t cnc_index_nbo = htons (i); - uint16_t newcoin_index_nbo = htons (j); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->coin_ev, commit_coin->coin_ev_size), - TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->refresh_link->coin_priv_enc, - commit_coin->refresh_link->blinding_key_enc_size + - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "insert_refresh_commit_coin", params); - - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 != strcmp ("1", PQcmdTuples (result))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Obtain information about the commitment of the - * given coin of the given refresh session from the database. - * - * @param db_conn database connection to use - * @param refresh_session_pub refresh session the commitment belongs to - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin[OUT] coin commitment to return - * @return #GNUNET_OK on success - * #GNUNET_NO if not found - * #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_get_refresh_commit_coin (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int cnc_index, - unsigned int newcoin_index, - struct RefreshCommitCoin *cc) -{ - // FIXME: check logic! - uint16_t cnc_index_nbo = htons (cnc_index); - uint16_t newcoin_index_nbo = htons (newcoin_index); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_END - }; - char *c_buf; - size_t c_buf_size; - char *rl_buf; - size_t rl_buf_size; - struct TALER_RefreshLinkEncrypted *rl; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_refresh_commit_coin", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR("coin_ev", &c_buf, &c_buf_size), - TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &rl_buf, &rl_buf_size), - TALER_DB_RESULT_SPEC_END - }; - if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - return GNUNET_SYSERR; - } - PQclear (result); - if (rl_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) - { - GNUNET_free (c_buf); - GNUNET_free (rl_buf); - return GNUNET_SYSERR; - } - rl = TALER_refresh_link_encrypted_decode (rl_buf, - rl_buf_size); - GNUNET_free (rl_buf); - cc->refresh_link = rl; - cc->coin_ev = c_buf; - cc->coin_ev_size = c_buf_size; - return GNUNET_YES; -} - - -/** - * Store the commitment to the given (encrypted) refresh link data - * for the given refresh session. - * - * @param db_conn database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param commit_link link information to store - * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success - */ -int -TALER_MINT_DB_insert_refresh_commit_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitLink *commit_link) -{ - // FIXME: check logic! - uint16_t cnc_index_nbo = htons (i); - uint16_t oldcoin_index_nbo = htons (j); - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_PTR(&commit_link->transfer_pub), - TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&commit_link->shared_secret_enc), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, - "insert_refresh_commit_link", - params); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 != strcmp ("1", PQcmdTuples (result))) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Obtain the commited (encrypted) refresh link data - * for the given refresh session. - * - * @param db_conn database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param cc[OUT] link information to return - * @return #GNUNET_SYSERR on internal error, - * #GNUNET_NO if commitment was not found - * #GNUNET_OK on success - */ -int -TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int cnc_index, - unsigned int oldcoin_index, - struct RefreshCommitLink *cc) -{ - // FIXME: check logic! - uint16_t cnc_index_nbo = htons (cnc_index); - uint16_t oldcoin_index_nbo = htons (oldcoin_index); - - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, - "get_refresh_commit_link", - params); - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("transfer_pub", &cc->transfer_pub), - TALER_DB_RESULT_SPEC("link_secret_enc", &cc->shared_secret_enc), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_free (cc); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - -/** - * Insert signature of a new coin generated during refresh into - * the database indexed by the refresh session and the index - * of the coin. This data is later used should an old coin - * be used to try to obtain the private keys during "/refresh/link". - * - * @param db_conn database connection - * @param session_pub refresh session - * @param newcoin_index coin index - * @param ev_sig coin signature - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) -{ - // FIXME: check logic! - uint16_t newcoin_index_nbo = htons (newcoin_index); - char *buf; - size_t buf_size; - PGresult *result; - - buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, - &buf); - { - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), - TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), - TALER_DB_QUERY_PARAM_END - }; - result = TALER_DB_exec_prepared (db_conn, - "insert_refresh_collectable", - params); - } - GNUNET_free (buf); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - PQclear (result); - return GNUNET_OK; -} - - -/** - * Obtain the link data of a coin, that is the encrypted link - * information, the denomination keys and the signatures. - * - * @param db_conn database connection - * @param coin_pub public key to use to retrieve linkage data - * @return all known link data for the coin - */ -struct LinkDataList * -TALER_db_get_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) -{ - // FIXME: check logic! - struct LinkDataList *ldl; - struct LinkDataList *pos; - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(coin_pub), - TALER_DB_QUERY_PARAM_END - }; - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_link", params); - - ldl = NULL; - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return NULL; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return NULL; - } - - - int i = 0; - - for (i = 0; i < PQntuples (result); i++) - { - struct TALER_RefreshLinkEncrypted *link_enc; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - struct GNUNET_CRYPTO_rsa_Signature *sig; - char *ld_buf; - size_t ld_buf_size; - char *pk_buf; - size_t pk_buf_size; - char *sig_buf; - size_t sig_buf_size; - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &ld_buf, &ld_buf_size), - TALER_DB_RESULT_SPEC_VAR("denom_pub", &pk_buf, &pk_buf_size), - TALER_DB_RESULT_SPEC_VAR("ev_sig", &sig_buf, &sig_buf_size), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_DB_extract_result (result, rs, i)) - { - PQclear (result); - GNUNET_break (0); - TALER_db_link_data_list_free (ldl); - return NULL; - } - if (ld_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) - { - PQclear (result); - GNUNET_free (pk_buf); - GNUNET_free (sig_buf); - GNUNET_free (ld_buf); - TALER_db_link_data_list_free (ldl); - return NULL; - } - // FIXME: use util API for this! - link_enc = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + - ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); - link_enc->blinding_key_enc = (const char *) &link_enc[1]; - link_enc->blinding_key_enc_size = ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); - memcpy (link_enc->coin_priv_enc, - ld_buf, - ld_buf_size); - - sig = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, - sig_buf_size); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, - pk_buf_size); - GNUNET_free (pk_buf); - GNUNET_free (sig_buf); - GNUNET_free (ld_buf); - if ( (NULL == sig) || - (NULL == denom_pub) ) - { - if (NULL != denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (denom_pub); - if (NULL != sig) - GNUNET_CRYPTO_rsa_signature_free (sig); - GNUNET_free (link_enc); - GNUNET_break (0); - PQclear (result); - TALER_db_link_data_list_free (ldl); - return NULL; - } - pos = GNUNET_new (struct LinkDataList); - pos->next = ldl; - pos->link_data_enc = link_enc; - pos->denom_pub = denom_pub; - pos->ev_sig = sig; - ldl = pos; - } - return ldl; -} - - -/** - * Free memory of the link data list. - * - * @param ldl link data list to release - */ -void -TALER_db_link_data_list_free (struct LinkDataList *ldl) -{ - GNUNET_break (0); // FIXME -} - - -/** - * Obtain shared secret and transfer public key from the public key of - * the coin. This information and the link information returned by - * #TALER_db_get_link() enable the owner of an old coin to determine - * the private keys of the new coins after the melt. - * - * - * @param db_conn database connection - * @param coin_pub public key of the coin - * @param transfer_pub[OUT] public transfer key - * @param shared_secret_enc[OUT] set to shared secret - * @return #GNUNET_OK on success, - * #GNUNET_NO on failure (not found) - * #GNUNET_SYSERR on internal failure (database issue) - */ -int -TALER_db_get_transfer (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, - struct TALER_EncryptedLinkSecret *shared_secret_enc) -{ - // FIXME: check logic! - struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(coin_pub), - TALER_DB_QUERY_PARAM_END - }; - - PGresult *result = TALER_DB_exec_prepared (db_conn, "get_transfer", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - return GNUNET_NO; - } - - if (1 != PQntuples (result)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "got %d tuples for get_transfer\n", - PQntuples (result)); - GNUNET_break (0); - return GNUNET_SYSERR; - } - - struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("transfer_pub", transfer_pub), - TALER_DB_RESULT_SPEC("link_secret_enc", shared_secret_enc), - TALER_DB_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_break (0); - return GNUNET_SYSERR; - } - - PQclear (result); - return GNUNET_OK; -} - - - - -/** - * Compile a list of all (historic) transactions performed - * with the given coin (/refresh/melt and /deposit operations). - * - * @param db_conn database connection - * @param coin_pub coin to investigate - * @return list of transactions, NULL if coin is fresh - */ -struct TALER_MINT_DB_TransactionList * -TALER_MINT_DB_get_coin_transactions (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) -{ - // FIXME: check logic! - GNUNET_break (0); // FIXME: implement! - return NULL; -} - - -/** - * Free linked list of transactions. - * - * @param list list to free - */ -void -TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list) -{ - // FIXME: check logic! - GNUNET_break (0); -} - - -/* end of mint_db.c */ diff --git a/src/mint/mint_db.h b/src/mint/mint_db.h deleted file mode 100644 index d11ee8fe9..000000000 --- a/src/mint/mint_db.h +++ /dev/null @@ -1,976 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) - - 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, If not, see -*/ -/** - * @file mint/mint_db.h - * @brief Low-level (statement-level) database access for the mint - * @author Florian Dold - * @author Christian Grothoff - */ -#ifndef MINT_DB_H -#define MINT_DB_H - -#include -#include -#include -#include "taler_util.h" - -#define TALER_TEMP_SCHEMA_NAME "taler_temporary" - -/** - * Initialize database subsystem. - * - * @param connection_cfg configuration for the DB - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_init (const char *connection_cfg); - - -/** - * Get the thread-local database-handle. - * Connect to the db if the connection does not exist yet. - * - * @param temporary #GNUNET_YES to use a temporary schema; #GNUNET_NO to use the - * database default one - * @param the database connection, or NULL on error - */ -PGconn * -TALER_MINT_DB_get_connection (int temporary); - - -/** - * Drop the temporary taler schema. This is only useful for testcases - * - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_drop_temporary (PGconn *db); - - -/** - * Create the necessary tables if they are not present - * - * @param temporary should we use a temporary schema - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_create_tables (int temporary); - -/** - * Setup prepared statements. FIXME: should this be part of the API, - * or just internal to "TALER_MINT_DB_get_connection()"? - * - * @param db_conn connection handle to initialize - * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure - */ -int -TALER_MINT_DB_prepare (PGconn *db_conn); - - -/** - * Start a transaction. - * - * @param db_conn connection to use - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_transaction (PGconn *db_conn); - - -/** - * Commit a transaction. - * - * @param db_conn connection to use - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_commit (PGconn *db_conn); - - -/** - * Abort/rollback a transaction. - * - * @param db_conn connection to use - */ -void -TALER_MINT_DB_rollback (PGconn *db_conn); - - -/** - * Information we keep on bank transfer(s) that established a reserve. - */ -struct BankTransfer -{ - - /** - * Public key of the reserve that was filled. - */ - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; - - /** - * Amount that was transferred to the mint. - */ - struct TALER_Amount amount; - - /** - * Detailed wire information about the transaction. - */ - const json_t *wire; - -}; - - -/* FIXME: add functions to add bank transfers to our DB - (and to test if we already did add one) (#3633/#3717) */ - -/** - * A summary of a Reserve - */ -struct Reserve -{ - /** - * The reserve's public key. This uniquely identifies the reserve - */ - struct GNUNET_CRYPTO_EddsaPublicKey *pub; - - /** - * The balance amount existing in the reserve - */ - struct TALER_Amount balance; - - /** - * The expiration date of this reserve - */ - struct GNUNET_TIME_Absolute expiry; -}; - - -/** - * Information we keep for a withdrawn coin to reproduce - * the /withdraw operation if needed, and to have proof - * that a reserve was drained by this amount. - */ -struct CollectableBlindcoin -{ - - /** - * Our signature over the (blinded) coin. - */ - struct GNUNET_CRYPTO_rsa_Signature *sig; - - /** - * Denomination key (which coin was generated). - */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - - /** - * Public key of the reserve that was drained. - */ - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; - - /** - * Hash over the blinded message, needed to verify - * the @e reserve_sig. - */ - struct GNUNET_HashCode h_coin_envelope; - - /** - * Signature confirming the withdrawl, matching @e reserve_pub, - * @e denom_pub and @e h_coin_envelope. - */ - struct GNUNET_CRYPTO_EddsaSignature reserve_sig; -}; - - -/** - * Get the summary of a reserve. - * - * @param db the database connection handle - * @param reserve the reserve data. The public key of the reserve should be set - * in this structure; it is used to query the database. The balance - * and expiration are then filled accordingly. - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_MINT_DB_reserve_get (PGconn *db, - struct Reserve *reserve); - - -/** - * Insert a incoming transaction into reserves. New reserves are also created - * through this function. - * - * @param db the database connection handle - * @param reserve the reserve structure. The public key of the reserve should - * be set here. Upon successful execution of this function, the - * balance and expiration of the reserve will be updated. - * @param balance the amount that has to be added to the reserve - * @param expiry the new expiration time for the reserve - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failures - */ -int -TALER_MINT_DB_reserves_in_insert (PGconn *db, - struct Reserve *reserve, - const struct TALER_Amount *balance, - const struct GNUNET_TIME_Absolute expiry); - - -/** - * Locate the response for a /withdraw request under the - * key of the hash of the blinded message. - * - * @param db_conn database connection to use - * @param h_blind hash of the blinded message - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return #GNUNET_SYSERR on internal error - * #GNUNET_NO if the collectable was not found - * #GNUNET_YES on success - */ -int -TALER_MINT_DB_get_collectable_blindcoin (PGconn *db_conn, - const struct GNUNET_HashCode *h_blind, - struct CollectableBlindcoin *collectable); - - -/** - * Store collectable bit coin under the corresponding - * hash of the blinded message. - * - * @param db_conn database connection to use - * @param h_blind hash of the blinded message - * @param withdraw amount by which the reserve will be withdrawn with this - * transaction - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return #GNUNET_SYSERR on internal error - * #GNUNET_NO if the collectable was not found - * #GNUNET_YES on success - */ -int -TALER_MINT_DB_insert_collectable_blindcoin (PGconn *db_conn, - const struct GNUNET_HashCode *h_blind, - struct TALER_Amount withdraw, - const struct CollectableBlindcoin *collectable); - - - -/** - * Types of operations on a reserved. - */ -enum TALER_MINT_DB_ReserveOperation -{ - /** - * Money was deposited into the reserve via a bank transfer. - */ - TALER_MINT_DB_RO_BANK_TO_MINT = 0, - - /** - * A Coin was withdrawn from the reserve using /withdraw. - */ - TALER_MINT_DB_RO_WITHDRAW_COIN = 1 -}; - - -/** - * Reserve history as a linked list. Lists all of the transactions - * associated with this reserve (such as the bank transfers that - * established the reserve and all /withdraw operations we have done - * since). - */ -struct ReserveHistory -{ - - /** - * Next entry in the reserve history. - */ - struct ReserveHistory *next; - - /** - * Type of the event, determins @e details. - */ - enum TALER_MINT_DB_ReserveOperation type; - - /** - * Details of the operation, depending on @e type. - */ - union - { - - /** - * Details about a bank transfer to the mint. - */ - struct BankTransfer *bank; - - /** - * Details about a /withdraw operation. - */ - struct CollectableBlindcoin *withdraw; - - } details; - -}; - - -/** - * Get all of the transaction history associated with the specified - * reserve. - * - * @param db_conn connection to use - * @param reserve_pub public key of the reserve - * @return known transaction history (NULL if reserve is unknown) - */ -struct ReserveHistory * -TALER_MINT_DB_get_reserve_history (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub); - - -/** - * Free memory associated with the given reserve history. - * - * @param rh history to free. - */ -void -TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh); - - -/** - * Specification for a /deposit operation. - */ -struct Deposit -{ - /** - * Information about the coin that is being deposited. - */ - struct TALER_CoinPublicInfo coin; - - /** - * ECDSA signature affirming that the customer intends - * this coin to be deposited at the merchant identified - * by @e h_wire in relation to the contract identified - * by @e h_contract. - */ - struct GNUNET_CRYPTO_EcdsaSignature csig; - - /** - * Public key of the merchant. Enables later identification - * of the merchant in case of a need to rollback transactions. - */ - struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; - - /** - * Hash over the contract between merchant and customer - * (remains unknown to the Mint). - */ - struct GNUNET_HashCode h_contract; - - /** - * Hash of the (canonical) representation of @e wire, used - * to check the signature on the request. Generated by - * the mint from the detailed wire data provided by the - * merchant. - */ - struct GNUNET_HashCode h_wire; - - /** - * Detailed wire information for executing the transaction. - */ - const json_t *wire; - - /** - * Merchant-generated transaction ID to detect duplicate - * transactions. - */ - uint64_t transaction_id; - - /** - * Fraction of the coin's remaining value to be deposited. - * The coin is identified by @e coin_pub. - */ - struct TALER_Amount amount; - -}; - - -/** - * Check if we have the specified deposit already in the database. - * - * @param db_conn database connection - * @param deposit deposit to search for - * @return #GNUNET_YES if we know this operation, - * #GNUNET_NO if this deposit is unknown to us, - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_have_deposit (PGconn *db_conn, - const struct Deposit *deposit); - - -/** - * Insert information about deposited coin into the - * database. - * - * @param db_conn connection to the database - * @param deposit deposit information to store - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_insert_deposit (PGconn *db_conn, - const struct Deposit *deposit); - - - -/** - * Global information for a refreshing session. Includes - * dimensions of the operation, security parameters and - * client signatures from "/refresh/melt" and "/refresh/commit". - */ -struct RefreshSession -{ - /** - * Signature over the commitments by the client, - * only valid if @e has_commit_sig is set. - */ - struct GNUNET_CRYPTO_EddsaSignature commit_sig; - - /** - * Hash over coins to melt and coins to create of the - * refresh session. - */ - struct GNUNET_HashCode session_hash; - - /** - * Signature over the melt by the client. - */ - struct GNUNET_CRYPTO_EddsaSignature melt_sig; - - /** - * Number of coins we are melting. - */ - uint16_t num_oldcoins; - - /** - * Number of new coins we are creating. - */ - uint16_t num_newcoins; - - /** - * Number of parallel operations we perform for the cut and choose. - * (must be greater or equal to three for security). 0 if not yet - * known. - */ - uint16_t kappa; - - /** - * Index (smaller @e kappa) which the mint has chosen to not - * have revealed during cut and choose. - */ - uint16_t noreveal_index; - -}; - - -/** - * Lookup refresh session data under the given public key. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use for the lookup - * @param session[OUT] where to store the result - * @return #GNUNET_YES on success, - * #GNUNET_NO if not found, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_get_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - struct RefreshSession *session); - - -/** - * Store new refresh session data under the given public key. - * - * @param db_conn database handle to use - * @param refresh_session_pub public key to use to locate the session - * @param session session data to store - * @return #GNUNET_YES on success, - * #GNUNET_SYSERR on DB failure - */ -int -TALER_MINT_DB_create_refresh_session (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - const struct RefreshSession *session); - - -/** - * Specification for coin in a /refresh/melt operation. - */ -struct RefreshMelt -{ - /** - * Information about the coin that is being melted. - */ - struct TALER_CoinPublicInfo coin; - - /** - * Signature over the melting operation. - */ - struct GNUNET_CRYPTO_EcdsaSignature coin_sig; - - /** - * Which melting operation should the coin become a part of. - */ - struct GNUNET_HashCode melt_hash; - - /** - * How much value is being melted? - * This amount includes the fees, so the final amount contributed - * to the melt is this value minus the fee for melting the coin. - */ - struct TALER_Amount amount; - -}; - - -/** - * Store the given /refresh/melt request in the database. - * - * @param db_conn database connection - * @param session session key of the melt operation - * @param oldcoin_index index of the coin to store - * @param melt coin melt operation details to store - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_insert_refresh_melt (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session, - uint16_t oldcoin_index, - const struct RefreshMelt *melt); - - - -/** - * Get information about melted coin details from the database. - * - * @param db_conn database connection - * @param session session key of the melt operation - * @param oldcoin_index index of the coin to retrieve - * @param melt melt data to fill in - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_get_refresh_melt (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session, - uint16_t oldcoin_index, - struct RefreshMelt *melt); - - -/** - * Store in the database which coin(s) we want to create - * in a given refresh operation. - * - * @param db_conn database connection - * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_insert_refresh_order (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); - - -/** - * Lookup in the database the @a newcoin_index coin that we want to - * create in the given refresh operation. - * - * @param db_conn database connection - * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return NULL on error (not found or internal error) - */ -struct GNUNET_CRYPTO_rsa_PublicKey * -TALER_MINT_DB_get_refresh_order (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index); - - -/** - * We have as many `struct RefreshCommitCoin` as there are new - * coins being created by the refresh (for each of the kappa - * sets). These are the coins we ask the mint to sign if the - * respective set is selected. - */ -struct RefreshCommitCoin -{ - - /** - * Encrypted data allowing those able to decrypt it to derive - * the private keys of the new coins created by the refresh. - */ - struct TALER_RefreshLinkEncrypted *refresh_link; - - /** - * Blinded message to be signed (in envelope), with @e coin_env_size bytes. - */ - char *coin_ev; - - /** - * Number of bytes in @e coin_ev. - */ - size_t coin_ev_size; - -}; - - -/** - * Store information about the commitment of the - * given coin for the given refresh session in the database. - * - * @param db_conn database connection to use - * @param refresh_session_pub refresh session this commitment belongs to - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin coin commitment to store - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_insert_refresh_commit_coin (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitCoin *commit_coin); - - -/** - * Obtain information about the commitment of the - * given coin of the given refresh session from the database. - * - * @param db_conn database connection to use - * @param refresh_session_pub refresh session the commitment belongs to - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin[OUT] coin commitment to return - * @return #GNUNET_OK on success - * #GNUNET_NO if not found - * #GNUNET_SYSERR on error - */ -int -TALER_MINT_DB_get_refresh_commit_coin (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - struct RefreshCommitCoin *commit_coin); - - -/** - * For each (old) coin being melted, we have a `struct - * RefreshCommitLink` that allows the user to find the shared secret - * to decrypt the respective refresh links for the new coins in the - * `struct RefreshCommitCoin`. - */ -struct RefreshCommitLink -{ - /** - * Transfer public key (FIXME: explain!) - */ - struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; - - /** - * Encrypted shared secret to decrypt the link. - */ - struct TALER_EncryptedLinkSecret shared_secret_enc; -}; - - -/** - * Store the commitment to the given (encrypted) refresh link data - * for the given refresh session. - * - * @param db_conn database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param commit_link link information to store - * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success - */ -int -TALER_MINT_DB_insert_refresh_commit_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitLink *commit_link); - -/** - * Obtain the commited (encrypted) refresh link data - * for the given refresh session. - * - * @param db_conn database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param cc[OUT] link information to return - * @return #GNUNET_SYSERR on internal error, - * #GNUNET_NO if commitment was not found - * #GNUNET_OK on success - */ -int -TALER_MINT_DB_get_refresh_commit_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - struct RefreshCommitLink *cc); - - -/** - * Insert signature of a new coin generated during refresh into - * the database indexed by the refresh session and the index - * of the coin. This data is later used should an old coin - * be used to try to obtain the private keys during "/refresh/link". - * - * @param db_conn database connection - * @param session_pub refresh session - * @param newcoin_index coin index - * @param ev_sig coin signature - * @return #GNUNET_OK on success - */ -int -TALER_MINT_DB_insert_refresh_collectable (PGconn *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); - - -/** - * Linked list of refresh information linked to a coin. - */ -struct LinkDataList -{ - /** - * Information is stored in a NULL-terminated linked list. - */ - struct LinkDataList *next; - - /** - * Link data, used to recover the private key of the coin - * by the owner of the old coin. - */ - struct TALER_RefreshLinkEncrypted *link_data_enc; - - /** - * Denomination public key, determines the value of the coin. - */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - - /** - * Signature over the blinded envelope. - */ - struct GNUNET_CRYPTO_rsa_Signature *ev_sig; -}; - - -/** - * Obtain the link data of a coin, that is the encrypted link - * information, the denomination keys and the signatures. - * - * @param db_conn database connection - * @param coin_pub public key to use to retrieve linkage data - * @return all known link data for the coin - */ -struct LinkDataList * -TALER_db_get_link (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); - - -/** - * Free memory of the link data list. - * - * @param ldl link data list to release - */ -void -TALER_db_link_data_list_free (struct LinkDataList *ldl); - - -/** - * Obtain shared secret and transfer public key from the public key of - * the coin. This information and the link information returned by - * #TALER_db_get_link() enable the owner of an old coin to determine - * the private keys of the new coins after the melt. - * - * - * @param db_conn database connection - * @param coin_pub public key of the coin - * @param transfer_pub[OUT] public transfer key - * @param shared_secret_enc[OUT] set to shared secret - * @return #GNUNET_OK on success, - * #GNUNET_NO on failure (not found) - * #GNUNET_SYSERR on internal failure (database issue) - */ -int -TALER_db_get_transfer (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, - struct TALER_EncryptedLinkSecret *shared_secret_enc); - - -/** - * Specification for a /lock operation. - */ -struct Lock -{ - /** - * Information about the coin that is being melted. - */ - struct TALER_CoinPublicInfo coin; - - /** - * Signature over the melting operation. - */ - const struct GNUNET_CRYPTO_EcdsaSignature coin_sig; - - /** - * How much value is being melted? - */ - struct TALER_Amount amount; - - // FIXME: more needed... -}; - - -/** - * Test if the given /lock request is known to us. - * - * @param db_conn database connection - * @param lock lock operation - * @return #GNUNET_YES if known, - * #GNUENT_NO if not, - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_have_lock (PGconn *db_conn, - const struct Lock *lock); - - -/** - * Store the given /lock request in the database. - * - * @param db_conn database connection - * @param lock lock operation - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on internal error - */ -int -TALER_MINT_DB_insert_lock (PGconn *db_conn, - const struct Lock *lock); - - -/** - * Enumeration to classify the different types of transactions - * that can be done with a coin. - */ -enum TALER_MINT_DB_TransactionType -{ - /** - * /deposit operation. - */ - TALER_MINT_DB_TT_DEPOSIT = 0, - - /** - * /refresh/melt operation. - */ - TALER_MINT_DB_TT_REFRESH_MELT = 1, - - /** - * /lock operation. - */ - TALER_MINT_DB_TT_LOCK = 2 -}; - - -/** - * List of transactions we performed for a particular coin. - */ -struct TALER_MINT_DB_TransactionList -{ - - /** - * Next pointer in the NULL-terminated linked list. - */ - struct TALER_MINT_DB_TransactionList *next; - - /** - * Type of the transaction, determines what is stored in @e details. - */ - enum TALER_MINT_DB_TransactionType type; - - /** - * Details about the transaction, depending on @e type. - */ - union - { - - /** - * Details if transaction was a /deposit operation. - */ - struct Deposit *deposit; - - /** - * Details if transaction was a /refresh/melt operation. - */ - struct RefreshMelt *melt; - - /** - * Details if transaction was a /lock operation. - */ - struct Lock *lock; - - } details; - -}; - - -/** - * Compile a list of all (historic) transactions performed - * with the given coin (/refresh/melt and /deposit operations). - * - * @param db_conn database connection - * @param coin_pub coin to investigate - * @return list of transactions, NULL if coin is fresh - */ -struct TALER_MINT_DB_TransactionList * -TALER_MINT_DB_get_coin_transactions (PGconn *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); - - -/** - * Free linked list of transactions. - * - * @param list list to free - */ -void -TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list); - - - -#endif /* _NEURO_MINT_DB_H */ diff --git a/src/mint/plugin.c b/src/mint/plugin.c new file mode 100644 index 000000000..91cd3f406 --- /dev/null +++ b/src/mint/plugin.c @@ -0,0 +1,183 @@ +/* + This file is part of TALER + Copyright (C) 2015 Christian Grothoff (and other contributing authors) + + 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, If not, see +*/ +/** + * @file mint/plugin.c + * @brief Logic to load database plugin + * @author Christian Grothoff + */ +#include "platform.h" +#include "plugin.h" +#include + + +/** + * Global variable with the plugin (once loaded). + */ +struct TALER_MINTDB_Plugin *plugin; + +/** + * Libtool search path before we started. + */ +static char *old_dlsearchpath; + + +/** + * Initialize the plugin. + * + * @param cfg configuration to use + * @return #GNUNET_OK on success + */ +int +TALER_MINT_plugin_load (struct GNUNET_CONFIGURATION_Handle *cfg) +{ + return GNUNET_SYSERR; +} + + +/** + * Shutdown the plugin. + */ +void +TALER_MINT_plugin_unload () +{ + if (NULL == plugin) + return; +} + + +/** + * Setup libtool paths. + */ +void __attribute__ ((constructor)) +plugin_init () +{ + int err; + const char *opath; + char *path; + char *cpath; + + err = lt_dlinit (); + if (err > 0) + { + FPRINTF (stderr, + _("Initialization of plugin mechanism failed: %s!\n"), + lt_dlerror ()); + return; + } + opath = lt_dlgetsearchpath (); + if (NULL != opath) + old_dlsearchpath = GNUNET_strdup (opath); + path = TALER_OS_installation_get_path (GNUNET_OS_IPK_LIBDIR); + if (NULL != path) + { + if (NULL != opath) + { + GNUNET_asprintf (&cpath, "%s:%s", opath, path); + lt_dlsetsearchpath (cpath); + GNUNET_free (path); + GNUNET_free (cpath); + } + else + { + lt_dlsetsearchpath (path); + GNUNET_free (path); + } + } +} + + +/** + * Shutdown libtool. + */ +void __attribute__ ((destructor)) +plugin_fini () +{ + lt_dlsetsearchpath (old_dlsearchpath); + if (NULL != old_dlsearchpath) + { + GNUNET_free (old_dlsearchpath); + old_dlsearchpath = NULL; + } + lt_dlexit (); +} + + +// FIXME: decide if we should keep these in each plugin, here +// or yet again somewhere else entirely (plugin_common.c?) + +/** + * Free memory associated with the given reserve history. + * + * @param rh history to free. + */ +void +TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh) +{ + struct BankTransfer *bt; + struct CollectableBlindcoin *cbc; + struct ReserveHistory *backref; + + while (NULL != rh) + { + switch(rh->type) + { + case TALER_MINT_DB_RO_BANK_TO_MINT: + bt = rh->details.bank; + if (NULL != bt->wire) + json_decref ((json_t *) bt->wire); /* FIXME: avoid cast? */ + GNUNET_free (bt); + break; + case TALER_MINT_DB_RO_WITHDRAW_COIN: + cbc = rh->details.withdraw; + GNUNET_CRYPTO_rsa_signature_free (cbc->sig); + GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); + GNUNET_free (cbc); + break; + } + backref = rh; + rh = rh->next; + GNUNET_free (backref); + } +} + + +/** + * Free memory of the link data list. + * + * @param ldl link data list to release + */ +void +TALER_db_link_data_list_free (struct LinkDataList *ldl) +{ + GNUNET_break (0); // FIXME +} + + +/** + * Free linked list of transactions. + * + * @param list list to free + */ +void +TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list) +{ + // FIXME: check logic! + GNUNET_break (0); +} + + + +/* end of plugin.c */ diff --git a/src/mint/plugin.h b/src/mint/plugin.h new file mode 100644 index 000000000..01b99ebc3 --- /dev/null +++ b/src/mint/plugin.h @@ -0,0 +1,77 @@ +/* + This file is part of TALER + Copyright (C) 2015 Christian Grothoff (and other contributing authors) + + 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, If not, see +*/ +/** + * @file mint/plugin.h + * @brief Logic to load database plugins + * @author Christian Grothoff + */ +#ifndef PLUGIN_H +#define PLUGIN_H + +#include +#include "taler_mintdb_plugin.h" + +/** + * Global variable with the plugin (once loaded). + */ +extern struct TALER_MINTDB_Plugin *plugin; + + +/** + * Initialize the plugin. + * + * @param cfg configuration to use + * @return #GNUNET_OK on success + */ +int +TALER_MINT_plugin_load (struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Shutdown the plugin. + */ +void +TALER_MINT_plugin_unload (void); + + +/** + * Free memory associated with the given reserve history. + * + * @param rh history to free. + */ +void +TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh); + + +/** + * Free memory of the link data list. + * + * @param ldl link data list to release + */ +void +TALER_db_link_data_list_free (struct LinkDataList *ldl); + + +/** + * Free linked list of transactions. + * + * @param list list to free + */ +void +TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list); + + +#endif diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c new file mode 100644 index 000000000..8935fe039 --- /dev/null +++ b/src/mint/plugin_mintdb_postgres.c @@ -0,0 +1,2316 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + + 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, If not, see +*/ + +/** + * @file plugin_mintdb_postgres.c + * @brief Low-level (statement-level) Postgres database access for the mint + * @author Florian Dold + * @author Christian Grothoff + * @author Sree Harsha Totakura + */ +#include "platform.h" +#include "db_pq.h" +#include "taler_signatures.h" +#include "taler_mintdb_plugin.h" +#include +#include + + +#define TALER_TEMP_SCHEMA_NAME "taler_temporary" + +#define QUERY_ERR(result) \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Query failed at %s:%u: %s\n", __FILE__, __LINE__, PQresultErrorMessage (result)) + + +#define BREAK_DB_ERR(result) do { \ + GNUNET_break(0); \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Database failure: %s\n", PQresultErrorMessage (result)); \ + } while (0) + +/** + * Shorthand for exit jumps. + */ +#define EXITIF(cond) \ + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } while (0) + + +#define SQLEXEC_(conn, sql, result) \ + do { \ + result = PQexec (conn, sql); \ + if (PGRES_COMMAND_OK != PQresultStatus (result)) \ + { \ + BREAK_DB_ERR (result); \ + PQclear (result); result = NULL; \ + goto SQLEXEC_fail; \ + } \ + PQclear (result); result = NULL; \ + } while (0) + +/** + * This the length of the currency strings (without 0-termination) we use. Note + * that we need to use this at the DB layer instead of TALER_CURRENCY_LEN as the + * DB only needs to store 3 bytes instead of 8 bytes. + */ +#define TALER_DB_CURRENCY_LEN 3 + + +/** + * Handle for a database session (per-thread, for transactions). + */ +struct TALER_MINTDB_Session +{ + /** + * Postgres connection handle. + */ + PGconn *conn; +}; + + +/** + * Type of the "cls" argument given to each of the functions in + * our API. + */ +struct PostgresClosure +{ + + /** + * Thread-local database connection. + * Contains a pointer to PGconn or NULL. + */ + pthread_key_t db_conn_threadlocal; + + /** + * Database connection string, as read from + * the configuration. + */ + char *TALER_MINT_db_connection_cfg_str; +}; + + + +/** + * Set the given connection to use a temporary schema + * + * @param db the database connection + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon error + */ +static int +set_temporary_schema (PGconn *db) +{ + PGresult *result; + + SQLEXEC_(db, + "CREATE SCHEMA IF NOT EXISTS " TALER_TEMP_SCHEMA_NAME ";" + "SET search_path to " TALER_TEMP_SCHEMA_NAME ";", + result); + return GNUNET_OK; + SQLEXEC_fail: + return GNUNET_SYSERR; +} + + +/** + * Drop the temporary taler schema. This is only useful for testcases + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +static int +postgres_drop_temporary (void *cls, + struct TALER_MINTDB_Session *session) +{ + PGresult *result; + + SQLEXEC_ (session->conn, + "DROP SCHEMA " TALER_TEMP_SCHEMA_NAME " CASCADE;", + result); + return GNUNET_OK; + SQLEXEC_fail: + return GNUNET_SYSERR; +} + + +/** + * Create the necessary tables if they are not present + * + * @param pc our overall context + * @param temporary should we use a temporary schema + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +static int +postgres_create_tables (struct PostgresClosure *pc, + int temporary) +{ + PGresult *result; + PGconn *conn; + + result = NULL; + conn = PQconnectdb (pc->TALER_MINT_db_connection_cfg_str); + if (CONNECTION_OK != PQstatus (conn)) + { + LOG_ERROR ("Database connection failed: %s\n", + PQerrorMessage (conn)); + GNUNET_break (0); + return GNUNET_SYSERR; + } + if ((GNUNET_YES == temporary) + && (GNUNET_SYSERR == set_temporary_schema (conn))) + { + PQfinish (conn); + return GNUNET_SYSERR; + } +#define SQLEXEC(sql) SQLEXEC_(conn, sql, result); + /* reserves table is for summarization of a reserve. It is updated when new + funds are added and existing funds are withdrawn */ + SQLEXEC ("CREATE TABLE IF NOT EXISTS reserves" + "(" + " reserve_pub BYTEA PRIMARY KEY" + ",current_balance_value INT4 NOT NULL" + ",current_balance_fraction INT4 NOT NULL" + ",balance_currency VARCHAR(4) NOT NULL" + ",expiration_date INT8 NOT NULL" + ")"); + /* reserves_in table collects the transactions which transfer funds into the + reserve. The amount and expiration date for the corresponding reserve are + updated when new transfer funds are added. The rows of this table + correspond to each incoming transaction. */ + SQLEXEC("CREATE TABLE IF NOT EXISTS reserves_in" + "(" + " reserve_pub BYTEA REFERENCES reserves (reserve_pub) ON DELETE CASCADE" + ",balance_value INT4 NOT NULL" + ",balance_fraction INT4 NOT NULL" + ",balance_currency VARCHAR(4) NOT NULL" + ",expiration_date INT8 NOT NULL" + ");"); + /* Create an index on the foreign key as it is not created automatically by PSQL */ + SQLEXEC ("CREATE INDEX reserves_in_reserve_pub_index" + " ON reserves_in (reserve_pub);"); + SQLEXEC ("CREATE TABLE IF NOT EXISTS collectable_blindcoins" + "(" + "blind_ev BYTEA PRIMARY KEY" + ",denom_pub BYTEA NOT NULL" /* FIXME: Make this a foreign key? */ + ",denom_sig BYTEA NOT NULL" + ",reserve_pub BYTEA REFERENCES reserves (reserve_pub) ON DELETE CASCADE" + ",reserve_sig BYTEA NOT NULL" + ");"); + SQLEXEC ("CREATE INDEX collectable_blindcoins_reserve_pub_index ON" + " collectable_blindcoins (reserve_pub)"); + SQLEXEC("CREATE TABLE IF NOT EXISTS known_coins " + "(" + " coin_pub BYTEA NOT NULL PRIMARY KEY" + ",denom_pub BYTEA NOT NULL" + ",denom_sig BYTEA NOT NULL" + ",expended_value INT4 NOT NULL" + ",expended_fraction INT4 NOT NULL" + ",expended_currency VARCHAR(4) NOT NULL" + ",refresh_session_pub BYTEA" + ")"); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions " + "(" + " session_pub BYTEA PRIMARY KEY CHECK (length(session_pub) = 32)" + ",session_melt_sig BYTEA" + ",session_commit_sig BYTEA" + ",noreveal_index INT2 NOT NULL" + // non-zero if all reveals were ok + // and the new coin signatures are ready + ",reveal_ok BOOLEAN NOT NULL DEFAULT false" + ") "); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_order " + "( " + " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" + ",newcoin_index INT2 NOT NULL " + ",denom_pub BYTEA NOT NULL " + ",PRIMARY KEY (session_pub, newcoin_index)" + ") "); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link" + "(" + " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" + ",transfer_pub BYTEA NOT NULL" + ",link_secret_enc BYTEA NOT NULL" + // index of the old coin in the customer's request + ",oldcoin_index INT2 NOT NULL" + // index for cut and choose, + // ranges from 0 to kappa-1 + ",cnc_index INT2 NOT NULL" + ")"); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_coin" + "(" + " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + ",link_vector_enc BYTEA NOT NULL" + // index of the new coin in the customer's request + ",newcoin_index INT2 NOT NULL" + // index for cut and choose, + ",cnc_index INT2 NOT NULL" + ",coin_ev BYTEA NOT NULL" + ")"); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_melt" + "(" + " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) " + ",denom_pub BYTEA NOT NULL " + ",oldcoin_index INT2 NOT NULL" + ")"); + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_collectable" + "(" + " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + ",ev_sig BYTEA NOT NULL" + ",newcoin_index INT2 NOT NULL" + ")"); + SQLEXEC("CREATE TABLE IF NOT EXISTS deposits " + "( " + " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)" + ",denom_pub BYTEA NOT NULL" /* FIXME: Link this as a foreign key? */ + ",denom_sig BYTEA NOT NULL" + ",transaction_id INT8 NOT NULL" + ",amount_currency VARCHAR(4) NOT NULL" + ",amount_value INT4 NOT NULL" + ",amount_fraction INT4 NOT NULL" + ",merchant_pub BYTEA NOT NULL CHECK (length(merchant_pub)=32)" + ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)" + ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)" + ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)" + ",wire TEXT NOT NULL" + ")"); +#undef SQLEXEC + PQfinish (conn); + return GNUNET_OK; + + SQLEXEC_fail: + PQfinish (conn); + return GNUNET_SYSERR; +} + + +/** + * Setup prepared statements. + * + * @param db_conn connection handle to initialize + * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure + */ +static int +postgres_prepare (PGconn *db_conn) +{ + PGresult *result; + +#define PREPARE(name, sql, ...) \ + do { \ + result = PQprepare (db_conn, name, sql, __VA_ARGS__); \ + if (PGRES_COMMAND_OK != PQresultStatus (result)) \ + { \ + BREAK_DB_ERR (result); \ + PQclear (result); result = NULL; \ + return GNUNET_SYSERR; \ + } \ + PQclear (result); result = NULL; \ + } while (0); + + PREPARE ("get_reserve", + "SELECT " + "current_balance_value" + ",current_balance_fraction" + ",balance_currency " + ",expiration_date " + "FROM reserves " + "WHERE reserve_pub=$1 " + "LIMIT 1; ", + 1, NULL); + PREPARE ("create_reserve", + "INSERT INTO reserves (" + " reserve_pub," + " current_balance_value," + " current_balance_fraction," + " balance_currency," + " expiration_date) VALUES (" + "$1, $2, $3, $4, $5);", + 5, NULL); + PREPARE ("update_reserve", + "UPDATE reserves " + "SET" + " current_balance_value=$2 " + ",current_balance_fraction=$3 " + ",expiration_date=$4 " + "WHERE reserve_pub=$1 ", + 4, NULL); + PREPARE ("create_reserves_in_transaction", + "INSERT INTO reserves_in (" + " reserve_pub," + " balance_value," + " balance_fraction," + " balance_currency," + " expiration_date) VALUES (" + " $1, $2, $3, $4, $5);", + 5, NULL); + PREPARE ("get_reserves_in_transactions", + "SELECT" + " balance_value" + ",balance_fraction" + ",balance_currency" + ",expiration_date" + " FROM reserves_in WHERE reserve_pub=$1", + 1, NULL); + PREPARE ("insert_collectable_blindcoin", + "INSERT INTO collectable_blindcoins ( " + " blind_ev" + ",denom_pub, denom_sig" + ",reserve_pub, reserve_sig) " + "VALUES ($1, $2, $3, $4, $5)", + 5, NULL); + PREPARE ("get_collectable_blindcoin", + "SELECT " + " denom_pub, denom_sig" + ",reserve_sig, reserve_pub " + "FROM collectable_blindcoins " + "WHERE blind_ev = $1", + 1, NULL); + PREPARE ("get_reserves_blindcoins", + "select" + " blind_ev" + ",denom_pub, denom_sig" + ",reserve_sig" + " FROM collectable_blindcoins" + " WHERE reserve_pub=$1;", + 1, NULL); + + /* FIXME: does it make sense to store these computed values in the DB? */ +#if 0 + PREPARE ("get_refresh_session", + "SELECT " + " (SELECT count(*) FROM refresh_melt WHERE session_pub = $1)::INT2 as num_oldcoins " + ",(SELECT count(*) FROM refresh_blind_session_keys " + " WHERE session_pub = $1 and cnc_index = 0)::INT2 as num_newcoins " + ",(SELECT count(*) FROM refresh_blind_session_keys " + " WHERE session_pub = $1 and newcoin_index = 0)::INT2 as kappa " + ",noreveal_index" + ",session_commit_sig " + ",reveal_ok " + "FROM refresh_sessions " + "WHERE session_pub = $1", + 1, NULL); +#endif + + PREPARE ("get_known_coin", + "SELECT " + " coin_pub, denom_pub, denom_sig " + ",expended_value, expended_fraction, expended_currency " + ",refresh_session_pub " + "FROM known_coins " + "WHERE coin_pub = $1", + 1, NULL); + PREPARE ("update_known_coin", + "UPDATE known_coins " + "SET " + " denom_pub = $2 " + ",denom_sig = $3 " + ",expended_value = $4 " + ",expended_fraction = $5 " + ",expended_currency = $6 " + ",refresh_session_pub = $7 " + "WHERE " + " coin_pub = $1 ", + 7, NULL); + PREPARE ("insert_known_coin", + "INSERT INTO known_coins (" + " coin_pub" + ",denom_pub" + ",denom_sig" + ",expended_value" + ",expended_fraction" + ",expended_currency" + ",refresh_session_pub" + ")" + "VALUES ($1,$2,$3,$4,$5,$6,$7)", + 7, NULL); + PREPARE ("get_refresh_commit_link", + "SELECT " + " transfer_pub " + ",link_secret_enc " + "FROM refresh_commit_link " + "WHERE session_pub = $1 AND cnc_index = $2 AND oldcoin_index = $3", + 3, NULL); + PREPARE ("get_refresh_commit_coin", + "SELECT " + " link_vector_enc " + ",coin_ev " + "FROM refresh_commit_coin " + "WHERE session_pub = $1 AND cnc_index = $2 AND newcoin_index = $3", + 3, NULL); + PREPARE ("insert_refresh_order", + "INSERT INTO refresh_order ( " + " newcoin_index " + ",session_pub " + ",denom_pub " + ") " + "VALUES ($1, $2, $3) ", + 3, NULL); + PREPARE ("insert_refresh_melt", + "INSERT INTO refresh_melt ( " + " session_pub " + ",oldcoin_index " + ",coin_pub " + ",denom_pub " + ") " + "VALUES ($1, $2, $3, $4) ", + 3, NULL); + PREPARE ("get_refresh_order", + "SELECT denom_pub " + "FROM refresh_order " + "WHERE session_pub = $1 AND newcoin_index = $2", + 2, NULL); + PREPARE ("get_refresh_collectable", + "SELECT ev_sig " + "FROM refresh_collectable " + "WHERE session_pub = $1 AND newcoin_index = $2", + 2, NULL); + PREPARE ("get_refresh_melt", + "SELECT coin_pub " + "FROM refresh_melt " + "WHERE session_pub = $1 AND oldcoin_index = $2", + 2, NULL); + PREPARE ("insert_refresh_session", + "INSERT INTO refresh_sessions ( " + " session_pub " + ",noreveal_index " + ") " + "VALUES ($1, $2) ", + 2, NULL); + PREPARE ("insert_refresh_commit_link", + "INSERT INTO refresh_commit_link ( " + " session_pub " + ",transfer_pub " + ",cnc_index " + ",oldcoin_index " + ",link_secret_enc " + ") " + "VALUES ($1, $2, $3, $4, $5) ", + 5, NULL); + PREPARE ("insert_refresh_commit_coin", + "INSERT INTO refresh_commit_coin ( " + " session_pub " + ",coin_ev " + ",cnc_index " + ",newcoin_index " + ",link_vector_enc " + ") " + "VALUES ($1, $2, $3, $4, $5) ", + 5, NULL); + PREPARE ("insert_refresh_collectable", + "INSERT INTO refresh_collectable ( " + " session_pub " + ",newcoin_index " + ",ev_sig " + ") " + "VALUES ($1, $2, $3) ", + 3, NULL); + PREPARE ("set_reveal_ok", + "UPDATE refresh_sessions " + "SET reveal_ok = TRUE " + "WHERE session_pub = $1 ", + 1, NULL); + PREPARE ("get_link", + "SELECT link_vector_enc, ro.denom_pub, ev_sig " + "FROM refresh_melt rm " + " JOIN refresh_order ro USING (session_pub) " + " JOIN refresh_commit_coin rcc USING (session_pub) " + " JOIN refresh_sessions rs USING (session_pub) " + " JOIN refresh_collectable rc USING (session_pub) " + "WHERE rm.coin_pub = $1 " + "AND ro.newcoin_index = rcc.newcoin_index " + "AND ro.newcoin_index = rc.newcoin_index " + "AND rcc.cnc_index = rs.noreveal_index % ( " + " SELECT count(*) FROM refresh_commit_coin rcc2 " + " WHERE rcc2.newcoin_index = 0 AND rcc2.session_pub = rs.session_pub " + " ) ", + 1, NULL); + PREPARE ("get_transfer", + "SELECT transfer_pub, link_secret_enc " + "FROM refresh_melt rm " + " JOIN refresh_commit_link rcl USING (session_pub) " + " JOIN refresh_sessions rs USING (session_pub) " + "WHERE rm.coin_pub = $1 " + "AND rm.oldcoin_index = rcl.oldcoin_index " + "AND rcl.cnc_index = rs.noreveal_index % ( " + " SELECT count(*) FROM refresh_commit_coin rcc2 " + " WHERE newcoin_index = 0 AND rcc2.session_pub = rm.session_pub " + " ) ", + 1, NULL); + PREPARE ("insert_deposit", + "INSERT INTO deposits (" + "coin_pub," + "denom_pub," + "denom_sig," + "transaction_id," + "amount_value," + "amount_fraction," + "amount_currency," + "merchant_pub," + "h_contract," + "h_wire," + "coin_sig," + "wire" + ") VALUES (" + "$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12" + ")", + 12, NULL); + PREPARE ("get_deposit", + "SELECT " + "coin_pub," + "denom_pub," + "transaction_id," + "amount_value," + "amount_fraction," + "amount_currency," + "merchant_pub," + "h_contract," + "h_wire," + "coin_sig" + " FROM deposits WHERE (" + "(coin_pub = $1) AND" + "(transaction_id = $2) AND" + "(merchant_pub = $3)" + ")", + 3, NULL); + return GNUNET_OK; +#undef PREPARE +} + + +/** + * Close thread-local database connection when a thread is destroyed. + * + * @param closure we get from pthreads (the db handle) + */ +static void +db_conn_destroy (void *cls) +{ + PGconn *db_conn = cls; + + if (NULL != db_conn) + PQfinish (db_conn); +} + + +/** + * Get the thread-local database-handle. + * Connect to the db if the connection does not exist yet. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param temporary #GNUNET_YES to use a temporary schema; #GNUNET_NO to use the + * database default one + * @return the database connection, or NULL on error + */ +static struct TALER_MINTDB_Session * +postgres_get_connection (void *cls, + int temporary) +{ + struct PostgresClosure *pc = cls; + PGconn *db_conn; + struct TALER_MINTDB_Session *session; + + if (NULL != (session = pthread_getspecific (pc->db_conn_threadlocal))) + return session; + db_conn = PQconnectdb (pc->TALER_MINT_db_connection_cfg_str); + if (CONNECTION_OK != + PQstatus (db_conn)) + { + LOG_ERROR ("Database connection failed: %s\n", + PQerrorMessage (db_conn)); + GNUNET_break (0); + return NULL; + } + if ((GNUNET_YES == temporary) + && (GNUNET_SYSERR == set_temporary_schema(db_conn))) + { + GNUNET_break (0); + return NULL; + } + if (GNUNET_OK != + postgres_prepare (db_conn)) + { + GNUNET_break (0); + return NULL; + } + session = GNUNET_new (struct TALER_MINTDB_Session); + session->conn = db_conn; + if (0 != pthread_setspecific (pc->db_conn_threadlocal, + session)) + { + GNUNET_break (0); + // FIXME: close db_conn! + GNUNET_free (session); + return NULL; + } + return session; +} + + +/** + * Start a transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection + * @return #GNUNET_OK on success + */ +static int +postgres_start (void *cls, + struct TALER_MINTDB_Session *session) +{ + PGresult *result; + + result = PQexec (session->conn, + "BEGIN"); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + LOG_ERROR ("Failed to start transaction: %s\n", + PQresultErrorMessage (result)); + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Roll back the current transaction of a database connection. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection + * @return #GNUNET_OK on success + */ +static void +postgres_rollback (void *cls, + struct TALER_MINTDB_Session *session) +{ + PGresult *result; + + result = PQexec (session->conn, + "ROLLBACK"); + GNUNET_break (PGRES_COMMAND_OK == + PQresultStatus (result)); + PQclear (result); +} + + +/** + * Commit the current transaction of a database connection. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection + * @return #GNUNET_OK on success + */ +static int +postgres_commit (void *cls, + struct TALER_MINTDB_Session *session) +{ + PGresult *result; + + result = PQexec (session->conn, + "COMMIT"); + if (PGRES_COMMAND_OK != + PQresultStatus (result)) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Get the summary of a reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection handle + * @param reserve the reserve data. The public key of the reserve should be set + * in this structure; it is used to query the database. The balance + * and expiration are then filled accordingly. + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ +static int +postgres_reserve_get (void *cls, + struct TALER_MINTDB_Session *session, + struct Reserve *reserve) +{ + PGresult *result; + uint64_t expiration_date_nbo; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(reserve->pub), + TALER_DB_QUERY_PARAM_END + }; + + if (NULL == reserve->pub) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + result = TALER_DB_exec_prepared (session->conn, + "get_reserve", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("expiration_date", &expiration_date_nbo), + TALER_DB_RESULT_SPEC_END + }; + EXITIF (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)); + EXITIF (GNUNET_OK != + TALER_DB_extract_amount (result, 0, + "current_balance_value", + "current_balance_fraction", + "balance_currency", + &reserve->balance)); + reserve->expiry.abs_value_us = GNUNET_ntohll (expiration_date_nbo); + PQclear (result); + return GNUNET_OK; + + EXITIF_exit: + PQclear (result); + return GNUNET_SYSERR; +} + + +/** + * Updates a reserve with the data from the given reserve structure. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection + * @param reserve the reserve structure whose data will be used to update the + * corresponding record in the database. + * @return #GNUNET_OK upon successful update; #GNUNET_SYSERR upon any error + */ +static int +postgres_reserves_update (void *cls, + struct TALER_MINTDB_Session *session, + struct Reserve *reserve) +{ + PGresult *result; + struct TALER_AmountNBO balance_nbo; + struct GNUNET_TIME_AbsoluteNBO expiry_nbo; + int ret; + + if ((NULL == reserve) || (NULL == reserve->pub)) + return GNUNET_SYSERR; + ret = GNUNET_OK; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), + TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), + TALER_DB_QUERY_PARAM_END + }; + TALER_amount_hton (&balance_nbo, + &reserve->balance); + expiry_nbo = GNUNET_TIME_absolute_hton (reserve->expiry); + result = TALER_DB_exec_prepared (session->conn, + "update_reserve", + params); + if (PGRES_COMMAND_OK != PQresultStatus(result)) + { + QUERY_ERR (result); + ret = GNUNET_SYSERR; + } + PQclear (result); + return ret; +} + + +/** + * Insert a incoming transaction into reserves. New reserves are also created + * through this function. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session the database connection handle + * @param reserve the reserve structure. The public key of the reserve should + * be set here. Upon successful execution of this function, the + * balance and expiration of the reserve will be updated. + * @param balance the amount that has to be added to the reserve + * @param expiry the new expiration time for the reserve + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failures + */ +static int +postgres_reserves_in_insert (void *cls, + struct TALER_MINTDB_Session *session, + struct Reserve *reserve, + const struct TALER_Amount *balance, + const struct GNUNET_TIME_Absolute expiry) +{ + struct TALER_AmountNBO balance_nbo; + struct GNUNET_TIME_AbsoluteNBO expiry_nbo; + PGresult *result; + int reserve_exists; + + result = NULL; + if (NULL == reserve) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + if (GNUNET_OK != postgres_start (cls, + session)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + reserve_exists = postgres_reserve_get (cls, + session, + reserve); + if (GNUNET_SYSERR == reserve_exists) + { + postgres_rollback (cls, + session); + return GNUNET_SYSERR; + } + TALER_amount_hton (&balance_nbo, + balance); + expiry_nbo = GNUNET_TIME_absolute_hton (expiry); + if (GNUNET_NO == reserve_exists) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Reserve does not exist; creating a new one\n"); + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), + TALER_DB_QUERY_PARAM_PTR_SIZED (balance_nbo.currency, + TALER_DB_CURRENCY_LEN), + TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "create_reserve", + params); + if (PGRES_COMMAND_OK != PQresultStatus(result)) + { + QUERY_ERR (result); + goto rollback; + } + } + if (NULL != result) + PQclear (result); + result = NULL; + /* create new incoming transaction */ + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), + TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), + TALER_DB_QUERY_PARAM_PTR_SIZED (&balance_nbo.currency, + TALER_DB_CURRENCY_LEN), + TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "create_reserves_in_transaction", + params); + if (PGRES_COMMAND_OK != PQresultStatus(result)) + { + QUERY_ERR (result); + goto rollback; + } + PQclear (result); + result = NULL; + if (GNUNET_NO == reserve_exists) + { + if (GNUNET_OK != postgres_commit (cls, + session)) + return GNUNET_SYSERR; + reserve->balance = *balance; + reserve->expiry = expiry; + return GNUNET_OK; + } + /* Update reserve */ + struct Reserve updated_reserve; + updated_reserve.pub = reserve->pub; + + if (GNUNET_OK != + TALER_amount_add (&updated_reserve.balance, + &reserve->balance, + balance)) + { + return GNUNET_SYSERR; + } + updated_reserve.expiry = GNUNET_TIME_absolute_max (expiry, reserve->expiry); + if (GNUNET_OK != postgres_reserves_update (cls, + session, + &updated_reserve)) + goto rollback; + if (GNUNET_OK != postgres_commit (cls, + session)) + return GNUNET_SYSERR; + reserve->balance = updated_reserve.balance; + reserve->expiry = updated_reserve.expiry; + return GNUNET_OK; + + rollback: + PQclear (result); + postgres_rollback (cls, + session); + return GNUNET_SYSERR; +} + + +/** + * Locate the response for a /withdraw request under the + * key of the hash of the blinded message. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ +static int +postgres_get_collectable_blindcoin (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_HashCode *h_blind, + struct CollectableBlindcoin *collectable) +{ + PGresult *result; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (h_blind), + TALER_DB_QUERY_PARAM_END + }; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct GNUNET_CRYPTO_rsa_Signature *denom_sig; + char *denom_pub_enc; + char *denom_sig_enc; + size_t denom_pub_enc_size; + size_t denom_sig_enc_size; + int ret; + + ret = GNUNET_SYSERR; + denom_pub = NULL; + denom_pub_enc = NULL; + denom_sig_enc = NULL; + result = TALER_DB_exec_prepared (session->conn, + "get_collectable_blindcoin", + params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + goto cleanup; + } + if (0 == PQntuples (result)) + { + ret = GNUNET_NO; + goto cleanup; + } + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR("denom_pub", &denom_pub_enc, &denom_pub_enc_size), + TALER_DB_RESULT_SPEC_VAR("denom_sig", &denom_sig_enc, &denom_sig_enc_size), + TALER_DB_RESULT_SPEC("reserve_sig", &collectable->reserve_sig), + TALER_DB_RESULT_SPEC("reserve_pub", &collectable->reserve_pub), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) + { + GNUNET_break (0); + goto cleanup; + } + denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, + denom_pub_enc_size); + denom_sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, + denom_sig_enc_size); + if ((NULL == denom_pub) || (NULL == denom_sig)) + { + GNUNET_break (0); + goto cleanup; + } + collectable->denom_pub = denom_pub; + collectable->sig = denom_sig; + ret = GNUNET_YES; + + cleanup: + PQclear (result); + GNUNET_free_non_null (denom_pub_enc); + GNUNET_free_non_null (denom_sig_enc); + if (GNUNET_YES != ret) + { if (NULL != denom_pub) + GNUNET_CRYPTO_rsa_public_key_free (denom_pub); + if (NULL != denom_sig) + GNUNET_CRYPTO_rsa_signature_free (denom_sig); + } + return ret; +} + + +/** + * Store collectable bit coin under the corresponding + * hash of the blinded message. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param h_blind hash of the blinded message + * @param withdraw amount by which the reserve will be withdrawn with this + * transaction + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ +static int +postgres_insert_collectable_blindcoin (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_HashCode *h_blind, + struct TALER_Amount withdraw, + const struct CollectableBlindcoin *collectable) +{ + PGresult *result; + struct Reserve reserve; + char *denom_pub_enc = NULL; + char *denom_sig_enc = NULL; + size_t denom_pub_enc_size; + size_t denom_sig_enc_size; + int ret; + + ret = GNUNET_SYSERR; + denom_pub_enc_size = + GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub, + &denom_pub_enc); + denom_sig_enc_size = + GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, + &denom_sig_enc); + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (h_blind), + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size - 1), + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size - 1), /* DB doesn't like the trailing \0 */ + TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_pub), + TALER_DB_QUERY_PARAM_PTR (&collectable->reserve_sig), + TALER_DB_QUERY_PARAM_END + }; + if (GNUNET_OK != postgres_start (cls, + session)) + goto cleanup; + result = TALER_DB_exec_prepared (session->conn, + "insert_collectable_blindcoin", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + goto rollback; + } + reserve.pub = (struct GNUNET_CRYPTO_EddsaPublicKey *) + &collectable->reserve_pub; + if (GNUNET_OK != postgres_reserve_get (cls, + session, + &reserve)) + goto rollback; + if (GNUNET_SYSERR == + TALER_amount_subtract (&reserve.balance, + &reserve.balance, + &withdraw)) + goto rollback; + if (GNUNET_OK != postgres_reserves_update (cls, + session, + &reserve)) + goto rollback; + if (GNUNET_OK == postgres_commit (cls, + session)) + { + ret = GNUNET_OK; + goto cleanup; + } + + rollback: + postgres_rollback (cls, + session); + cleanup: + PQclear (result); + GNUNET_free_non_null (denom_pub_enc); + GNUNET_free_non_null (denom_sig_enc); + return ret; +} + + +/** + * Get all of the transaction history associated with the specified + * reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session connection to use + * @param reserve_pub public key of the reserve + * @return known transaction history (NULL if reserve is unknown) + */ +static struct ReserveHistory * +postgres_get_reserve_history (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) +{ + PGresult *result; + struct ReserveHistory *rh; + struct ReserveHistory *rh_head; + int rows; + int ret; + + result = NULL; + rh = NULL; + rh_head = NULL; + ret = GNUNET_SYSERR; + { + struct BankTransfer *bt; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (reserve_pub), + TALER_DB_QUERY_PARAM_END + }; + + result = TALER_DB_exec_prepared (session->conn, + "get_reserves_in_transactions", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + goto cleanup; + } + if (0 == (rows = PQntuples (result))) + { + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Asked to fetch history for an unknown reserve.\n"); + goto cleanup; + } + while (0 < rows) + { + bt = GNUNET_new (struct BankTransfer); + if (GNUNET_OK != TALER_DB_extract_amount (result, + --rows, + "balance_value", + "balance_fraction", + "balance_currency", + &bt->amount)) + { + GNUNET_free (bt); + GNUNET_break (0); + goto cleanup; + } + (void) memcpy (&bt->reserve_pub, reserve_pub, sizeof (bt->reserve_pub)); + if (NULL != rh_head) + { + rh_head->next = GNUNET_new (struct ReserveHistory); + rh_head = rh_head->next; + } + else + { + rh_head = GNUNET_new (struct ReserveHistory); + rh = rh_head; + } + rh_head->type = TALER_MINT_DB_RO_BANK_TO_MINT; + rh_head->details.bank = bt; + } + } + PQclear (result); + result = NULL; + { + struct GNUNET_HashCode blind_ev; + struct GNUNET_CRYPTO_EddsaSignature reserve_sig; + struct CollectableBlindcoin *cbc; + char *denom_pub_enc; + char *denom_sig_enc; + size_t denom_pub_enc_size; + size_t denom_sig_enc_size; + + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (reserve_pub), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "get_reserves_blindcoins", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + QUERY_ERR (result); + goto cleanup; + } + if (0 == (rows = PQntuples (result))) + { + ret = GNUNET_OK; /* Its OK if there are no withdrawls yet */ + goto cleanup; + } + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC ("blind_ev", &blind_ev), + TALER_DB_RESULT_SPEC_VAR ("denom_pub", &denom_pub_enc, &denom_pub_enc_size), + TALER_DB_RESULT_SPEC_VAR ("denom_sig", &denom_sig_enc, &denom_sig_enc_size), + TALER_DB_RESULT_SPEC ("reserve_sig", &reserve_sig), + TALER_DB_RESULT_SPEC_END + }; + GNUNET_assert (NULL != rh); + GNUNET_assert (NULL != rh_head); + GNUNET_assert (NULL == rh_head->next); + while (0 < rows) + { + if (GNUNET_YES != TALER_DB_extract_result (result, rs, --rows)) + { + GNUNET_break (0); + goto cleanup; + } + cbc = GNUNET_new (struct CollectableBlindcoin); + cbc->sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, + denom_sig_enc_size); + GNUNET_free (denom_sig_enc); + denom_sig_enc = NULL; + cbc->denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, + denom_pub_enc_size); + GNUNET_free (denom_pub_enc); + denom_pub_enc = NULL; + if ((NULL == cbc->sig) || (NULL == cbc->denom_pub)) + { + if (NULL != cbc->sig) + GNUNET_CRYPTO_rsa_signature_free (cbc->sig); + if (NULL != cbc->denom_pub) + GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); + GNUNET_free (cbc); + GNUNET_break (0); + goto cleanup; + } + (void) memcpy (&cbc->h_coin_envelope, &blind_ev, sizeof (blind_ev)); + (void) memcpy (&cbc->reserve_pub, reserve_pub, sizeof (cbc->reserve_pub)); + (void) memcpy (&cbc->reserve_sig, &reserve_sig, sizeof (cbc->reserve_sig)); + rh_head->next = GNUNET_new (struct ReserveHistory); + rh_head = rh_head->next; + rh_head->type = TALER_MINT_DB_RO_WITHDRAW_COIN; + rh_head->details.withdraw = cbc; + } + } + ret = GNUNET_OK; + + cleanup: + if (NULL != result) + PQclear (result); + if (GNUNET_SYSERR == ret) + { + TALER_MINT_DB_free_reserve_history (rh); + rh = NULL; + } + return rh; +} + + +/** + * Check if we have the specified deposit already in the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param deposit deposit to search for + * @return #GNUNET_YES if we know this operation, + * #GNUNET_NO if this deposit is unknown to us + */ +static int +postgres_have_deposit (void *cls, + struct TALER_MINTDB_Session *session, + const struct Deposit *deposit) +{ + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), + TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), + TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), + TALER_DB_QUERY_PARAM_END + }; + PGresult *result; + int ret; + + ret = GNUNET_SYSERR; + result = TALER_DB_exec_prepared (session->conn, + "get_deposit", + params); + if (PGRES_TUPLES_OK != + PQresultStatus (result)) + { + BREAK_DB_ERR (result); + goto cleanup; + } + + if (0 == PQntuples (result)) + { + ret = GNUNET_NO; + goto cleanup; + } + ret = GNUNET_YES; + + cleanup: + PQclear (result); + return ret; +} + + +/** + * Insert information about deposited coin into the + * database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session connection to the database + * @param deposit deposit information to store + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +static int +postgres_insert_deposit (void *cls, + struct TALER_MINTDB_Session *session, + const struct Deposit *deposit) +{ + char *denom_pub_enc; + char *denom_sig_enc; + char *json_wire_enc; + PGresult *result; + struct TALER_AmountNBO amount_nbo; + size_t denom_pub_enc_size; + size_t denom_sig_enc_size; + int ret; + + ret = GNUNET_SYSERR; + denom_pub_enc_size = + GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub, + &denom_pub_enc); + denom_sig_enc_size = + GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig, + &denom_sig_enc); + json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); + TALER_amount_hton (&amount_nbo, + &deposit->amount); + struct TALER_DB_QueryParam params[]= { + TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), + TALER_DB_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size), + TALER_DB_QUERY_PARAM_PTR (&deposit->transaction_id), + TALER_DB_QUERY_PARAM_PTR (&amount_nbo.value), + TALER_DB_QUERY_PARAM_PTR (&amount_nbo.fraction), + TALER_DB_QUERY_PARAM_PTR_SIZED (amount_nbo.currency, + TALER_CURRENCY_LEN - 1), + TALER_DB_QUERY_PARAM_PTR (&deposit->merchant_pub), + TALER_DB_QUERY_PARAM_PTR (&deposit->h_contract), + TALER_DB_QUERY_PARAM_PTR (&deposit->h_wire), + TALER_DB_QUERY_PARAM_PTR (&deposit->csig), + TALER_DB_QUERY_PARAM_PTR_SIZED (json_wire_enc, + strlen (json_wire_enc)), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, "insert_deposit", params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + goto cleanup; + } + ret = GNUNET_OK; + + cleanup: + PQclear (result); + GNUNET_free_non_null (denom_pub_enc); + GNUNET_free_non_null (denom_sig_enc); + GNUNET_free_non_null (json_wire_enc); + return ret; +} + + +/** + * Lookup refresh session data under the given public key. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database handle to use + * @param refresh_session_pub public key to use for the lookup + * @param refresh_session[OUT] where to store the result + * @return #GNUNET_YES on success, + * #GNUNET_NO if not found, + * #GNUNET_SYSERR on DB failure + */ +static int +postgres_get_refresh_session (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct RefreshSession *refresh_session) +{ + // FIXME: check logic! + int res; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, + "get_refresh_session", + params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Query failed: %s\n", + PQresultErrorMessage (result)); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + return GNUNET_NO; + + GNUNET_assert (1 == PQntuples (result)); + + /* We're done if the caller is only interested in + * whether the session exists or not */ + + if (NULL == refresh_session) + return GNUNET_YES; + + memset (session, 0, sizeof (struct RefreshSession)); + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("num_oldcoins", &refresh_session->num_oldcoins), + TALER_DB_RESULT_SPEC("num_newcoins", &refresh_session->num_newcoins), + TALER_DB_RESULT_SPEC("kappa", &refresh_session->kappa), + TALER_DB_RESULT_SPEC("noreveal_index", &refresh_session->noreveal_index), + TALER_DB_RESULT_SPEC_END + }; + + res = TALER_DB_extract_result (result, rs, 0); + + if (GNUNET_OK != res) + { + GNUNET_break (0); + PQclear (result); + return GNUNET_SYSERR; + } + + refresh_session->num_oldcoins = ntohs (refresh_session->num_oldcoins); + refresh_session->num_newcoins = ntohs (refresh_session->num_newcoins); + refresh_session->kappa = ntohs (refresh_session->kappa); + refresh_session->noreveal_index = ntohs (refresh_session->noreveal_index); + + PQclear (result); + return GNUNET_YES; +} + + +/** + * Store new refresh session data under the given public key. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param refresh_session session data to store + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ +static int +postgres_create_refresh_session (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct RefreshSession *refresh_session) +{ + // FIXME: actually store session data! + uint16_t noreveal_index; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&noreveal_index), + TALER_DB_QUERY_PARAM_END + }; + + noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15); + noreveal_index = htonl (noreveal_index); + + PGresult *result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_session", + params); + + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Store the given /refresh/melt request in the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param refresh_session session key of the melt operation + * @param oldcoin_index index of the coin to store + * @param melt melt operation + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ +static int +postgres_insert_refresh_melt (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + uint16_t oldcoin_index, + const struct RefreshMelt *melt) +{ + // FIXME: check logic! + uint16_t oldcoin_index_nbo = htons (oldcoin_index); + char *buf; + size_t buf_size; + PGresult *result; + + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub, + &buf); + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session), + TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&melt->coin.coin_pub), + TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_melt", + params); + } + GNUNET_free (buf); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Get information about melted coin details from the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param refresh_session session key of the melt operation + * @param oldcoin_index index of the coin to retrieve + * @param melt melt data to fill in + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ +static int +postgres_get_refresh_melt (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + uint16_t oldcoin_index, + struct RefreshMelt *melt) +{ + // FIXME: check logic! + GNUNET_break (0); + return GNUNET_SYSERR; +} + + +/** + * Store in the database which coin(s) we want to create + * in a given refresh operation. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ +static int +postgres_insert_refresh_order (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) +{ + // FIXME: check logic + uint16_t newcoin_index_nbo = htons (newcoin_index); + char *buf; + size_t buf_size; + PGresult *result; + + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, + &buf); + + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR (&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR (session_pub), + TALER_DB_QUERY_PARAM_PTR_SIZED (buf, buf_size), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_order", + params); + } + GNUNET_free (buf); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Lookup in the database the @a newcoin_index coin that we want to + * create in the given refresh operation. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return NULL on error (not found or internal error) + */ +static struct GNUNET_CRYPTO_rsa_PublicKey * +postgres_get_refresh_order (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index) +{ + // FIXME: check logic + char *buf; + size_t buf_size; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + uint16_t newcoin_index_nbo = htons (newcoin_index); + + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, "get_refresh_order", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return NULL; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + /* FIXME: may want to distinguish between different error cases! */ + return NULL; + } + GNUNET_assert (1 == PQntuples (result)); + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR ("denom_pub", &buf, &buf_size), + TALER_DB_RESULT_SPEC_END + }; + if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + GNUNET_break (0); + return NULL; + } + PQclear (result); + denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + GNUNET_free (buf); + return denom_pub; +} + + + +/** + * Store information about the commitment of the + * given coin for the given refresh session in the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param refresh_session_pub refresh session this commitment belongs to + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to refreshed (new) coins + * @param commit_coin coin commitment to store + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on error + */ +static int +postgres_insert_refresh_commit_coin (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + const struct RefreshCommitCoin *commit_coin) +{ + // FIXME: check logic! + uint16_t cnc_index_nbo = htons (i); + uint16_t newcoin_index_nbo = htons (j); + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->coin_ev, commit_coin->coin_ev_size), + TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->refresh_link->coin_priv_enc, + commit_coin->refresh_link->blinding_key_enc_size + + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, "insert_refresh_commit_coin", params); + + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Obtain information about the commitment of the + * given coin of the given refresh session from the database. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param refresh_session_pub refresh session the commitment belongs to + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to refreshed (new) coins + * @param commit_coin[OUT] coin commitment to return + * @return #GNUNET_OK on success + * #GNUNET_NO if not found + * #GNUNET_SYSERR on error + */ +static int +postgres_get_refresh_commit_coin (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int cnc_index, + unsigned int newcoin_index, + struct RefreshCommitCoin *cc) +{ + // FIXME: check logic! + uint16_t cnc_index_nbo = htons (cnc_index); + uint16_t newcoin_index_nbo = htons (newcoin_index); + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_END + }; + char *c_buf; + size_t c_buf_size; + char *rl_buf; + size_t rl_buf_size; + struct TALER_RefreshLinkEncrypted *rl; + + PGresult *result = TALER_DB_exec_prepared (session->conn, "get_refresh_commit_coin", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR("coin_ev", &c_buf, &c_buf_size), + TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &rl_buf, &rl_buf_size), + TALER_DB_RESULT_SPEC_END + }; + if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + if (rl_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) + { + GNUNET_free (c_buf); + GNUNET_free (rl_buf); + return GNUNET_SYSERR; + } + rl = TALER_refresh_link_encrypted_decode (rl_buf, + rl_buf_size); + GNUNET_free (rl_buf); + cc->refresh_link = rl; + cc->coin_ev = c_buf; + cc->coin_ev_size = c_buf_size; + return GNUNET_YES; +} + + +/** + * Store the commitment to the given (encrypted) refresh link data + * for the given refresh session. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param refresh_session_pub public key of the refresh session this + * commitment belongs with + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to melted (old) coins + * @param commit_link link information to store + * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success + */ +static int +postgres_insert_refresh_commit_link (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + const struct RefreshCommitLink *commit_link) +{ + // FIXME: check logic! + uint16_t cnc_index_nbo = htons (i); + uint16_t oldcoin_index_nbo = htons (j); + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(&commit_link->transfer_pub), + TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&commit_link->shared_secret_enc), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_commit_link", + params); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 != strcmp ("1", PQcmdTuples (result))) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Obtain the commited (encrypted) refresh link data + * for the given refresh session. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection to use + * @param refresh_session_pub public key of the refresh session this + * commitment belongs with + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to melted (old) coins + * @param cc[OUT] link information to return + * @return #GNUNET_SYSERR on internal error, + * #GNUNET_NO if commitment was not found + * #GNUNET_OK on success + */ +static int +postgres_get_refresh_commit_link (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int cnc_index, + unsigned int oldcoin_index, + struct RefreshCommitLink *cc) +{ + // FIXME: check logic! + uint16_t cnc_index_nbo = htons (cnc_index); + uint16_t oldcoin_index_nbo = htons (oldcoin_index); + + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), + TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, + "get_refresh_commit_link", + params); + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("transfer_pub", &cc->transfer_pub), + TALER_DB_RESULT_SPEC("link_secret_enc", &cc->shared_secret_enc), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + GNUNET_free (cc); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Insert signature of a new coin generated during refresh into + * the database indexed by the refresh session and the index + * of the coin. This data is later used should an old coin + * be used to try to obtain the private keys during "/refresh/link". + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param session_pub refresh session + * @param newcoin_index coin index + * @param ev_sig coin signature + * @return #GNUNET_OK on success + */ +static int +postgres_insert_refresh_collectable (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) +{ + // FIXME: check logic! + uint16_t newcoin_index_nbo = htons (newcoin_index); + char *buf; + size_t buf_size; + PGresult *result; + + buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, + &buf); + { + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), + TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), + TALER_DB_QUERY_PARAM_END + }; + result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_collectable", + params); + } + GNUNET_free (buf); + if (PGRES_COMMAND_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + PQclear (result); + return GNUNET_OK; +} + + +/** + * Obtain the link data of a coin, that is the encrypted link + * information, the denomination keys and the signatures. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param coin_pub public key to use to retrieve linkage data + * @return all known link data for the coin + */ +static struct LinkDataList * +postgres_get_link (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) +{ + // FIXME: check logic! + struct LinkDataList *ldl; + struct LinkDataList *pos; + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(coin_pub), + TALER_DB_QUERY_PARAM_END + }; + PGresult *result = TALER_DB_exec_prepared (session->conn, "get_link", params); + + ldl = NULL; + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return NULL; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return NULL; + } + + + int i = 0; + + for (i = 0; i < PQntuples (result); i++) + { + struct TALER_RefreshLinkEncrypted *link_enc; + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct GNUNET_CRYPTO_rsa_Signature *sig; + char *ld_buf; + size_t ld_buf_size; + char *pk_buf; + size_t pk_buf_size; + char *sig_buf; + size_t sig_buf_size; + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC_VAR("link_vector_enc", &ld_buf, &ld_buf_size), + TALER_DB_RESULT_SPEC_VAR("denom_pub", &pk_buf, &pk_buf_size), + TALER_DB_RESULT_SPEC_VAR("ev_sig", &sig_buf, &sig_buf_size), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_OK != TALER_DB_extract_result (result, rs, i)) + { + PQclear (result); + GNUNET_break (0); + TALER_db_link_data_list_free (ldl); + return NULL; + } + if (ld_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) + { + PQclear (result); + GNUNET_free (pk_buf); + GNUNET_free (sig_buf); + GNUNET_free (ld_buf); + TALER_db_link_data_list_free (ldl); + return NULL; + } + // FIXME: use util API for this! + link_enc = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + + ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); + link_enc->blinding_key_enc = (const char *) &link_enc[1]; + link_enc->blinding_key_enc_size = ld_buf_size - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey); + memcpy (link_enc->coin_priv_enc, + ld_buf, + ld_buf_size); + + sig = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, + sig_buf_size); + denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, + pk_buf_size); + GNUNET_free (pk_buf); + GNUNET_free (sig_buf); + GNUNET_free (ld_buf); + if ( (NULL == sig) || + (NULL == denom_pub) ) + { + if (NULL != denom_pub) + GNUNET_CRYPTO_rsa_public_key_free (denom_pub); + if (NULL != sig) + GNUNET_CRYPTO_rsa_signature_free (sig); + GNUNET_free (link_enc); + GNUNET_break (0); + PQclear (result); + TALER_db_link_data_list_free (ldl); + return NULL; + } + pos = GNUNET_new (struct LinkDataList); + pos->next = ldl; + pos->link_data_enc = link_enc; + pos->denom_pub = denom_pub; + pos->ev_sig = sig; + ldl = pos; + } + return ldl; +} + + +/** + * Obtain shared secret and transfer public key from the public key of + * the coin. This information and the link information returned by + * #TALER_db_get_link() enable the owner of an old coin to determine + * the private keys of the new coins after the melt. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param coin_pub public key of the coin + * @param transfer_pub[OUT] public transfer key + * @param shared_secret_enc[OUT] set to shared secret + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure (not found) + * #GNUNET_SYSERR on internal failure (database issue) + */ +static int +postgres_get_transfer (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + struct TALER_EncryptedLinkSecret *shared_secret_enc) +{ + // FIXME: check logic! + struct TALER_DB_QueryParam params[] = { + TALER_DB_QUERY_PARAM_PTR(coin_pub), + TALER_DB_QUERY_PARAM_END + }; + + PGresult *result = TALER_DB_exec_prepared (session->conn, "get_transfer", params); + + if (PGRES_TUPLES_OK != PQresultStatus (result)) + { + BREAK_DB_ERR (result); + PQclear (result); + return GNUNET_SYSERR; + } + + if (0 == PQntuples (result)) + { + PQclear (result); + return GNUNET_NO; + } + + if (1 != PQntuples (result)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "got %d tuples for get_transfer\n", + PQntuples (result)); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + struct TALER_DB_ResultSpec rs[] = { + TALER_DB_RESULT_SPEC("transfer_pub", transfer_pub), + TALER_DB_RESULT_SPEC("link_secret_enc", shared_secret_enc), + TALER_DB_RESULT_SPEC_END + }; + + if (GNUNET_OK != TALER_DB_extract_result (result, rs, 0)) + { + PQclear (result); + GNUNET_break (0); + return GNUNET_SYSERR; + } + + PQclear (result); + return GNUNET_OK; +} + + +/** + * Compile a list of all (historic) transactions performed + * with the given coin (/refresh/melt and /deposit operations). + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param session database connection + * @param coin_pub coin to investigate + * @return list of transactions, NULL if coin is fresh + */ +static struct TALER_MINT_DB_TransactionList * +postgres_get_coin_transactions (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) +{ + // FIXME: check logic! + GNUNET_break (0); // FIXME: implement! + return NULL; +} + + + +/** + * Initialize Postgres database subsystem. + * + * @param cls a configuration instance + * @return NULL on error, otherwise a `struct TALER_MINTDB_Plugin` + */ +void * +libtaler_plugin_mintdb_postgres_init (void *cls) +{ + struct GNUNET_CONFIGURATION_Handle *cfg = cls; + struct PostgresClosure *pg; + struct TALER_MINTDB_Plugin *plugin; + + pg = GNUNET_new (struct PostgresClosure); + + if (0 != pthread_key_create (&pg->db_conn_threadlocal, + &db_conn_destroy)) + { + LOG_ERROR ("Cannnot create pthread key.\n"); + return NULL; + } + /* FIXME: use configuration section with "postgres" in its name... */ + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "mint", "db", + &pg->TALER_MINT_db_connection_cfg_str)) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + "mint", + "db"); + return NULL; + } + plugin = GNUNET_new (struct TALER_MINTDB_Plugin); + plugin->cls = pg; + + return plugin; +} + + +/** + * Shutdown Postgres database subsystem. + * + * @param cls a `struct TALER_MINTDB_Plugin` + * @return NULL (always) + */ +void * +libtaler_plugin_mintdb_postgres_done (void *cls) +{ + struct TALER_MINTDB_Plugin *plugin = cls; + struct PostgresClosure *pg = plugin->cls; + + GNUNET_free (pg); + GNUNET_free (plugin); + return NULL; +} + +/* end of plugin_mintdb_postgres.c */ diff --git a/src/mint/taler-mint-dbinit.c b/src/mint/taler-mint-dbinit.c index 838f98e25..060eabc7b 100644 --- a/src/mint/taler-mint-dbinit.c +++ b/src/mint/taler-mint-dbinit.c @@ -22,7 +22,7 @@ #include #include #include "taler_util.h" -#include "mint_db.h" +#include "taler_mintdb_plugin.h" /** diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 7903d5c1c..9adf26dfd 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -35,7 +35,7 @@ #include "taler-mint-httpd_withdraw.h" #include "taler-mint-httpd_refresh.h" #include "taler-mint-httpd_keystate.h" -#include "mint_db.h" +#include "taler_mintdb_plugin.h" /** @@ -260,16 +260,7 @@ mint_serve_process_config (const char *mint_directory) GNUNET_free (master_pub_str); if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint", "db", - &db_cfg)) - { - fprintf (stderr, - "invalid configuration: mint.db\n"); - return GNUNET_NO; - } - if (GNUNET_OK != - TALER_MINT_DB_init (db_cfg)) + TALER_MINT_plugin_load (cfg)) { fprintf (stderr, "failed to initialize DB subsystem\n"); diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 0c3675d38..292ef68fa 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -29,9 +29,9 @@ #include "taler-mint-httpd_db.h" #include "taler_signatures.h" #include "taler-mint-httpd_responses.h" -#include "mint_db.h" #include "taler_util.h" #include "taler-mint-httpd_keystate.h" +#include "plugin.h" /** @@ -48,7 +48,7 @@ int TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, const struct Deposit *deposit) { - PGconn *db_conn; + struct TALER_MINTDB_Session *session; struct TALER_MINT_DB_TransactionList *tl; struct TALER_MINT_DB_TransactionList *pos; struct TALER_Amount spent; @@ -59,14 +59,16 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, struct TALER_MINT_DenomKeyIssuePriv *dki; int ret; - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) + if (NULL == (session = plugin->get_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_YES == - TALER_MINT_DB_have_deposit (db_conn, - deposit)) + plugin->have_deposit (plugin->cls, + session, + deposit)) { return TALER_MINT_reply_deposit_success (connection, &deposit->coin.coin_pub, @@ -88,13 +90,15 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, TALER_MINT_key_state_release (mks); if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) + plugin->start (plugin->cls, + session)) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - tl = TALER_MINT_DB_get_coin_transactions (db_conn, - &deposit->coin.coin_pub); + tl = plugin->get_coin_transactions (plugin->cls, + session, + &deposit->coin.coin_pub); spent = fee_deposit; /* fee for THIS transaction */ if (GNUNET_OK != TALER_amount_add (&spent, @@ -155,7 +159,8 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, if (0 < TALER_amount_cmp (&spent, &value)) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); ret = TALER_MINT_reply_deposit_insufficient_funds (connection, tl); TALER_MINT_DB_free_coin_transaction_list (tl); @@ -164,16 +169,19 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, TALER_MINT_DB_free_coin_transaction_list (tl); if (GNUNET_OK != - TALER_MINT_DB_insert_deposit (db_conn, - deposit)) + plugin->insert_deposit (plugin->cls, + session, + deposit)) { LOG_WARNING ("Failed to store /deposit information in database\n"); - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_OK != - TALER_MINT_DB_commit (db_conn)) + plugin->commit (plugin->cls, + session)) { LOG_WARNING ("/deposit transaction commit failed\n"); return TALER_MINT_reply_commit_error (connection); @@ -200,17 +208,19 @@ int TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) { - PGconn *db_conn; + struct TALER_MINTDB_Session *session; struct ReserveHistory *rh; int res; - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) + if (NULL == (session = plugin->get_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - rh = TALER_MINT_DB_get_reserve_history (db_conn, - reserve_pub); + rh = plugin->get_reserve_history (plugin->cls, + session, + reserve_pub); if (NULL == rh) return TALER_MINT_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, @@ -245,7 +255,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, size_t blinded_msg_len, const struct GNUNET_CRYPTO_EddsaSignature *signature) { - PGconn *db_conn; + struct TALER_MINTDB_Session *session; struct ReserveHistory *rh; const struct ReserveHistory *pos; struct MintKeyState *key_state; @@ -266,14 +276,16 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, blinded_msg_len, &h_blind); - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) + if (NULL == (session = plugin->get_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - res = TALER_MINT_DB_get_collectable_blindcoin (db_conn, - &h_blind, - &collectable); + res = plugin->get_collectable_blindcoin (plugin->cls, + session, + &h_blind, + &collectable); if (GNUNET_SYSERR == res) { GNUNET_break (0); @@ -305,18 +317,21 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, "Denomination not found"); } if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) + plugin->start (plugin->cls, + session)) { GNUNET_break (0); TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_internal_db_error (connection); } - rh = TALER_MINT_DB_get_reserve_history (db_conn, - reserve); + rh = plugin->get_reserve_history (plugin->cls, + session, + reserve); if (NULL == rh) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, @@ -336,7 +351,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, &value, &fee_withdraw)) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_internal_db_error (connection); } @@ -356,7 +372,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, &deposit_total, &pos->details.bank->amount)) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_internal_db_error (connection); } @@ -375,7 +392,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, &withdraw_total, &value)) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_internal_db_error (connection); } @@ -392,7 +410,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, &balance)) { TALER_MINT_key_state_release (key_state); - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); res = TALER_MINT_reply_withdraw_sign_insufficient_funds (connection, rh); TALER_MINT_DB_free_reserve_history (rh); @@ -408,7 +427,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, if (NULL == sig) { GNUNET_break (0); - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_error (connection, "Internal error"); } @@ -420,18 +440,21 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, &collectable.h_coin_envelope); collectable.reserve_sig = *signature; if (GNUNET_OK != - TALER_MINT_DB_insert_collectable_blindcoin (db_conn, - &h_blind, - amount_required, - &collectable)) + plugin->insert_collectable_blindcoin (plugin->cls, + session, + &h_blind, + amount_required, + &collectable)) { GNUNET_break (0); GNUNET_CRYPTO_rsa_signature_free (sig); - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_OK != - TALER_MINT_DB_commit (db_conn)) + plugin->commit (plugin->cls, + session)) { LOG_WARNING ("/withdraw/sign transaction commit failed\n"); return TALER_MINT_reply_commit_error (connection); @@ -448,7 +471,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, * the database. * * @param connection the connection to send errors to - * @param db_conn the database connection + * @param session the database connection * @param key_state the mint's key state * @param session_pub the refresh session's public key * @param coin_public_info the coin to melt @@ -460,7 +483,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, */ static int refresh_accept_melts (struct MHD_Connection *connection, - PGconn *db_conn, + struct TALER_MINTDB_Session *session, const struct MintKeyState *key_state, const struct GNUNET_HashCode *melt_hash, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, @@ -489,8 +512,9 @@ refresh_accept_melts (struct MHD_Connection *connection, TALER_amount_ntoh (&coin_value, &dki->value); - tl = TALER_MINT_DB_get_coin_transactions (db_conn, - &coin_public_info->coin_pub); + tl = plugin->get_coin_transactions (plugin->cls, + session, + &coin_public_info->coin_pub); /* FIXME: #3636: compute how much value is left with this coin and compare to `expected_value`! (subtract from "coin_value") */ coin_residual = coin_value; @@ -518,10 +542,11 @@ refresh_accept_melts (struct MHD_Connection *connection, melt.melt_hash = *melt_hash; melt.amount = coin_details->melt_amount; if (GNUNET_OK != - TALER_MINT_DB_insert_refresh_melt (db_conn, - session_pub, - oldcoin_index, - &melt)) + plugin->insert_refresh_melt (plugin->cls, + session, + session_pub, + oldcoin_index, + &melt)) { GNUNET_break (0); return GNUNET_SYSERR; @@ -570,37 +595,42 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, struct RefreshCommitLink *const* commit_link) { struct MintKeyState *key_state; - struct RefreshSession session; - PGconn *db_conn; + struct RefreshSession refresh_session; + struct TALER_MINTDB_Session *session; int res; unsigned int i; unsigned int j; - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) + if (NULL == (session = plugin->get_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) + plugin->start (plugin->cls, + session)) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &session); + res = plugin->get_refresh_session (plugin->cls, + session, + refresh_session_pub, + &refresh_session); if (GNUNET_YES == res) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); res = TALER_MINT_reply_refresh_melt_success (connection, - &session.session_hash, - session.noreveal_index); + &refresh_session.session_hash, + refresh_session.noreveal_index); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } if (GNUNET_SYSERR == res) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } @@ -610,7 +640,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, { if (GNUNET_OK != (res = refresh_accept_melts (connection, - db_conn, + session, key_state, melt_hash, refresh_session_pub, @@ -619,7 +649,8 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, i))) { TALER_MINT_key_state_release (key_state); - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } } @@ -629,12 +660,14 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, for (i=0;iinsert_refresh_order (plugin->cls, + session, + refresh_session_pub, + i, + denom_pubs[i])) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } } @@ -644,13 +677,15 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, for (j = 0; j < num_new_denoms; j++) { if (GNUNET_OK != - TALER_MINT_DB_insert_refresh_commit_coin (db_conn, - refresh_session_pub, - i, - j, - &commit_coin[i][j])) + plugin->insert_refresh_commit_coin (plugin->cls, + session, + refresh_session_pub, + i, + j, + &commit_coin[i][j])) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } } @@ -660,13 +695,15 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, for (j = 0; j < coin_count; j++) { if (GNUNET_OK != - TALER_MINT_DB_insert_refresh_commit_link (db_conn, - refresh_session_pub, - i, - j, - &commit_link[i][j])) + plugin->insert_refresh_commit_link (plugin->cls, + session, + refresh_session_pub, + i, + j, + &commit_link[i][j])) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } } @@ -674,34 +711,37 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, /* store 'global' session data */ - session.melt_sig = *client_signature; - session.session_hash = *melt_hash; - session.num_oldcoins = coin_count; - session.num_newcoins = num_new_denoms; - session.kappa = KAPPA; // FIXME... - session.noreveal_index + refresh_session.melt_sig = *client_signature; + refresh_session.session_hash = *melt_hash; + refresh_session.num_oldcoins = coin_count; + refresh_session.num_newcoins = num_new_denoms; + refresh_session.kappa = KAPPA; // FIXME... + refresh_session.noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, - session.kappa); + refresh_session.kappa); if (GNUNET_OK != - (res = TALER_MINT_DB_create_refresh_session (db_conn, - refresh_session_pub, - &session))) + (res = plugin->create_refresh_session (plugin->cls, + session, + refresh_session_pub, + &refresh_session))) { - TALER_MINT_DB_rollback (db_conn); + plugin->rollback (plugin->cls, + session); return TALER_MINT_reply_internal_db_error (connection); } if (GNUNET_OK != - TALER_MINT_DB_commit (db_conn)) + plugin->commit (plugin->cls, + session)) { LOG_WARNING ("/refresh/melt transaction commit failed\n"); return TALER_MINT_reply_commit_error (connection); } return TALER_MINT_reply_refresh_melt_success (connection, - &session.session_hash, - session.noreveal_index); + &refresh_session.session_hash, + refresh_session.noreveal_index); } @@ -712,7 +752,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * Then derives the shared secret for each kappa, and check that they match. * * @param connection the MHD connection to handle - * @param db_conn database connection to use + * @param session database connection to use * @param refresh_session session to query * @param off commitment offset to check * @param num_oldcoins size of the @a transfer_privs and @a melts arrays @@ -726,7 +766,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, */ static int check_commitment (struct MHD_Connection *connection, - PGconn *db_conn, + struct TALER_MINTDB_Session *session, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, unsigned int off, unsigned int num_oldcoins, @@ -749,11 +789,12 @@ check_commitment (struct MHD_Connection *connection, struct TALER_LinkSecret shared_secret; struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check; - res = TALER_MINT_DB_get_refresh_commit_link (db_conn, - refresh_session, - off, - j, - &commit_link); + res = plugin->get_refresh_commit_link (plugin->cls, + session, + refresh_session, + off, + j, + &commit_link); if (GNUNET_OK != res) { GNUNET_break (0); @@ -842,11 +883,12 @@ check_commitment (struct MHD_Connection *connection, char *buf; size_t buf_len; - res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, - refresh_session, - off, - j, - &commit_coin); + res = plugin->get_refresh_commit_coin (plugin->cls, + session, + refresh_session, + off, + j, + &commit_coin); if (GNUNET_OK != res) { GNUNET_break (0); @@ -914,7 +956,7 @@ check_commitment (struct MHD_Connection *connection, * envelope from the database and performs the signing operation. * * @param connection the MHD connection to handle - * @param db_conn database connection to use + * @param session database connection to use * @param refresh_session session to query * @param key_state key state to lookup denomination pubs * @param denom_pub denomination key for the coin to create @@ -925,7 +967,7 @@ check_commitment (struct MHD_Connection *connection, */ static struct GNUNET_CRYPTO_rsa_Signature * refresh_mint_coin (struct MHD_Connection *connection, - PGconn *db_conn, + struct TALER_MINTDB_Session *session, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, struct MintKeyState *key_state, const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, @@ -937,11 +979,12 @@ refresh_mint_coin (struct MHD_Connection *connection, struct GNUNET_CRYPTO_rsa_Signature *ev_sig; int res; - res = TALER_MINT_DB_get_refresh_commit_coin (db_conn, - refresh_session, - noreveal_index, - coin_off, - &commit_coin); + res = plugin->get_refresh_commit_coin (plugin->cls, + session, + refresh_session, + noreveal_index, + coin_off, + &commit_coin); if (GNUNET_OK != res) { GNUNET_break (0); @@ -962,10 +1005,11 @@ refresh_mint_coin (struct MHD_Connection *connection, return NULL; } if (GNUNET_OK != - TALER_MINT_DB_insert_refresh_collectable (db_conn, - refresh_session, - coin_off, - ev_sig)) + plugin->insert_refresh_collectable (plugin->cls, + session, + refresh_session, + coin_off, + ev_sig)) { GNUNET_break (0); GNUNET_CRYPTO_rsa_signature_free (ev_sig); @@ -997,7 +1041,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, struct GNUNET_CRYPTO_EcdsaPrivateKey *const*transfer_privs) { int res; - PGconn *db_conn; + struct TALER_MINTDB_Session *session; struct RefreshSession refresh_session; struct MintKeyState *key_state; struct RefreshMelt *melts; @@ -1007,15 +1051,17 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, unsigned int j; unsigned int off; - if (NULL == (db_conn = TALER_MINT_DB_get_connection (GNUNET_NO))) + if (NULL == (session = plugin->get_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - res = TALER_MINT_DB_get_refresh_session (db_conn, - refresh_session_pub, - &refresh_session); + res = plugin->get_refresh_session (plugin->cls, + session, + refresh_session_pub, + &refresh_session); if (GNUNET_NO == res) return TALER_MINT_reply_arg_invalid (connection, "session_pub"); @@ -1032,10 +1078,11 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, for (j=0;jget_refresh_melt (plugin->cls, + session, + refresh_session_pub, + j, + &melts[j])) { GNUNET_break (0); GNUNET_free (melts); @@ -1046,9 +1093,10 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *)); for (j=0;jget_refresh_order (plugin->cls, + session, + refresh_session_pub, + j); if (NULL == denom_pubs[j]) { GNUNET_break (0); @@ -1069,7 +1117,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, off = 1; if (GNUNET_OK != (res = check_commitment (connection, - db_conn, + session, refresh_session_pub, i + off, refresh_session.num_oldcoins, @@ -1089,7 +1137,8 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, /* Client request OK, start transaction */ if (GNUNET_OK != - TALER_MINT_DB_transaction (db_conn)) + plugin->start (plugin->cls, + session)) { GNUNET_break (0); for (j=0;jcommit (plugin->cls, + session)) { LOG_WARNING ("/refresh/reveal transaction commit failed\n"); for (i=0;iget_session (plugin->cls, + GNUNET_NO))) { GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } - res = TALER_db_get_transfer (db_conn, - coin_pub, - &transfer_pub, - &shared_secret_enc); + res = plugin->get_transfer (plugin->cls, + session, + coin_pub, + &transfer_pub, + &shared_secret_enc); if (GNUNET_SYSERR == res) { GNUNET_break (0); @@ -1190,7 +1242,9 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, } GNUNET_assert (GNUNET_OK == res); - ldl = TALER_db_get_link (db_conn, coin_pub); + ldl = plugin->get_link (plugin->cls, + session, + coin_pub); if (NULL == ldl) { return TALER_MINT_reply_json_pack (connection, diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index a40e3ae22..dbfecccd1 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -25,7 +25,7 @@ #include #include #include "taler_util.h" -#include "mint_db.h" +#include "taler_mintdb_plugin.h" /** diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 37d6d23d5..e411e0d8e 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -32,7 +32,7 @@ #include #include #include -#include "mint_db.h" +#include "taler_mintdb_plugin.h" #include "taler_signatures.h" #include "taler_util.h" #include "taler-mint-httpd_parsing.h" diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index e62521ef4..d4979288d 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -24,7 +24,7 @@ #include #include #include -#include "mint_db.h" +#include "taler_mintdb_plugin.h" #include "taler_signatures.h" #include "taler_util.h" #include "taler-mint-httpd_parsing.h" diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index df3f0cd5d..958d234b1 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -24,7 +24,7 @@ #include #include "taler_util.h" #include "taler_signatures.h" -#include "mint_db.h" +#include "taler_mintdb_plugin.h" #include "db_pq.h" diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h new file mode 100644 index 000000000..d330b817b --- /dev/null +++ b/src/mint/taler_mintdb_plugin.h @@ -0,0 +1,1002 @@ +/* + This file is part of TALER + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) + + 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, If not, see +*/ +/** + * @file mint/mint_db.h + * @brief Low-level (statement-level) database access for the mint + * @author Florian Dold + * @author Christian Grothoff + */ +#ifndef MINT_DB_H +#define MINT_DB_H + +#include +#include "taler_util.h" + + +/** + * Information we keep on bank transfer(s) that established a reserve. + */ +struct BankTransfer +{ + + /** + * Public key of the reserve that was filled. + */ + struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + + /** + * Amount that was transferred to the mint. + */ + struct TALER_Amount amount; + + /** + * Detailed wire information about the transaction. + */ + const json_t *wire; + +}; + + +/** + * A summary of a Reserve + */ +struct Reserve +{ + /** + * The reserve's public key. This uniquely identifies the reserve + */ + struct GNUNET_CRYPTO_EddsaPublicKey *pub; + + /** + * The balance amount existing in the reserve + */ + struct TALER_Amount balance; + + /** + * The expiration date of this reserve + */ + struct GNUNET_TIME_Absolute expiry; +}; + + +/** + * Information we keep for a withdrawn coin to reproduce + * the /withdraw operation if needed, and to have proof + * that a reserve was drained by this amount. + */ +struct CollectableBlindcoin +{ + + /** + * Our signature over the (blinded) coin. + */ + struct GNUNET_CRYPTO_rsa_Signature *sig; + + /** + * Denomination key (which coin was generated). + */ + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + + /** + * Public key of the reserve that was drained. + */ + struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + + /** + * Hash over the blinded message, needed to verify + * the @e reserve_sig. + */ + struct GNUNET_HashCode h_coin_envelope; + + /** + * Signature confirming the withdrawl, matching @e reserve_pub, + * @e denom_pub and @e h_coin_envelope. + */ + struct GNUNET_CRYPTO_EddsaSignature reserve_sig; +}; + + + +/** + * Types of operations on a reserved. + */ +enum TALER_MINT_DB_ReserveOperation +{ + /** + * Money was deposited into the reserve via a bank transfer. + */ + TALER_MINT_DB_RO_BANK_TO_MINT = 0, + + /** + * A Coin was withdrawn from the reserve using /withdraw. + */ + TALER_MINT_DB_RO_WITHDRAW_COIN = 1 +}; + + +/** + * Reserve history as a linked list. Lists all of the transactions + * associated with this reserve (such as the bank transfers that + * established the reserve and all /withdraw operations we have done + * since). + */ +struct ReserveHistory +{ + + /** + * Next entry in the reserve history. + */ + struct ReserveHistory *next; + + /** + * Type of the event, determins @e details. + */ + enum TALER_MINT_DB_ReserveOperation type; + + /** + * Details of the operation, depending on @e type. + */ + union + { + + /** + * Details about a bank transfer to the mint. + */ + struct BankTransfer *bank; + + /** + * Details about a /withdraw operation. + */ + struct CollectableBlindcoin *withdraw; + + } details; + +}; + + +/** + * Specification for a /deposit operation. + */ +struct Deposit +{ + /** + * Information about the coin that is being deposited. + */ + struct TALER_CoinPublicInfo coin; + + /** + * ECDSA signature affirming that the customer intends + * this coin to be deposited at the merchant identified + * by @e h_wire in relation to the contract identified + * by @e h_contract. + */ + struct GNUNET_CRYPTO_EcdsaSignature csig; + + /** + * Public key of the merchant. Enables later identification + * of the merchant in case of a need to rollback transactions. + */ + struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; + + /** + * Hash over the contract between merchant and customer + * (remains unknown to the Mint). + */ + struct GNUNET_HashCode h_contract; + + /** + * Hash of the (canonical) representation of @e wire, used + * to check the signature on the request. Generated by + * the mint from the detailed wire data provided by the + * merchant. + */ + struct GNUNET_HashCode h_wire; + + /** + * Detailed wire information for executing the transaction. + */ + const json_t *wire; + + /** + * Merchant-generated transaction ID to detect duplicate + * transactions. + */ + uint64_t transaction_id; + + /** + * Fraction of the coin's remaining value to be deposited. + * The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount; + +}; + + +/** + * Global information for a refreshing session. Includes + * dimensions of the operation, security parameters and + * client signatures from "/refresh/melt" and "/refresh/commit". + */ +struct RefreshSession +{ + /** + * Signature over the commitments by the client, + * only valid if @e has_commit_sig is set. + */ + struct GNUNET_CRYPTO_EddsaSignature commit_sig; + + /** + * Hash over coins to melt and coins to create of the + * refresh session. + */ + struct GNUNET_HashCode session_hash; + + /** + * Signature over the melt by the client. + */ + struct GNUNET_CRYPTO_EddsaSignature melt_sig; + + /** + * Number of coins we are melting. + */ + uint16_t num_oldcoins; + + /** + * Number of new coins we are creating. + */ + uint16_t num_newcoins; + + /** + * Number of parallel operations we perform for the cut and choose. + * (must be greater or equal to three for security). 0 if not yet + * known. + */ + uint16_t kappa; + + /** + * Index (smaller @e kappa) which the mint has chosen to not + * have revealed during cut and choose. + */ + uint16_t noreveal_index; + +}; + + +/** + * Specification for coin in a /refresh/melt operation. + */ +struct RefreshMelt +{ + /** + * Information about the coin that is being melted. + */ + struct TALER_CoinPublicInfo coin; + + /** + * Signature over the melting operation. + */ + struct GNUNET_CRYPTO_EcdsaSignature coin_sig; + + /** + * Which melting operation should the coin become a part of. + */ + struct GNUNET_HashCode melt_hash; + + /** + * How much value is being melted? + * This amount includes the fees, so the final amount contributed + * to the melt is this value minus the fee for melting the coin. + */ + struct TALER_Amount amount; + +}; + + +/** + * We have as many `struct RefreshCommitCoin` as there are new + * coins being created by the refresh (for each of the kappa + * sets). These are the coins we ask the mint to sign if the + * respective set is selected. + */ +struct RefreshCommitCoin +{ + + /** + * Encrypted data allowing those able to decrypt it to derive + * the private keys of the new coins created by the refresh. + */ + struct TALER_RefreshLinkEncrypted *refresh_link; + + /** + * Blinded message to be signed (in envelope), with @e coin_env_size bytes. + */ + char *coin_ev; + + /** + * Number of bytes in @e coin_ev. + */ + size_t coin_ev_size; + +}; + + +/** + * For each (old) coin being melted, we have a `struct + * RefreshCommitLink` that allows the user to find the shared secret + * to decrypt the respective refresh links for the new coins in the + * `struct RefreshCommitCoin`. + */ +struct RefreshCommitLink +{ + /** + * Transfer public key (FIXME: explain!) + */ + struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; + + /** + * Encrypted shared secret to decrypt the link. + */ + struct TALER_EncryptedLinkSecret shared_secret_enc; +}; + + +/** + * Linked list of refresh information linked to a coin. + */ +struct LinkDataList +{ + /** + * Information is stored in a NULL-terminated linked list. + */ + struct LinkDataList *next; + + /** + * Link data, used to recover the private key of the coin + * by the owner of the old coin. + */ + struct TALER_RefreshLinkEncrypted *link_data_enc; + + /** + * Denomination public key, determines the value of the coin. + */ + struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + + /** + * Signature over the blinded envelope. + */ + struct GNUNET_CRYPTO_rsa_Signature *ev_sig; +}; + + +/** + * Specification for a /lock operation. + */ +struct Lock +{ + /** + * Information about the coin that is being melted. + */ + struct TALER_CoinPublicInfo coin; + + /** + * Signature over the melting operation. + */ + const struct GNUNET_CRYPTO_EcdsaSignature coin_sig; + + /** + * How much value is being melted? + */ + struct TALER_Amount amount; + + // FIXME: more needed... +}; + + +/** + * Enumeration to classify the different types of transactions + * that can be done with a coin. + */ +enum TALER_MINT_DB_TransactionType +{ + /** + * /deposit operation. + */ + TALER_MINT_DB_TT_DEPOSIT = 0, + + /** + * /refresh/melt operation. + */ + TALER_MINT_DB_TT_REFRESH_MELT = 1, + + /** + * /lock operation. + */ + TALER_MINT_DB_TT_LOCK = 2 +}; + + +/** + * List of transactions we performed for a particular coin. + */ +struct TALER_MINT_DB_TransactionList +{ + + /** + * Next pointer in the NULL-terminated linked list. + */ + struct TALER_MINT_DB_TransactionList *next; + + /** + * Type of the transaction, determines what is stored in @e details. + */ + enum TALER_MINT_DB_TransactionType type; + + /** + * Details about the transaction, depending on @e type. + */ + union + { + + /** + * Details if transaction was a /deposit operation. + */ + struct Deposit *deposit; + + /** + * Details if transaction was a /refresh/melt operation. + */ + struct RefreshMelt *melt; + + /** + * Details if transaction was a /lock operation. + */ + struct Lock *lock; + + } details; + +}; + + +/** + * Handle for a database session (per-thread, for transactions). + */ +struct TALER_MINTDB_Session; + + +/** + * The plugin API, returned from the plugin's "init" function. + * The argument given to "init" is simply a configuration handle. + */ +struct TALER_MINTDB_Plugin +{ + + /** + * Closure for all callbacks. + */ + void *cls; + + /** + * Get the thread-local database-handle. + * Connect to the db if the connection does not exist yet. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param temporary #GNUNET_YES to use a temporary schema; #GNUNET_NO to use the + * database default one + * @param the database connection, or NULL on error + */ + struct TALER_MINTDB_Session * + (*get_session) (void *cls, + int temporary); + + + /** + * Drop the temporary taler schema. This is only useful for testcases. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ + int + (*drop_temporary) (void *cls, + struct TALER_MINTDB_Session *db); + + + /** + * Create the necessary tables if they are not present + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param temporary should we use a temporary schema + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ + int + (*create_tables) (void *cls, + int temporary); + + + /** + * Start a transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn connection to use + * @return #GNUNET_OK on success + */ + int + (*start) (void *cls, + struct TALER_MINTDB_Session *db_conn); + + + /** + * Commit a transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn connection to use + * @return #GNUNET_OK on success + */ + int + (*commit) (void *cls, + struct TALER_MINTDB_Session *db_conn); + + + /** + * Abort/rollback a transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn connection to use + */ + void + (*rollback) (void *cls, + struct TALER_MINTDB_Session *db_conn); + + + /** + * Get the summary of a reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db the database connection handle + * @param reserve the reserve data. The public key of the reserve should be set + * in this structure; it is used to query the database. The balance + * and expiration are then filled accordingly. + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + */ + int + (*reserve_get) (void *cls, + struct TALER_MINTDB_Session *db, + struct Reserve *reserve); + + /* FIXME: add functions to add bank transfers to our DB + (and to test if we already did add one) (#3633/#3717) */ + + + /** + * Insert a incoming transaction into reserves. New reserves are also created + * through this function. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db the database connection handle + * @param reserve the reserve structure. The public key of the reserve should + * be set here. Upon successful execution of this function, the + * balance and expiration of the reserve will be updated. + * @param balance the amount that has to be added to the reserve + * @param expiry the new expiration time for the reserve + * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failures + */ + int + (*reserves_in_insert) (void *cls, + struct TALER_MINTDB_Session *db, + struct Reserve *reserve, + const struct TALER_Amount *balance, + const struct GNUNET_TIME_Absolute expiry); + + + /** + * Locate the response for a /withdraw request under the + * key of the hash of the blinded message. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ + int + (*get_collectable_blindcoin) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_HashCode *h_blind, + struct CollectableBlindcoin *collectable); + + + /** + * Store collectable bit coin under the corresponding + * hash of the blinded message. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param h_blind hash of the blinded message + * @param withdraw amount by which the reserve will be withdrawn with this + * transaction + * @param collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return #GNUNET_SYSERR on internal error + * #GNUNET_NO if the collectable was not found + * #GNUNET_YES on success + */ + int + (*insert_collectable_blindcoin) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_HashCode *h_blind, + struct TALER_Amount withdraw, + const struct CollectableBlindcoin *collectable); + + + /** + * Get all of the transaction history associated with the specified + * reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn connection to use + * @param reserve_pub public key of the reserve + * @return known transaction history (NULL if reserve is unknown) + */ + struct ReserveHistory * + (*get_reserve_history) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub); + + + /** + * Check if we have the specified deposit already in the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param deposit deposit to search for + * @return #GNUNET_YES if we know this operation, + * #GNUNET_NO if this deposit is unknown to us, + * #GNUNET_SYSERR on internal error + */ + int + (*have_deposit) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct Deposit *deposit); + + + /** + * Insert information about deposited coin into the + * database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn connection to the database + * @param deposit deposit information to store + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ + int + (*insert_deposit) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct Deposit *deposit); + + + /** + * Lookup refresh session data under the given public key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database handle to use + * @param refresh_session_pub public key to use for the lookup + * @param refresh_session[OUT] where to store the result + * @return #GNUNET_YES on success, + * #GNUNET_NO if not found, + * #GNUNET_SYSERR on DB failure + */ + int + (*get_refresh_session) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct RefreshSession *refresh_session); + + + /** + * Store new refresh session data under the given public key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database handle to use + * @param refresh_session_pub public key to use to locate the session + * @param refresh_session session data to store + * @return #GNUNET_YES on success, + * #GNUNET_SYSERR on DB failure + */ + int + (*create_refresh_session) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct RefreshSession *refresh_session); + + + + /** + * Store the given /refresh/melt request in the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param refresh_session session key of the melt operation + * @param oldcoin_index index of the coin to store + * @param melt coin melt operation details to store + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ + int + (*insert_refresh_melt) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + uint16_t oldcoin_index, + const struct RefreshMelt *melt); + + + /** + * Get information about melted coin details from the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param refresh_session session key of the melt operation + * @param oldcoin_index index of the coin to retrieve + * @param melt melt data to fill in + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ + int + (*get_refresh_melt) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + uint16_t oldcoin_index, + struct RefreshMelt *melt); + + + /** + * Store in the database which coin(s) we want to create + * in a given refresh operation. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ + int + (*insert_refresh_order) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); + + + /** + * Lookup in the database the @a newcoin_index coin that we want to + * create in the given refresh operation. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param session_pub refresh session key + * @param newcoin_index index of the coin to generate + * @param denom_pub denomination of the coin to create + * @return NULL on error (not found or internal error) + */ + struct GNUNET_CRYPTO_rsa_PublicKey * + (*get_refresh_order) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index); + + + /** + * Store information about the commitment of the + * given coin for the given refresh session in the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param refresh_session_pub refresh session this commitment belongs to + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to refreshed (new) coins + * @param commit_coin coin commitment to store + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on error + */ + int + (*insert_refresh_commit_coin) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + const struct RefreshCommitCoin *commit_coin); + + + /** + * Obtain information about the commitment of the + * given coin of the given refresh session from the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param refresh_session_pub refresh session the commitment belongs to + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to refreshed (new) coins + * @param commit_coin[OUT] coin commitment to return + * @return #GNUNET_OK on success + * #GNUNET_NO if not found + * #GNUNET_SYSERR on error + */ + int + (*get_refresh_commit_coin) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + struct RefreshCommitCoin *commit_coin); + + + /** + * Store the commitment to the given (encrypted) refresh link data + * for the given refresh session. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param refresh_session_pub public key of the refresh session this + * commitment belongs with + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to melted (old) coins + * @param commit_link link information to store + * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success + */ + int + (*insert_refresh_commit_link) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + const struct RefreshCommitLink *commit_link); + + /** + * Obtain the commited (encrypted) refresh link data + * for the given refresh session. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection to use + * @param refresh_session_pub public key of the refresh session this + * commitment belongs with + * @param i set index (1st dimension) + * @param j coin index (2nd dimension), corresponds to melted (old) coins + * @param cc[OUT] link information to return + * @return #GNUNET_SYSERR on internal error, + * #GNUNET_NO if commitment was not found + * #GNUNET_OK on success + */ + int + (*get_refresh_commit_link) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + struct RefreshCommitLink *cc); + + + /** + * Insert signature of a new coin generated during refresh into + * the database indexed by the refresh session and the index + * of the coin. This data is later used should an old coin + * be used to try to obtain the private keys during "/refresh/link". + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param session_pub refresh session + * @param newcoin_index coin index + * @param ev_sig coin signature + * @return #GNUNET_OK on success + */ + int + (*insert_refresh_collectable) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + uint16_t newcoin_index, + const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); + + + /** + * Obtain the link data of a coin, that is the encrypted link + * information, the denomination keys and the signatures. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param coin_pub public key to use to retrieve linkage data + * @return all known link data for the coin + */ + struct LinkDataList * + (*get_link) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + + + /** + * Obtain shared secret and transfer public key from the public key of + * the coin. This information and the link information returned by + * #TALER_db_get_link() enable the owner of an old coin to determine + * the private keys of the new coins after the melt. + * + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param coin_pub public key of the coin + * @param transfer_pub[OUT] public transfer key + * @param shared_secret_enc[OUT] set to shared secret + * @return #GNUNET_OK on success, + * #GNUNET_NO on failure (not found) + * #GNUNET_SYSERR on internal failure (database issue) + */ + int + (*get_transfer) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + struct TALER_EncryptedLinkSecret *shared_secret_enc); + + + /** + * Test if the given /lock request is known to us. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param lock lock operation + * @return #GNUNET_YES if known, + * #GNUENT_NO if not, + * #GNUNET_SYSERR on internal error + */ + int + (*have_lock) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct Lock *lock); + + + /** + * Store the given /lock request in the database. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param lock lock operation + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error + */ + int + (*insert_lock) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct Lock *lock); + + + /** + * Compile a list of all (historic) transactions performed + * with the given coin (/refresh/melt and /deposit operations). + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param db_conn database connection + * @param coin_pub coin to investigate + * @return list of transactions, NULL if coin is fresh + */ + struct TALER_MINT_DB_TransactionList * + (*get_coin_transactions) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + +}; + + +#endif /* _NEURO_MINT_DB_H */ diff --git a/src/util/Makefile.am b/src/util/Makefile.am index a15d42ad8..07c120c50 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -8,7 +8,8 @@ libtalerutil_la_SOURCES = \ amount.c \ crypto.c \ util.c \ - json.c + json.c \ + os_installation.c libtalerutil_la_LIBADD = \ -lgnunetutil \ diff --git a/src/util/os_installation.c b/src/util/os_installation.c new file mode 100644 index 000000000..82dc49180 --- /dev/null +++ b/src/util/os_installation.c @@ -0,0 +1,701 @@ +/* + This file is part of GNUnet. + Copyright (C) 2006-2014 Christian Grothoff (and other contributing authors) + + GNUnet 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. + + GNUnet 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 GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file os_installation.c + * @brief get paths used by the program; based heavily on the + * corresponding GNUnet file, just adapted for Taler. + * @author Milan + */ +#include "platform.h" +#include +#if DARWIN +#include +#include +#elif WINDOWS +#include +#endif + + +#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) + +#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename) + + +#if LINUX +/** + * Try to determine path by reading /proc/PID/exe + * + * @return NULL on error + */ +static char * +get_path_from_proc_maps () +{ + char fn[64]; + char line[1024]; + char dir[1024]; + FILE *f; + char *lgu; + + GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/maps", getpid ()); + if (NULL == (f = FOPEN (fn, "r"))) + return NULL; + while (NULL != fgets (line, sizeof (line), f)) + { + if ((1 == + SSCANF (line, "%*x-%*x %*c%*c%*c%*c %*x %*2x:%*2x %*u%*[ ]%1023s", dir)) && + (NULL != (lgu = strstr (dir, "libtalerutil")))) + { + lgu[0] = '\0'; + FCLOSE (f); + return GNUNET_strdup (dir); + } + } + FCLOSE (f); + return NULL; +} + + +/** + * Try to determine path by reading /proc/PID/exe + * + * @return NULL on error + */ +static char * +get_path_from_proc_exe () +{ + char fn[64]; + char lnk[1024]; + ssize_t size; + + GNUNET_snprintf (fn, sizeof (fn), "/proc/%u/exe", getpid ()); + size = readlink (fn, lnk, sizeof (lnk) - 1); + if (size <= 0) + { + LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "readlink", fn); + return NULL; + } + GNUNET_assert (size < sizeof (lnk)); + lnk[size] = '\0'; + while ((lnk[size] != '/') && (size > 0)) + size--; + /* test for being in lib/taler/libexec/ or lib/MULTIARCH/taler/libexec */ + if ( (size > strlen ("/taler/libexec/")) && + (0 == strcmp ("/taler/libexec/", + &lnk[size - strlen ("/taler/libexec/")])) ) + size -= strlen ("taler/libexec/"); + if ((size < 4) || (lnk[size - 4] != '/')) + { + /* not installed in "/bin/" -- binary path probably useless */ + return NULL; + } + lnk[size] = '\0'; + return GNUNET_strdup (lnk); +} +#endif + + +#if WINDOWS +static HINSTANCE dll_instance; + + +/** + * GNUNET_util_cl_init() in common_logging.c is preferred. + * This function is only for thread-local storage (not used in GNUnet) + * and hInstance saving. + */ +BOOL WINAPI +DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + dll_instance = hinstDLL; + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + + +/** + * Try to determine path with win32-specific function + * + * @return NULL on error + */ +static char * +get_path_from_module_filename () +{ + size_t pathlen = 512; + DWORD real_pathlen; + wchar_t *idx; + wchar_t *modulepath = NULL; + char *upath; + uint8_t *u8_string; + size_t u8_string_length; + + /* This braindead function won't tell us how much space it needs, so + * we start at 1024 and double the space up if it doesn't fit, until + * it fits, or we exceed the threshold. + */ + do + { + pathlen = pathlen * 2; + modulepath = GNUNET_realloc (modulepath, pathlen * sizeof (wchar_t)); + SetLastError (0); + real_pathlen = GetModuleFileNameW (dll_instance, modulepath, pathlen * sizeof (wchar_t)); + } while (real_pathlen >= pathlen && pathlen < 16*1024); + if (real_pathlen >= pathlen) + GNUNET_assert (0); + /* To be safe */ + modulepath[real_pathlen] = '\0'; + + idx = modulepath + real_pathlen; + while ((idx > modulepath) && (*idx != L'\\') && (*idx != L'/')) + idx--; + *idx = L'\0'; + + /* Now modulepath holds full path to the directory where libtalerutil is. + * This directory should look like /bin or . + */ + if (wcschr (modulepath, L'/') || wcschr (modulepath, L'\\')) + { + /* At least one directory component (i.e. we're not in a root directory) */ + wchar_t *dirname = idx; + while ((dirname > modulepath) && (*dirname != L'\\') && (*dirname != L'/')) + dirname--; + *dirname = L'\0'; + if (dirname > modulepath) + { + dirname++; + /* Now modulepath holds full path to the parent directory of the directory + * where libtalerutil is. + * dirname holds the name of the directory where libtalerutil is. + */ + if (wcsicmp (dirname, L"bin") == 0) + { + /* pass */ + } + else + { + /* Roll back our changes to modulepath */ + dirname--; + *dirname = L'/'; + } + } + } + + /* modulepath is TALER_PREFIX */ + u8_string = u16_to_u8 (modulepath, wcslen (modulepath), NULL, &u8_string_length); + if (NULL == u8_string) + GNUNET_assert (0); + + upath = GNUNET_malloc (u8_string_length + 1); + memcpy (upath, u8_string, u8_string_length); + upath[u8_string_length] = '\0'; + + free (u8_string); + GNUNET_free (modulepath); + + return upath; +} +#endif + + +#if DARWIN +/** + * Signature of the '_NSGetExecutablePath" function. + * + * @param buf where to write the path + * @param number of bytes available in 'buf' + * @return 0 on success, otherwise desired number of bytes is stored in 'bufsize' + */ +typedef int (*MyNSGetExecutablePathProto) (char *buf, size_t * bufsize); + + +/** + * Try to obtain the path of our executable using '_NSGetExecutablePath'. + * + * @return NULL on error + */ +static char * +get_path_from_NSGetExecutablePath () +{ + static char zero = '\0'; + char *path; + size_t len; + MyNSGetExecutablePathProto func; + + path = NULL; + if (NULL == (func = + (MyNSGetExecutablePathProto) dlsym (RTLD_DEFAULT, "_NSGetExecutablePath"))) + return NULL; + path = &zero; + len = 0; + /* get the path len, including the trailing \0 */ + (void) func (path, &len); + if (0 == len) + return NULL; + path = GNUNET_malloc (len); + if (0 != func (path, &len)) + { + GNUNET_free (path); + return NULL; + } + len = strlen (path); + while ((path[len] != '/') && (len > 0)) + len--; + path[len] = '\0'; + return path; +} + + +/** + * Try to obtain the path of our executable using '_dyld_image' API. + * + * @return NULL on error + */ +static char * +get_path_from_dyld_image () +{ + const char *path; + char *p; + char *s; + unsigned int i; + int c; + + c = _dyld_image_count (); + for (i = 0; i < c; i++) + { + if (((const void *) _dyld_get_image_header (i)) != (const void *)&_mh_dylib_header) + continue; + path = _dyld_get_image_name (i); + if ( (NULL == path) || (0 == strlen (path)) ) + continue; + p = GNUNET_strdup (path); + s = p + strlen (p); + while ((s > p) && ('/' != *s)) + s--; + s++; + *s = '\0'; + return p; + } + return NULL; +} +#endif + + +/** + * Return the actual path to a file found in the current + * PATH environment variable. + * + * @param binary the name of the file to find + * @return path to binary, NULL if not found + */ +static char * +get_path_from_PATH (const char *binary) +{ + char *path; + char *pos; + char *end; + char *buf; + const char *p; + + if (NULL == (p = getenv ("PATH"))) + return NULL; +#if WINDOWS + /* On W32 look in CWD first. */ + GNUNET_asprintf (&path, ".%c%s", PATH_SEPARATOR, p); +#else + path = GNUNET_strdup (p); /* because we write on it */ +#endif + buf = GNUNET_malloc (strlen (path) + strlen (binary) + 1 + 1); + pos = path; + while (NULL != (end = strchr (pos, PATH_SEPARATOR))) + { + *end = '\0'; + sprintf (buf, "%s/%s", pos, binary); + if (GNUNET_DISK_file_test (buf) == GNUNET_YES) + { + pos = GNUNET_strdup (pos); + GNUNET_free (buf); + GNUNET_free (path); + return pos; + } + pos = end + 1; + } + sprintf (buf, "%s/%s", pos, binary); + if (GNUNET_YES == GNUNET_DISK_file_test (buf)) + { + pos = GNUNET_strdup (pos); + GNUNET_free (buf); + GNUNET_free (path); + return pos; + } + GNUNET_free (buf); + GNUNET_free (path); + return NULL; +} + + +/** + * Try to obtain the installation path using the "TALER_PREFIX" environment + * variable. + * + * @return NULL on error (environment variable not set) + */ +static char * +get_path_from_TALER_PREFIX () +{ + const char *p; + + if (NULL != (p = getenv ("TALER_PREFIX"))) + return GNUNET_strdup (p); + return NULL; +} + + +/** + * @brief get the path to Taler bin/ or lib/, prefering the lib/ path + * @author Milan + * + * @return a pointer to the executable path, or NULL on error + */ +static char * +os_get_taler_path () +{ + char *ret; + + if (NULL != (ret = get_path_from_TALER_PREFIX ())) + return ret; +#if LINUX + if (NULL != (ret = get_path_from_proc_maps ())) + return ret; + /* try path *first*, before /proc/exe, as /proc/exe can be wrong */ + if (NULL != (ret = get_path_from_PATH ("taler-mint-httpd"))) + return ret; + if (NULL != (ret = get_path_from_proc_exe ())) + return ret; +#endif +#if WINDOWS + if (NULL != (ret = get_path_from_module_filename ())) + return ret; +#endif +#if DARWIN + if (NULL != (ret = get_path_from_dyld_image ())) + return ret; + if (NULL != (ret = get_path_from_NSGetExecutablePath ())) + return ret; +#endif + if (NULL != (ret = get_path_from_PATH ("taler-mint-httpd"))) + return ret; + /* other attempts here */ + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Could not determine installation path for %s. Set `%s' environment variable.\n"), + "Taler", "TALER_PREFIX"); + return NULL; +} + + +/** + * @brief get the path to current app's bin/ + * @author Milan + * + * @return a pointer to the executable path, or NULL on error + */ +static char * +os_get_exec_path () +{ + char *ret = NULL; + +#if LINUX + if (NULL != (ret = get_path_from_proc_exe ())) + return ret; +#endif +#if WINDOWS + if (NULL != (ret = get_path_from_module_filename ())) + return ret; +#endif +#if DARWIN + if (NULL != (ret = get_path_from_NSGetExecutablePath ())) + return ret; +#endif + /* other attempts here */ + return ret; +} + + +/** + * @brief get the path to a specific Taler installation directory or, + * with #TALER_OS_IPK_SELF_PREFIX, the current running apps installation directory + * @author Milan + * @return a pointer to the dir path (to be freed by the caller) + */ +char * +TALER_OS_installation_get_path (enum GNUNET_OS_InstallationPathKind dirkind) +{ + size_t n; + const char *dirname; + char *execpath = NULL; + char *tmp; + char *multiarch; + char *libdir; + int isbasedir; + + /* if wanted, try to get the current app's bin/ */ + if (dirkind == GNUNET_OS_IPK_SELF_PREFIX) + execpath = os_get_exec_path (); + + /* try to get Taler's bin/ or lib/, or if previous was unsuccessful some + * guess for the current app */ + if (NULL == execpath) + execpath = os_get_taler_path (); + + if (NULL == execpath) + return NULL; + + n = strlen (execpath); + if (0 == n) + { + /* should never happen, but better safe than sorry */ + GNUNET_free (execpath); + return NULL; + } + /* remove filename itself */ + while ((n > 1) && (DIR_SEPARATOR == execpath[n - 1])) + execpath[--n] = '\0'; + + isbasedir = 1; + if ((n > 6) && + ((0 == strcasecmp (&execpath[n - 6], "/lib32")) || + (0 == strcasecmp (&execpath[n - 6], "/lib64")))) + { + if ( (GNUNET_OS_IPK_LIBDIR != dirkind) && + (GNUNET_OS_IPK_LIBEXECDIR != dirkind) ) + { + /* strip '/lib32' or '/lib64' */ + execpath[n - 6] = '\0'; + n -= 6; + } + else + isbasedir = 0; + } + else if ((n > 4) && + ((0 == strcasecmp (&execpath[n - 4], "/bin")) || + (0 == strcasecmp (&execpath[n - 4], "/lib")))) + { + /* strip '/bin' or '/lib' */ + execpath[n - 4] = '\0'; + n -= 4; + } + multiarch = NULL; + if (NULL != (libdir = strstr (execpath, "/lib/"))) + { + /* test for multi-arch path of the form "PREFIX/lib/MULTIARCH/"; + here we need to re-add 'multiarch' to lib and libexec paths later! */ + multiarch = &libdir[5]; + if (NULL == strchr (multiarch, '/')) + libdir[0] = '\0'; /* Debian multiarch format, cut of from 'execpath' but preserve in multicarch */ + else + multiarch = NULL; /* maybe not, multiarch still has a '/', which is not OK */ + } + /* in case this was a directory named foo-bin, remove "foo-" */ + while ((n > 1) && (execpath[n - 1] == DIR_SEPARATOR)) + execpath[--n] = '\0'; + switch (dirkind) + { + case GNUNET_OS_IPK_PREFIX: + case GNUNET_OS_IPK_SELF_PREFIX: + dirname = DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_BINDIR: + dirname = DIR_SEPARATOR_STR "bin" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_LIBDIR: + if (isbasedir) + { + GNUNET_asprintf (&tmp, + "%s%s%s%s%s", + execpath, + DIR_SEPARATOR_STR "lib", + (NULL != multiarch) ? DIR_SEPARATOR_STR : "", + (NULL != multiarch) ? multiarch : "", + DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR); + if (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) + { + GNUNET_free (execpath); + return tmp; + } + GNUNET_free (tmp); + tmp = NULL; + if (4 == sizeof (void *)) + { + dirname = + DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + if (8 == sizeof (void *)) + { + dirname = + DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + + if ( (NULL != tmp) && + (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) + { + GNUNET_free (execpath); + return tmp; + } + GNUNET_free (tmp); + } + dirname = DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_DATADIR: + dirname = + DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_LOCALEDIR: + dirname = + DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "locale" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_ICONDIR: + dirname = + DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "icons" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_DOCDIR: + dirname = + DIR_SEPARATOR_STR "share" DIR_SEPARATOR_STR "doc" DIR_SEPARATOR_STR \ + "gnunet" DIR_SEPARATOR_STR; + break; + case GNUNET_OS_IPK_LIBEXECDIR: + if (isbasedir) + { + dirname = + DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR "libexec" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s%s%s", + execpath, + DIR_SEPARATOR_STR "lib" DIR_SEPARATOR_STR, + (NULL != multiarch) ? multiarch : "", + dirname); + if (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) + { + GNUNET_free (execpath); + return tmp; + } + GNUNET_free (tmp); + tmp = NULL; + if (4 == sizeof (void *)) + { + dirname = + DIR_SEPARATOR_STR "lib32" DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + if (8 == sizeof (void *)) + { + dirname = + DIR_SEPARATOR_STR "lib64" DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + } + if ( (NULL != tmp) && + (GNUNET_YES == + GNUNET_DISK_directory_test (tmp, GNUNET_YES)) ) + { + GNUNET_free (execpath); + return tmp; + } + + GNUNET_free (tmp); + } + dirname = + DIR_SEPARATOR_STR "taler" DIR_SEPARATOR_STR \ + "libexec" DIR_SEPARATOR_STR; + break; + default: + GNUNET_free (execpath); + return NULL; + } + GNUNET_asprintf (&tmp, + "%s%s", + execpath, + dirname); + GNUNET_free (execpath); + return tmp; +} + + +/** + * Given the name of a taler-helper, taler-service or taler-daemon + * binary, try to prefix it with the libexec/-directory to get the + * full path. + * + * @param progname name of the binary + * @return full path to the binary, if possible, otherwise copy of 'progname' + */ +char * +TALER_OS_get_libexec_binary_path (const char *progname) +{ + static char *cache; + char *libexecdir; + char *binary; + + if ( (DIR_SEPARATOR == progname[0]) || + (GNUNET_YES == GNUNET_STRINGS_path_is_absolute (progname, GNUNET_NO, NULL, NULL)) ) + return GNUNET_strdup (progname); + if (NULL != cache) + libexecdir = cache; + else + libexecdir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_LIBEXECDIR); + if (NULL == libexecdir) + return GNUNET_strdup (progname); + GNUNET_asprintf (&binary, + "%s%s", + libexecdir, + progname); + cache = libexecdir; + return binary; +} + + + +/* end of os_installation.c */ -- cgit v1.2.3 From 067d4891411f7add6256352e661aab9fb0b58266 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 21 Mar 2015 14:04:13 +0100 Subject: -fix FTBFS --- src/mint/taler-mint-dbinit.c | 34 ++++++++-------------------------- src/mint/taler-mint-httpd.c | 2 +- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/src/mint/taler-mint-dbinit.c b/src/mint/taler-mint-dbinit.c index 060eabc7b..8056b7df0 100644 --- a/src/mint/taler-mint-dbinit.c +++ b/src/mint/taler-mint-dbinit.c @@ -23,7 +23,7 @@ #include #include "taler_util.h" #include "taler_mintdb_plugin.h" - +#include "plugin.h" /** * Mint directory with the keys. @@ -35,12 +35,6 @@ static char *mint_base_dir; */ static struct GNUNET_CONFIGURATION_Handle *cfg; -/** - * Database connection handle. - */ -static PGconn *db_conn; - - /** * The main function of the database initialization tool. @@ -61,7 +55,6 @@ main (int argc, &GNUNET_GETOPT_set_filename, &mint_base_dir}, GNUNET_GETOPT_OPTION_END }; - char *db_connection_cfg_str; if (GNUNET_GETOPT_run ("taler-mint-dbinit", options, @@ -78,7 +71,6 @@ main (int argc, "Mint base directory not given.\n"); return 1; } - cfg = TALER_config_load (mint_base_dir); if (NULL == cfg) { @@ -87,32 +79,22 @@ main (int argc, return 1; } if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint", - "db", - &db_connection_cfg_str)) + TALER_MINT_plugin_load (cfg)) { fprintf (stderr, - "Configuration 'mint.db' not found.\n"); + "Failed to initialize database plugin.\n"); return 1; } - db_conn = PQconnectdb (db_connection_cfg_str); - if (CONNECTION_OK != PQstatus (db_conn)) - { - fprintf (stderr, - "Database connection failed: %s\n", - PQerrorMessage (db_conn)); - free (db_connection_cfg_str); - return 1; - } - free (db_connection_cfg_str); - - if (GNUNET_OK != TALER_MINT_DB_create_tables (GNUNET_NO)) + if (GNUNET_OK != + plugin->create_tables (plugin->cls, + GNUNET_NO)) { fprintf (stderr, "Failed to initialize database.\n"); + TALER_MINT_plugin_unload (); return 1; } + TALER_MINT_plugin_unload (); return 0; } diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 9adf26dfd..70d3b64f0 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -36,6 +36,7 @@ #include "taler-mint-httpd_refresh.h" #include "taler-mint-httpd_keystate.h" #include "taler_mintdb_plugin.h" +#include "plugin.h" /** @@ -229,7 +230,6 @@ mint_serve_process_config (const char *mint_directory) unsigned long long port; unsigned long long kappa; char *master_pub_str; - char *db_cfg; cfg = TALER_config_load (mint_directory); if (NULL == cfg) -- cgit v1.2.3 From f7025fd6303b754f601bccf0c01272cf35e0b991 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 21 Mar 2015 14:21:00 +0100 Subject: fix testcase FTBFS --- src/mint/plugin.c | 2 +- src/mint/plugin.h | 2 +- src/mint/plugin_mintdb_postgres.c | 10 +- src/mint/taler-mint-httpd.h | 1 + src/mint/test_mint_db.c | 189 +++++++++++++++++++++++++------------- src/mint/test_mint_deposits.c | 94 +++++-------------- 6 files changed, 157 insertions(+), 141 deletions(-) diff --git a/src/mint/plugin.c b/src/mint/plugin.c index 91cd3f406..67cabd815 100644 --- a/src/mint/plugin.c +++ b/src/mint/plugin.c @@ -41,7 +41,7 @@ static char *old_dlsearchpath; * @return #GNUNET_OK on success */ int -TALER_MINT_plugin_load (struct GNUNET_CONFIGURATION_Handle *cfg) +TALER_MINT_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg) { return GNUNET_SYSERR; } diff --git a/src/mint/plugin.h b/src/mint/plugin.h index 01b99ebc3..bb1f0ecbc 100644 --- a/src/mint/plugin.h +++ b/src/mint/plugin.h @@ -37,7 +37,7 @@ extern struct TALER_MINTDB_Plugin *plugin; * @return #GNUNET_OK on success */ int -TALER_MINT_plugin_load (struct GNUNET_CONFIGURATION_Handle *cfg); +TALER_MINT_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg); /** diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 8935fe039..078e6e1ba 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -148,14 +148,15 @@ postgres_drop_temporary (void *cls, /** * Create the necessary tables if they are not present * - * @param pc our overall context + * @param cls the `struct PostgresClosure` with the plugin-specific state * @param temporary should we use a temporary schema * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ static int -postgres_create_tables (struct PostgresClosure *pc, +postgres_create_tables (void *cls, int temporary) { + struct PostgresClosure *pc = cls; PGresult *result; PGconn *conn; @@ -168,8 +169,8 @@ postgres_create_tables (struct PostgresClosure *pc, GNUNET_break (0); return GNUNET_SYSERR; } - if ((GNUNET_YES == temporary) - && (GNUNET_SYSERR == set_temporary_schema (conn))) + if ( (GNUNET_YES == temporary) && + (GNUNET_SYSERR == set_temporary_schema (conn))) { PQfinish (conn); return GNUNET_SYSERR; @@ -287,6 +288,7 @@ postgres_create_tables (struct PostgresClosure *pc, ",wire TEXT NOT NULL" ")"); #undef SQLEXEC + PQfinish (conn); return GNUNET_OK; diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index a86b06e43..36d150bbc 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -23,6 +23,7 @@ #ifndef TALER_MINT_HTTPD_H #define TALER_MINT_HTTPD_H +#include /** * Cut-and-choose size for refreshing. diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index 2bb25aa6a..750303a03 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -13,15 +13,13 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file mint/test_mint_db.c * @brief test cases for DB interaction functions * @author Sree Harsha Totakura */ - #include "platform.h" -#include "mint_db.h" +#include "plugin.h" static int result; @@ -45,7 +43,7 @@ static int result; /** * Checks if the given reserve has the given amount of balance and expiry * - * @param db the database connection + * @param session the database connection * @param pub the public key of the reserve * @param value balance value * @param fraction balance fraction @@ -54,16 +52,21 @@ static int result; * @return #GNUNET_OK if the given reserve has the same balance and expiration * as the given parameters; #GNUNET_SYSERR if not */ -int -check_reserve (PGconn *db, +static int +check_reserve (struct TALER_MINTDB_Session *session, struct GNUNET_CRYPTO_EddsaPublicKey *pub, - uint32_t value, uint32_t fraction, const char *currency, + uint32_t value, + uint32_t fraction, + const char *currency, uint64_t expiry) { struct Reserve reserve; reserve.pub = pub; - FAILIF (GNUNET_OK != TALER_MINT_DB_reserve_get (db, &reserve)); + FAILIF (GNUNET_OK != + plugin->reserve_get (plugin->cls, + session, + &reserve)); FAILIF (value != reserve.balance.value); FAILIF (fraction != reserve.balance.fraction); FAILIF (0 != strcmp (currency, reserve.balance.currency)); @@ -81,7 +84,8 @@ struct DenomKeyPair struct GNUNET_CRYPTO_rsa_PublicKey *pub; }; -struct DenomKeyPair * + +static struct DenomKeyPair * create_denom_key_pair (unsigned int size) { struct DenomKeyPair *dkp; @@ -93,6 +97,7 @@ create_denom_key_pair (unsigned int size) return dkp; } + static void destroy_denon_key_pair (struct DenomKeyPair *dkp) { @@ -107,13 +112,15 @@ destroy_denon_key_pair (struct DenomKeyPair *dkp) * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration + * @param cfg configuration */ static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) { - PGconn *db; + struct TALER_MINTDB_Session *session; struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; struct Reserve reserve; struct GNUNET_TIME_Absolute expiry; @@ -139,23 +146,27 @@ run (void *cls, char *const *args, const char *cfgfile, \"address\": \"foobar\"}"; unsigned int cnt; - db = NULL; dkp = NULL; rh = NULL; wire = NULL; ZR_BLK (&cbc); ZR_BLK (&cbc2); - if (GNUNET_OK != TALER_MINT_DB_init ("postgres:///taler")) + if (GNUNET_OK != + TALER_MINT_plugin_load (cfg)) { result = 1; return; } - if (GNUNET_OK != TALER_MINT_DB_create_tables (GNUNET_YES)) + if (GNUNET_OK != + plugin->create_tables (plugin->cls, + GNUNET_YES)) { result = 2; goto drop; } - if (NULL == (db = TALER_MINT_DB_get_connection(GNUNET_YES))) + if (NULL == + (session = plugin->get_session (plugin->cls, + GNUNET_YES))) { result = 3; goto drop; @@ -168,60 +179,85 @@ run (void *cls, char *const *args, const char *cfgfile, expiry = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), GNUNET_TIME_UNIT_HOURS); result = 4; - FAILIF (GNUNET_OK != TALER_MINT_DB_reserves_in_insert (db, - &reserve, - &amount, - expiry)); - FAILIF (GNUNET_OK != check_reserve (db, - &reserve_pub, - amount.value, - amount.fraction, - amount.currency, - expiry.abs_value_us)); - FAILIF (GNUNET_OK != TALER_MINT_DB_reserves_in_insert (db, - &reserve, - &amount, - expiry)); - FAILIF (GNUNET_OK != check_reserve (db, - &reserve_pub, - ++amount.value, - ++amount.fraction, - amount.currency, - expiry.abs_value_us)); + FAILIF (GNUNET_OK != + plugin->reserves_in_insert (plugin->cls, + session, + &reserve, + &amount, + expiry)); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + amount.value, + amount.fraction, + amount.currency, + expiry.abs_value_us)); + FAILIF (GNUNET_OK != + plugin->reserves_in_insert (plugin->cls, + session, + &reserve, + &amount, + expiry)); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + ++amount.value, + ++amount.fraction, + amount.currency, + expiry.abs_value_us)); dkp = create_denom_key_pair (1024); RND_BLK(&h_blind); RND_BLK(&cbc.reserve_sig); cbc.denom_pub = dkp->pub; cbc.sig = GNUNET_CRYPTO_rsa_sign (dkp->priv, &h_blind, sizeof (h_blind)); - (void) memcpy (&cbc.reserve_pub, &reserve_pub, sizeof (reserve_pub)); + (void) memcpy (&cbc.reserve_pub, + &reserve_pub, + sizeof (reserve_pub)); amount.value--; amount.fraction--; - FAILIF (GNUNET_OK != TALER_MINT_DB_insert_collectable_blindcoin (db, - &h_blind, - amount, - &cbc)); - FAILIF (GNUNET_OK != check_reserve (db, - &reserve_pub, - amount.value, - amount.fraction, - amount.currency, - expiry.abs_value_us)); - FAILIF (GNUNET_YES != TALER_MINT_DB_get_collectable_blindcoin (db, - &h_blind, - &cbc2)); + FAILIF (GNUNET_OK != + plugin->insert_collectable_blindcoin (plugin->cls, + session, + &h_blind, + amount, + &cbc)); + FAILIF (GNUNET_OK != + check_reserve (session, + &reserve_pub, + amount.value, + amount.fraction, + amount.currency, + expiry.abs_value_us)); + FAILIF (GNUNET_YES != + plugin->get_collectable_blindcoin (plugin->cls, + session, + &h_blind, + &cbc2)); FAILIF (NULL == cbc2.denom_pub); - FAILIF (0 != memcmp (&cbc2.reserve_sig, &cbc.reserve_sig, sizeof (cbc2.reserve_sig))); - FAILIF (0 != memcmp (&cbc2.reserve_pub, &cbc.reserve_pub, sizeof (cbc2.reserve_pub))); - FAILIF (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&h_blind, cbc2.sig, dkp->pub)); - rh_head = rh = TALER_MINT_DB_get_reserve_history (db, &reserve_pub); + FAILIF (0 != memcmp (&cbc2.reserve_sig, + &cbc.reserve_sig, + sizeof (cbc2.reserve_sig))); + FAILIF (0 != memcmp (&cbc2.reserve_pub, + &cbc.reserve_pub, + sizeof (cbc2.reserve_pub))); + FAILIF (GNUNET_OK != + GNUNET_CRYPTO_rsa_verify (&h_blind, + cbc2.sig, + dkp->pub)); + rh = plugin->get_reserve_history (plugin->cls, + session, + &reserve_pub); FAILIF (NULL == rh); + rh_head = rh; for (cnt=0; NULL != rh_head; rh_head=rh_head->next, cnt++) { switch (rh_head->type) { case TALER_MINT_DB_RO_BANK_TO_MINT: bt = rh_head->details.bank; - FAILIF (0 != memcmp (&bt->reserve_pub, &reserve_pub, sizeof (reserve_pub))); + FAILIF (0 != memcmp (&bt->reserve_pub, + &reserve_pub, + sizeof (reserve_pub))); FAILIF (1 != bt->amount.value); FAILIF (1 != bt->amount.fraction); FAILIF (0 != strcmp (CURRENCY, bt->amount.currency)); @@ -251,17 +287,35 @@ run (void *cls, char *const *args, const char *cfgfile, deposit.transaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); deposit.amount = amount; - FAILIF (GNUNET_OK != TALER_MINT_DB_insert_deposit (db, &deposit)); - FAILIF (GNUNET_YES != TALER_MINT_DB_have_deposit (db, &deposit)); - (void) memcpy (&deposit2, &deposit, sizeof (deposit)); + FAILIF (GNUNET_OK != + plugin->insert_deposit (plugin->cls, + session, &deposit)); + FAILIF (GNUNET_YES != + plugin->have_deposit (plugin->cls, + session, + &deposit)); + (void) memcpy (&deposit2, + &deposit, + sizeof (deposit)); deposit2.transaction_id++; /* should fail if transaction id is different */ - FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); deposit2.transaction_id = deposit.transaction_id; RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */ - FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); - (void) memcpy (&deposit2.merchant_pub, &deposit.merchant_pub, sizeof (deposit.merchant_pub)); + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); + (void) memcpy (&deposit2.merchant_pub, + &deposit.merchant_pub, + sizeof (deposit.merchant_pub)); RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */ - FAILIF (GNUNET_NO != TALER_MINT_DB_have_deposit (db, &deposit2)); + FAILIF (GNUNET_NO != + plugin->have_deposit (plugin->cls, + session, + &deposit2)); result = 0; drop: @@ -270,8 +324,10 @@ run (void *cls, char *const *args, const char *cfgfile, if (NULL != rh) TALER_MINT_DB_free_reserve_history (rh); rh = NULL; - if (NULL != db) - GNUNET_break (GNUNET_OK == TALER_MINT_DB_drop_temporary (db)); + if (NULL != session) + GNUNET_break (GNUNET_OK == + plugin->drop_temporary (plugin->cls, + session)); if (NULL != dkp) destroy_denon_key_pair (dkp); if (NULL != cbc.sig) @@ -285,7 +341,8 @@ run (void *cls, char *const *args, const char *cfgfile, int -main (int argc, char *const argv[]) +main (int argc, + char *const argv[]) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c index 5ad8006e8..c829e6e10 100644 --- a/src/mint/test_mint_deposits.c +++ b/src/mint/test_mint_deposits.c @@ -13,17 +13,15 @@ You should have received a copy of the GNU General Public License along with TALER; see the file COPYING. If not, If not, see */ - /** * @file mint/test_mint_deposits.c * @brief testcase for mint deposits * @author Sree Harsha Totakura */ - #include "platform.h" #include #include -#include "mint_db.h" +#include "plugin.h" #include "db_pq.h" #include "taler-mint-httpd.h" @@ -43,11 +41,6 @@ } while (0) -/** - * DB connection handle - */ -static PGconn *conn; - /** * Should we not interact with a temporary table? */ @@ -59,64 +52,19 @@ static int persistent; static int result; -int -TALER_MINT_DB_init_deposits (PGconn *conn, int tmp) -{ - const char *tmp_str = (1 == tmp) ? "TEMPORARY" : ""; - char *sql; - PGresult *res; - int ret; - - res = NULL; - (void) GNUNET_asprintf (&sql, - "CREATE %1$s TABLE IF NOT EXISTS deposits (" - " coin_pub BYTEA NOT NULL PRIMARY KEY CHECK (length(coin_pub)=32)" - ",denom_pub BYTEA NOT NULL CHECK (length(denom_pub)=32)" - ",transaction_id INT8 NOT NULL" - ",amount_value INT4 NOT NULL" - ",amount_fraction INT4 NOT NULL" - ",amount_currency VARCHAR(4) NOT NULL" - ",merchant_pub BYTEA NOT NULL" - ",h_contract BYTEA NOT NULL CHECK (length(h_contract)=64)" - ",h_wire BYTEA NOT NULL CHECK (length(h_wire)=64)" - ",coin_sig BYTEA NOT NULL CHECK (length(coin_sig)=64)" - ",wire TEXT NOT NULL" - ")", - tmp_str); - res = PQexec (conn, sql); - GNUNET_free (sql); - if (PGRES_COMMAND_OK != PQresultStatus (res)) - { - break_db_err (res); - ret = GNUNET_SYSERR; - } - else - ret = GNUNET_OK; - PQclear (res); - return ret; -} - - -static void -do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) -{ - if (NULL != conn) - PQfinish (conn); - conn = NULL; -} - - /** * Main function that will be run by the scheduler. * * @param cls closure * @param args remaining command-line arguments * @param cfgfile name of the configuration file used (for saving, can be NULL!) - * @param config configuration + * @param cfg configuration */ static void -run (void *cls, char *const *args, const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *config) +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) { static const char wire[] = "{" "\"type\":\"SEPA\"," @@ -126,13 +74,16 @@ run (void *cls, char *const *args, const char *cfgfile, "}"; struct Deposit *deposit; uint64_t transaction_id; + struct TALER_MINTDB_Session *session; deposit = NULL; - GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, - &do_shutdown, NULL); - EXITIF (NULL == (conn = PQconnectdb(DB_URI))); - EXITIF (GNUNET_OK != TALER_MINT_DB_init_deposits (conn, !persistent)); - EXITIF (GNUNET_OK != TALER_MINT_DB_prepare (conn)); + EXITIF (GNUNET_OK != TALER_MINT_plugin_load (cfg)); + EXITIF (GNUNET_OK != + plugin->create_tables (plugin->cls, + ! persistent)); + session = plugin->get_session (plugin->cls, + ! persistent); + EXITIF (NULL == session); deposit = GNUNET_malloc (sizeof (struct Deposit) + sizeof (wire)); /* Makeup a random coin public key */ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, @@ -151,20 +102,25 @@ run (void *cls, char *const *args, const char *cfgfile, strcpy (deposit->amount.currency, MINT_CURRENCY); /* Copy wireformat */ deposit->wire = json_loads (wire, 0, NULL); - EXITIF (GNUNET_OK != TALER_MINT_DB_insert_deposit (conn, - deposit)); - EXITIF (GNUNET_OK != TALER_MINT_DB_have_deposit (conn, - deposit)); + EXITIF (GNUNET_OK != + plugin->insert_deposit (plugin->cls, + session, + deposit)); + EXITIF (GNUNET_OK != + plugin->have_deposit (plugin->cls, + session, + deposit)); result = GNUNET_OK; EXITIF_exit: GNUNET_free_non_null (deposit); - GNUNET_SCHEDULER_shutdown (); return; } -int main(int argc, char *const argv[]) +int +main (int argc, + char *const argv[]) { static const struct GNUNET_GETOPT_CommandLineOption options[] = { {'T', "persist", NULL, -- cgit v1.2.3 From 53876904c590aa9b1e7bd48395cb049f109adbd4 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 12:49:48 +0100 Subject: fill in plugin vtable --- src/mint/plugin_mintdb_postgres.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 078e6e1ba..c49ea1399 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -616,8 +616,8 @@ db_conn_destroy (void *cls) * @return the database connection, or NULL on error */ static struct TALER_MINTDB_Session * -postgres_get_connection (void *cls, - int temporary) +postgres_get_session (void *cls, + int temporary) { struct PostgresClosure *pc = cls; PGconn *db_conn; @@ -2293,7 +2293,35 @@ libtaler_plugin_mintdb_postgres_init (void *cls) } plugin = GNUNET_new (struct TALER_MINTDB_Plugin); plugin->cls = pg; - + plugin->get_session = &postgres_get_session; + plugin->drop_temporary = &postgres_drop_temporary; + plugin->create_tables = &postgres_create_tables; + plugin->start = &postgres_start; + plugin->commit = &postgres_commit; + plugin->rollback = &postgres_rollback; + plugin->reserve_get = &postgres_reserve_get; + plugin->reserves_in_insert = &postgres_reserves_in_insert; + plugin->get_collectable_blindcoin = &postgres_get_collectable_blindcoin; + plugin->insert_collectable_blindcoin = &postgres_insert_collectable_blindcoin; + plugin->get_reserve_history = &postgres_get_reserve_history; + plugin->have_deposit = &postgres_have_deposit; + plugin->insert_deposit = &postgres_insert_deposit; + plugin->get_refresh_session = &postgres_get_refresh_session; + plugin->create_refresh_session = &postgres_create_refresh_session; + plugin->insert_refresh_melt = &postgres_insert_refresh_melt; + plugin->get_refresh_melt = &postgres_get_refresh_melt; + plugin->insert_refresh_order = &postgres_insert_refresh_order; + plugin->get_refresh_order = &postgres_get_refresh_order; + plugin->insert_refresh_commit_coin = &postgres_insert_refresh_commit_coin; + plugin->get_refresh_commit_coin = &postgres_get_refresh_commit_coin; + plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link; + plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link; + plugin->insert_refresh_collectable = &postgres_insert_refresh_collectable; + plugin->get_link = &postgres_get_link; + plugin->get_transfer = &postgres_get_transfer; + // plugin->have_lock = &postgres_have_lock; + // plugin->insert_lock = &postgres_insert_lock; + plugin->get_coin_transactions = &postgres_get_coin_transactions; return plugin; } -- cgit v1.2.3 From 0d3ec509d7192e973123de1ab390826fff4df230 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 13:02:11 +0100 Subject: move free functions into plugin --- src/mint/Makefile.am | 2 ++ src/mint/plugin.c | 65 --------------------------------------- src/mint/plugin.h | 27 ---------------- src/mint/plugin_mintdb_postgres.c | 28 +++++++++++------ src/mint/taler-mint-httpd_db.c | 39 ++++++++++++++--------- src/mint/taler_mintdb_plugin.h | 40 ++++++++++++++++++++++-- 6 files changed, 82 insertions(+), 119 deletions(-) diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index c4f99af63..1eba7d61d 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -6,6 +6,8 @@ plugindir = $(libdir)/taler plugin_LTLIBRARIES = \ libtaler_plugin_mintdb_postgres.la +EXTRA_DIST = plugin_mintdb_common.c + libtaler_plugin_mintdb_postgres_la_SOURCES = \ plugin_mintdb_postgres.c libtaler_plugin_mintdb_postgres_la_LIBADD = \ diff --git a/src/mint/plugin.c b/src/mint/plugin.c index 67cabd815..4fb75f87a 100644 --- a/src/mint/plugin.c +++ b/src/mint/plugin.c @@ -115,69 +115,4 @@ plugin_fini () } -// FIXME: decide if we should keep these in each plugin, here -// or yet again somewhere else entirely (plugin_common.c?) - -/** - * Free memory associated with the given reserve history. - * - * @param rh history to free. - */ -void -TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh) -{ - struct BankTransfer *bt; - struct CollectableBlindcoin *cbc; - struct ReserveHistory *backref; - - while (NULL != rh) - { - switch(rh->type) - { - case TALER_MINT_DB_RO_BANK_TO_MINT: - bt = rh->details.bank; - if (NULL != bt->wire) - json_decref ((json_t *) bt->wire); /* FIXME: avoid cast? */ - GNUNET_free (bt); - break; - case TALER_MINT_DB_RO_WITHDRAW_COIN: - cbc = rh->details.withdraw; - GNUNET_CRYPTO_rsa_signature_free (cbc->sig); - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); - GNUNET_free (cbc); - break; - } - backref = rh; - rh = rh->next; - GNUNET_free (backref); - } -} - - -/** - * Free memory of the link data list. - * - * @param ldl link data list to release - */ -void -TALER_db_link_data_list_free (struct LinkDataList *ldl) -{ - GNUNET_break (0); // FIXME -} - - -/** - * Free linked list of transactions. - * - * @param list list to free - */ -void -TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list) -{ - // FIXME: check logic! - GNUNET_break (0); -} - - - /* end of plugin.c */ diff --git a/src/mint/plugin.h b/src/mint/plugin.h index bb1f0ecbc..0dfb866da 100644 --- a/src/mint/plugin.h +++ b/src/mint/plugin.h @@ -47,31 +47,4 @@ void TALER_MINT_plugin_unload (void); -/** - * Free memory associated with the given reserve history. - * - * @param rh history to free. - */ -void -TALER_MINT_DB_free_reserve_history (struct ReserveHistory *rh); - - -/** - * Free memory of the link data list. - * - * @param ldl link data list to release - */ -void -TALER_db_link_data_list_free (struct LinkDataList *ldl); - - -/** - * Free linked list of transactions. - * - * @param list list to free - */ -void -TALER_MINT_DB_free_coin_transaction_list (struct TALER_MINT_DB_TransactionList *list); - - #endif diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index c49ea1399..adc85251c 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -28,6 +28,7 @@ #include #include +#include "plugin_mintdb_common.c" #define TALER_TEMP_SCHEMA_NAME "taler_temporary" @@ -1313,7 +1314,8 @@ postgres_get_reserve_history (void *cls, PQclear (result); if (GNUNET_SYSERR == ret) { - TALER_MINT_DB_free_reserve_history (rh); + common_free_reserve_history (cls, + rh); rh = NULL; } return rh; @@ -2064,9 +2066,9 @@ postgres_insert_refresh_collectable (void *cls, * @return all known link data for the coin */ static struct LinkDataList * -postgres_get_link (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) +postgres_get_link_data_list (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) { // FIXME: check logic! struct LinkDataList *ldl; @@ -2116,7 +2118,8 @@ postgres_get_link (void *cls, { PQclear (result); GNUNET_break (0); - TALER_db_link_data_list_free (ldl); + common_free_link_data_list (cls, + ldl); return NULL; } if (ld_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) @@ -2125,7 +2128,8 @@ postgres_get_link (void *cls, GNUNET_free (pk_buf); GNUNET_free (sig_buf); GNUNET_free (ld_buf); - TALER_db_link_data_list_free (ldl); + common_free_link_data_list (cls, + ldl); return NULL; } // FIXME: use util API for this! @@ -2154,7 +2158,8 @@ postgres_get_link (void *cls, GNUNET_free (link_enc); GNUNET_break (0); PQclear (result); - TALER_db_link_data_list_free (ldl); + common_free_link_data_list (cls, + ldl); return NULL; } pos = GNUNET_new (struct LinkDataList); @@ -2171,8 +2176,8 @@ postgres_get_link (void *cls, /** * Obtain shared secret and transfer public key from the public key of * the coin. This information and the link information returned by - * #TALER_db_get_link() enable the owner of an old coin to determine - * the private keys of the new coins after the melt. + * #postgres_get_link_data_list() enable the owner of an old coin to + * determine the private keys of the new coins after the melt. * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection @@ -2304,6 +2309,7 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_collectable_blindcoin = &postgres_get_collectable_blindcoin; plugin->insert_collectable_blindcoin = &postgres_insert_collectable_blindcoin; plugin->get_reserve_history = &postgres_get_reserve_history; + plugin->free_reserve_history = &common_free_reserve_history; plugin->have_deposit = &postgres_have_deposit; plugin->insert_deposit = &postgres_insert_deposit; plugin->get_refresh_session = &postgres_get_refresh_session; @@ -2317,11 +2323,13 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link; plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link; plugin->insert_refresh_collectable = &postgres_insert_refresh_collectable; - plugin->get_link = &postgres_get_link; + plugin->get_link_data_list = &postgres_get_link_data_list; + plugin->free_link_data_list = &common_free_link_data_list; plugin->get_transfer = &postgres_get_transfer; // plugin->have_lock = &postgres_have_lock; // plugin->insert_lock = &postgres_insert_lock; plugin->get_coin_transactions = &postgres_get_coin_transactions; + plugin->free_coin_transaction_list = &common_free_coin_transaction_list; return plugin; } diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 292ef68fa..35c6dfb95 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -106,7 +106,8 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &deposit->amount)) { GNUNET_break (0); - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); return TALER_MINT_reply_internal_db_error (connection); } @@ -125,7 +126,8 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &fee_deposit)) ) { GNUNET_break (0); - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); return TALER_MINT_reply_internal_db_error (connection); } break; @@ -140,7 +142,8 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &fee_refresh)) ) { GNUNET_break (0); - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); return TALER_MINT_reply_internal_db_error (connection); } break; @@ -163,10 +166,12 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, session); ret = TALER_MINT_reply_deposit_insufficient_funds (connection, tl); - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); return ret; } - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); if (GNUNET_OK != plugin->insert_deposit (plugin->cls, @@ -228,7 +233,8 @@ TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, "error", "Reserve not found"); res = TALER_MINT_reply_withdraw_status_success (connection, rh); - TALER_MINT_DB_free_reserve_history (rh); + plugin->free_reserve_history (plugin->cls, + rh); return res; } @@ -414,10 +420,12 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, session); res = TALER_MINT_reply_withdraw_sign_insufficient_funds (connection, rh); - TALER_MINT_DB_free_reserve_history (rh); + plugin->free_reserve_history (plugin->cls, + rh); return res; } - TALER_MINT_DB_free_reserve_history (rh); + plugin->free_reserve_history (plugin->cls, + rh); /* Balance is good, sign the coin! */ sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, @@ -532,10 +540,12 @@ refresh_accept_melts (struct MHD_Connection *connection, coin_details->melt_amount, coin_residual)) ? GNUNET_NO : GNUNET_SYSERR; - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); return res; } - TALER_MINT_DB_free_coin_transaction_list (tl); + plugin->free_coin_transaction_list (plugin->cls, + tl); melt.coin = *coin_public_info; melt.coin_sig = coin_details->melt_sig; @@ -1242,9 +1252,9 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, } GNUNET_assert (GNUNET_OK == res); - ldl = plugin->get_link (plugin->cls, - session, - coin_pub); + ldl = plugin->get_link_data_list (plugin->cls, + session, + coin_pub); if (NULL == ldl) { return TALER_MINT_reply_json_pack (connection, @@ -1257,7 +1267,8 @@ TALER_MINT_db_execute_refresh_link (struct MHD_Connection *connection, &transfer_pub, &shared_secret_enc, ldl); - TALER_db_link_data_list_free (ldl); + plugin->free_link_data_list (plugin->cls, + ldl); return res; } diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index d330b817b..eabb00d9a 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -658,6 +658,17 @@ struct TALER_MINTDB_Plugin const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub); + /** + * Free memory associated with the given reserve history. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param rh history to free. + */ + void + (*free_reserve_history) (void *cls, + struct ReserveHistory *rh); + + /** * Check if we have the specified deposit already in the database. * @@ -922,9 +933,20 @@ struct TALER_MINTDB_Plugin * @return all known link data for the coin */ struct LinkDataList * - (*get_link) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + (*get_link_data_list) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + + + /** + * Free memory of the link data list. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param ldl link data list to release + */ + void + (*free_link_data_list) (void *cls, + struct LinkDataList *ldl); /** @@ -996,6 +1018,18 @@ struct TALER_MINTDB_Plugin struct TALER_MINTDB_Session *db_conn, const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + + /** + * Free linked list of transactions. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param list list to free + */ + void + (*free_coin_transaction_list) (void *cls, + struct TALER_MINT_DB_TransactionList *list); + + }; -- cgit v1.2.3 From 3a94a76aacd3e3e486e8df15257f8d0bdaa49619 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 13:02:49 +0100 Subject: move free functions into plugin --- src/mint/test_mint_db.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index 750303a03..e4d312927 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -322,7 +322,8 @@ run (void *cls, if (NULL != wire) json_decref (wire); if (NULL != rh) - TALER_MINT_DB_free_reserve_history (rh); + plugin->free_reserve_history (plugin->cls, + rh); rh = NULL; if (NULL != session) GNUNET_break (GNUNET_OK == -- cgit v1.2.3 From 81e234e7239f37bface096b8ecd36bce346210c1 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 14:21:16 +0100 Subject: store and retrieve arrays from database where arrays are the unit of transaction, to reduce number of DB interactions --- src/mint/plugin_mintdb_postgres.c | 139 +++++++++++------------ src/mint/taler-mint-httpd_db.c | 224 +++++++++++++++++++------------------- src/mint/taler-mint-httpd_db.h | 1 - src/mint/taler_mintdb_plugin.h | 90 +++++++-------- 4 files changed, 233 insertions(+), 221 deletions(-) diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index adc85251c..16b134350 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -1637,8 +1637,8 @@ postgres_get_refresh_melt (void *cls, * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create + * @param num_newcoins number of coins to generate, size of the @a denom_pubs array + * @param denom_pubs array denominations of the coins to create * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ @@ -1646,16 +1646,16 @@ static int postgres_insert_refresh_order (void *cls, struct TALER_MINTDB_Session *session, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) + uint16_t num_newcoins, + struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs) { - // FIXME: check logic - uint16_t newcoin_index_nbo = htons (newcoin_index); + // FIXME: check logic: was written for just one COIN! + uint16_t newcoin_index_nbo = htons (num_newcoins); char *buf; size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pub, + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (*denom_pubs, &buf); { @@ -1687,27 +1687,28 @@ postgres_insert_refresh_order (void *cls, /** - * Lookup in the database the @a newcoin_index coin that we want to + * Lookup in the database the coins that we want to * create in the given refresh operation. * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return NULL on error (not found or internal error) + * @param newcoin_index array of the @a denom_pubs array + * @param denom_pubs where to store the deomination keys + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error */ -static struct GNUNET_CRYPTO_rsa_PublicKey * +static int postgres_get_refresh_order (void *cls, struct TALER_MINTDB_Session *session, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index) + uint16_t num_newcoins, + struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs) { - // FIXME: check logic + // FIXME: check logic -- was written for just one coin! char *buf; size_t buf_size; - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; - uint16_t newcoin_index_nbo = htons (newcoin_index); + uint16_t newcoin_index_nbo = htons (num_newcoins); struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR(session_pub), @@ -1715,20 +1716,21 @@ postgres_get_refresh_order (void *cls, TALER_DB_QUERY_PARAM_END }; - PGresult *result = TALER_DB_exec_prepared (session->conn, "get_refresh_order", params); + PGresult *result = TALER_DB_exec_prepared (session->conn, + "get_refresh_order", params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { BREAK_DB_ERR (result); PQclear (result); - return NULL; + return GNUNET_SYSERR; } if (0 == PQntuples (result)) { PQclear (result); /* FIXME: may want to distinguish between different error cases! */ - return NULL; + return GNUNET_SYSERR; } GNUNET_assert (1 == PQntuples (result)); struct TALER_DB_ResultSpec rs[] = { @@ -1739,12 +1741,12 @@ postgres_get_refresh_order (void *cls, { PQclear (result); GNUNET_break (0); - return NULL; + return GNUNET_SYSERR; } PQclear (result); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + denom_pubs[0] = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); GNUNET_free (buf); - return denom_pub; + return GNUNET_OK; } @@ -1757,34 +1759,36 @@ postgres_get_refresh_order (void *cls, * @param session database connection to use * @param refresh_session_pub refresh session this commitment belongs to * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin coin commitment to store + * @param num_newcoins coin index size of the @a commit_coins array + * @param commit_coins array of coin commitments to store * @return #GNUNET_OK on success * #GNUNET_SYSERR on error */ static int -postgres_insert_refresh_commit_coin (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitCoin *commit_coin) +postgres_insert_refresh_commit_coins (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int num_newcoins, + const struct RefreshCommitCoin *commit_coins) { - // FIXME: check logic! + // FIXME: check logic! -- was written for single commit_coin! uint16_t cnc_index_nbo = htons (i); - uint16_t newcoin_index_nbo = htons (j); + uint16_t newcoin_index_nbo = htons (num_newcoins); struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), - TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->coin_ev, commit_coin->coin_ev_size), + TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coins->coin_ev, commit_coins->coin_ev_size), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coin->refresh_link->coin_priv_enc, - commit_coin->refresh_link->blinding_key_enc_size + + TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coins->refresh_link->coin_priv_enc, + commit_coins->refresh_link->blinding_key_enc_size + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)), TALER_DB_QUERY_PARAM_END }; - PGresult *result = TALER_DB_exec_prepared (session->conn, "insert_refresh_commit_coin", params); + PGresult *result = TALER_DB_exec_prepared (session->conn, + "insert_refresh_commit_coin", + params); if (PGRES_COMMAND_OK != PQresultStatus (result)) { @@ -1819,12 +1823,12 @@ postgres_insert_refresh_commit_coin (void *cls, * #GNUNET_SYSERR on error */ static int -postgres_get_refresh_commit_coin (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int cnc_index, - unsigned int newcoin_index, - struct RefreshCommitCoin *cc) +postgres_get_refresh_commit_coins (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int cnc_index, + unsigned int newcoin_index, + struct RefreshCommitCoin *cc) { // FIXME: check logic! uint16_t cnc_index_nbo = htons (cnc_index); @@ -1841,7 +1845,9 @@ postgres_get_refresh_commit_coin (void *cls, size_t rl_buf_size; struct TALER_RefreshLinkEncrypted *rl; - PGresult *result = TALER_DB_exec_prepared (session->conn, "get_refresh_commit_coin", params); + PGresult *result = TALER_DB_exec_prepared (session->conn, + "get_refresh_commit_coin", + params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { @@ -1897,12 +1903,12 @@ postgres_get_refresh_commit_coin (void *cls, * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success */ static int -postgres_insert_refresh_commit_link (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitLink *commit_link) +postgres_insert_refresh_commit_links (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + const struct RefreshCommitLink *commit_link) { // FIXME: check logic! uint16_t cnc_index_nbo = htons (i); @@ -1946,23 +1952,23 @@ postgres_insert_refresh_commit_link (void *cls, * @param refresh_session_pub public key of the refresh session this * commitment belongs with * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param cc[OUT] link information to return + * @param num_links size of the @a commit_link array + * @param links[OUT] array of link information to return * @return #GNUNET_SYSERR on internal error, * #GNUNET_NO if commitment was not found * #GNUNET_OK on success */ static int -postgres_get_refresh_commit_link (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int cnc_index, - unsigned int oldcoin_index, - struct RefreshCommitLink *cc) +postgres_get_refresh_commit_links (void *cls, + struct TALER_MINTDB_Session *session, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int num_links, + struct RefreshCommitLink *links) { - // FIXME: check logic! - uint16_t cnc_index_nbo = htons (cnc_index); - uint16_t oldcoin_index_nbo = htons (oldcoin_index); + // FIXME: check logic: was written for a single link! + uint16_t cnc_index_nbo = htons (i); + uint16_t oldcoin_index_nbo = htons (num_links); struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), @@ -1988,15 +1994,14 @@ postgres_get_refresh_commit_link (void *cls, } struct TALER_DB_ResultSpec rs[] = { - TALER_DB_RESULT_SPEC("transfer_pub", &cc->transfer_pub), - TALER_DB_RESULT_SPEC("link_secret_enc", &cc->shared_secret_enc), + TALER_DB_RESULT_SPEC("transfer_pub", &links->transfer_pub), + TALER_DB_RESULT_SPEC("link_secret_enc", &links->shared_secret_enc), TALER_DB_RESULT_SPEC_END }; if (GNUNET_YES != TALER_DB_extract_result (result, rs, 0)) { PQclear (result); - GNUNET_free (cc); return GNUNET_SYSERR; } @@ -2318,10 +2323,10 @@ libtaler_plugin_mintdb_postgres_init (void *cls) plugin->get_refresh_melt = &postgres_get_refresh_melt; plugin->insert_refresh_order = &postgres_insert_refresh_order; plugin->get_refresh_order = &postgres_get_refresh_order; - plugin->insert_refresh_commit_coin = &postgres_insert_refresh_commit_coin; - plugin->get_refresh_commit_coin = &postgres_get_refresh_commit_coin; - plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link; - plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link; + plugin->insert_refresh_commit_coins = &postgres_insert_refresh_commit_coins; + plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins; + plugin->insert_refresh_commit_links = &postgres_insert_refresh_commit_links; + plugin->get_refresh_commit_links = &postgres_get_refresh_commit_links; plugin->insert_refresh_collectable = &postgres_insert_refresh_collectable; plugin->get_link_data_list = &postgres_get_link_data_list; plugin->free_link_data_list = &common_free_link_data_list; diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 35c6dfb95..a7a603288 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -609,7 +609,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session; int res; unsigned int i; - unsigned int j; if (NULL == (session = plugin->get_session (plugin->cls, GNUNET_NO))) @@ -667,55 +666,46 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, TALER_MINT_key_state_release (key_state); /* store requested new denominations */ - for (i=0;iinsert_refresh_order (plugin->cls, + session, + refresh_session_pub, + num_new_denoms, + denom_pubs)) { - if (GNUNET_OK != - plugin->insert_refresh_order (plugin->cls, - session, - refresh_session_pub, - i, - denom_pubs[i])) - { - plugin->rollback (plugin->cls, - session); - return TALER_MINT_reply_internal_db_error (connection); - } + plugin->rollback (plugin->cls, + session); + return TALER_MINT_reply_internal_db_error (connection); } for (i = 0; i < kappa; i++) { - for (j = 0; j < num_new_denoms; j++) + if (GNUNET_OK != + plugin->insert_refresh_commit_coins (plugin->cls, + session, + refresh_session_pub, + i, + num_new_denoms, + commit_coin[i])) { - if (GNUNET_OK != - plugin->insert_refresh_commit_coin (plugin->cls, - session, - refresh_session_pub, - i, - j, - &commit_coin[i][j])) - { - plugin->rollback (plugin->cls, - session); - return TALER_MINT_reply_internal_db_error (connection); - } + plugin->rollback (plugin->cls, + session); + return TALER_MINT_reply_internal_db_error (connection); } } for (i = 0; i < kappa; i++) { - for (j = 0; j < coin_count; j++) + if (GNUNET_OK != + plugin->insert_refresh_commit_links (plugin->cls, + session, + refresh_session_pub, + i, + coin_count, + commit_link[i])) { - if (GNUNET_OK != - plugin->insert_refresh_commit_link (plugin->cls, - session, - refresh_session_pub, - i, - j, - &commit_link[i][j])) - { - plugin->rollback (plugin->cls, - session); - return TALER_MINT_reply_internal_db_error (connection); - } + plugin->rollback (plugin->cls, + session); + return TALER_MINT_reply_internal_db_error (connection); } } @@ -783,44 +773,48 @@ check_commitment (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EcdsaPrivateKey *transfer_privs, const struct RefreshMelt *melts, unsigned int num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs) + struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs) { unsigned int j; - int res; struct TALER_LinkSecret last_shared_secret; int secret_initialized = GNUNET_NO; struct GNUNET_CRYPTO_EcdhePublicKey coin_ecdhe; struct GNUNET_CRYPTO_EcdhePrivateKey transfer_ecdhe; + struct RefreshCommitLink *commit_links; + struct RefreshCommitCoin *commit_coins; + + commit_links = GNUNET_malloc (num_oldcoins * + sizeof (struct RefreshCommitLink)); + if (GNUNET_OK != + plugin->get_refresh_commit_links (plugin->cls, + session, + refresh_session, + off, + num_oldcoins, + commit_links)) + { + GNUNET_break (0); + GNUNET_free (commit_links); + return (MHD_YES == TALER_MINT_reply_internal_db_error (connection)) + ? GNUNET_NO : GNUNET_SYSERR; + } for (j = 0; j < num_oldcoins; j++) { - struct RefreshCommitLink commit_link; struct TALER_TransferSecret transfer_secret; struct TALER_LinkSecret shared_secret; struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check; - res = plugin->get_refresh_commit_link (plugin->cls, - session, - refresh_session, - off, - j, - &commit_link); - if (GNUNET_OK != res) - { - GNUNET_break (0); - return (MHD_YES == TALER_MINT_reply_internal_db_error (connection)) - ? GNUNET_NO : GNUNET_SYSERR; - } - GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_privs[j], &transfer_pub_check); if (0 != memcmp (&transfer_pub_check, - &commit_link.transfer_pub, + &commit_links[j].transfer_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n"); + GNUNET_free (commit_links); /* FIXME: return more specific error with original signature (#3712) */ return (MHD_YES == TALER_MINT_reply_refresh_reveal_missmatch (connection, @@ -843,17 +837,19 @@ check_commitment (struct MHD_Connection *connection, { GNUNET_break (0); GNUNET_CRYPTO_ecdhe_key_clear (&transfer_ecdhe); + GNUNET_free (commit_links); return (MHD_YES == TALER_MINT_reply_internal_error (connection, "ECDH error")) ? GNUNET_NO : GNUNET_SYSERR; } GNUNET_CRYPTO_ecdhe_key_clear (&transfer_ecdhe); if (GNUNET_OK != - TALER_transfer_decrypt (&commit_link.shared_secret_enc, + TALER_transfer_decrypt (&commit_links[j].shared_secret_enc, &transfer_secret, &shared_secret)) { GNUNET_break (0); + GNUNET_free (commit_links); return (MHD_YES == TALER_MINT_reply_internal_error (connection, "Decryption error")) @@ -871,6 +867,7 @@ check_commitment (struct MHD_Connection *connection, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "shared secrets do not match\n"); + GNUNET_free (commit_links); /* FIXME: return more specific error with original signature (#3712) */ return (MHD_YES == TALER_MINT_reply_refresh_reveal_missmatch (connection, @@ -881,36 +878,40 @@ check_commitment (struct MHD_Connection *connection, } } GNUNET_break (GNUNET_YES == secret_initialized); - + GNUNET_free (commit_links); /* Check that the commitments for all new coins were correct */ + commit_coins = GNUNET_malloc (num_newcoins * + sizeof (struct RefreshCommitCoin)); + + if (GNUNET_OK != + plugin->get_refresh_commit_coins (plugin->cls, + session, + refresh_session, + off, + num_newcoins, + commit_coins)) + { + GNUNET_break (0); + GNUNET_free (commit_coins); + return (MHD_YES == TALER_MINT_reply_internal_db_error (connection)) + ? GNUNET_NO : GNUNET_SYSERR; + } + for (j = 0; j < num_newcoins; j++) { - struct RefreshCommitCoin commit_coin; struct TALER_RefreshLinkDecrypted *link_data; struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; struct GNUNET_HashCode h_msg; char *buf; size_t buf_len; - res = plugin->get_refresh_commit_coin (plugin->cls, - session, - refresh_session, - off, - j, - &commit_coin); - if (GNUNET_OK != res) - { - GNUNET_break (0); - return (MHD_YES == TALER_MINT_reply_internal_db_error (connection)) - ? GNUNET_NO : GNUNET_SYSERR; - } - - link_data = TALER_refresh_decrypt (commit_coin.refresh_link, + link_data = TALER_refresh_decrypt (commit_coins[j].refresh_link, &last_shared_secret); if (NULL == link_data) { GNUNET_break (0); + GNUNET_free (commit_coins); return (MHD_YES == TALER_MINT_reply_internal_error (connection, "Decryption error")) ? GNUNET_NO : GNUNET_SYSERR; @@ -932,14 +933,15 @@ check_commitment (struct MHD_Connection *connection, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "blind failed\n"); + GNUNET_free (commit_coins); return (MHD_YES == TALER_MINT_reply_internal_error (connection, "Blinding error")) ? GNUNET_NO : GNUNET_SYSERR; } - if ( (buf_len != commit_coin.coin_ev_size) || + if ( (buf_len != commit_coins[j].coin_ev_size) || (0 != memcmp (buf, - commit_coin.coin_ev, + commit_coins[j].coin_ev, buf_len)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -947,6 +949,7 @@ check_commitment (struct MHD_Connection *connection, off, (int) j); /* FIXME: return more specific error with original signature (#3712) */ + GNUNET_free (commit_coins); return (MHD_YES == TALER_MINT_reply_refresh_reveal_missmatch (connection, off, @@ -956,6 +959,7 @@ check_commitment (struct MHD_Connection *connection, } GNUNET_free (buf); } + GNUNET_free (commit_coins); return GNUNET_OK; } @@ -970,8 +974,7 @@ check_commitment (struct MHD_Connection *connection, * @param refresh_session session to query * @param key_state key state to lookup denomination pubs * @param denom_pub denomination key for the coin to create - * @param noreveal_index which index should we use to obtain the - * envelope for the coin, based on cut-and-choose + * @param commit_coin the coin that was committed * @param coin_off number of the coin * @return NULL on error, otherwise signature over the coin */ @@ -981,25 +984,12 @@ refresh_mint_coin (struct MHD_Connection *connection, const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, struct MintKeyState *key_state, const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, - unsigned int noreveal_index, + const struct RefreshCommitCoin *commit_coin, unsigned int coin_off) { - struct RefreshCommitCoin commit_coin; struct TALER_MINT_DenomKeyIssuePriv *dki; struct GNUNET_CRYPTO_rsa_Signature *ev_sig; - int res; - res = plugin->get_refresh_commit_coin (plugin->cls, - session, - refresh_session, - noreveal_index, - coin_off, - &commit_coin); - if (GNUNET_OK != res) - { - GNUNET_break (0); - return NULL; - } dki = TALER_MINT_get_denom_key (key_state, denom_pub); if (NULL == dki) { @@ -1007,8 +997,8 @@ refresh_mint_coin (struct MHD_Connection *connection, return NULL; } ev_sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, - commit_coin.coin_ev, - commit_coin.coin_ev_size); + commit_coin->coin_ev, + commit_coin->coin_ev_size); if (NULL == ev_sig) { GNUNET_break (0); @@ -1057,6 +1047,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, struct RefreshMelt *melts; struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs; struct GNUNET_CRYPTO_rsa_Signature **ev_sigs; + struct RefreshCommitCoin *commit_coins; unsigned int i; unsigned int j; unsigned int off; @@ -1101,22 +1092,18 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, } denom_pubs = GNUNET_malloc (refresh_session.num_newcoins * sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *)); - for (j=0;jget_refresh_order (plugin->cls, + session, + refresh_session_pub, + refresh_session.num_newcoins, + denom_pubs)) { - denom_pubs[j] = plugin->get_refresh_order (plugin->cls, - session, - refresh_session_pub, - j); - if (NULL == denom_pubs[j]) - { - GNUNET_break (0); - for (i=0;iget_refresh_commit_coins (plugin->cls, + session, + refresh_session_pub, + refresh_session.noreveal_index, + refresh_session.num_newcoins, + commit_coins)) + { + GNUNET_break (0); + GNUNET_free (commit_coins); + for (j=0;jcommit (plugin->cls, diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index dbfecccd1..aefbfc424 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -126,7 +126,6 @@ struct MeltDetails * future) * @return MHD result code */ -// FIXME: see #3635. int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_HashCode *melt_hash, diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index eabb00d9a..bc5cd69a6 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -781,8 +781,8 @@ struct TALER_MINTDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param db_conn database connection * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create + * @param num_newcoins number of coins to generate, size of the @a denom_pubs array + * @param denom_pubs array denominations of the coins to create * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ @@ -790,48 +790,50 @@ struct TALER_MINTDB_Plugin (*insert_refresh_order) (void *cls, struct TALER_MINTDB_Session *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); + uint16_t num_newcoins, + struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs); /** - * Lookup in the database the @a newcoin_index coin that we want to + * Lookup in the database for the @a num_newcoins coins that we want to * create in the given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state * @param db_conn database connection * @param session_pub refresh session key - * @param newcoin_index index of the coin to generate - * @param denom_pub denomination of the coin to create - * @return NULL on error (not found or internal error) + * @param num_newcoins size of the @a denom_pubs array + * @param denom_pubs[OUT] where to write @a num_newcoins denomination keys + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on internal error */ - struct GNUNET_CRYPTO_rsa_PublicKey * + int (*get_refresh_order) (void *cls, struct TALER_MINTDB_Session *db_conn, const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, - uint16_t newcoin_index); + uint16_t num_newcoins, + struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs); /** - * Store information about the commitment of the - * given coin for the given refresh session in the database. + * Store information about the commitments of the given index @a i + * for the given refresh session in the database. * * @param cls the @e cls of this struct with the plugin-specific state * @param db_conn database connection to use * @param refresh_session_pub refresh session this commitment belongs to - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin coin commitment to store + * @param i set index (1st dimension), relating to kappa + * @param num_newcoins coin index size of the @a commit_coins array + * @param commit_coin array of coin commitments to store * @return #GNUNET_OK on success * #GNUNET_SYSERR on error */ int - (*insert_refresh_commit_coin) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitCoin *commit_coin); + (*insert_refresh_commit_coins) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int num_newcoins, + const struct RefreshCommitCoin *commit_coins); /** @@ -849,12 +851,12 @@ struct TALER_MINTDB_Plugin * #GNUNET_SYSERR on error */ int - (*get_refresh_commit_coin) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - struct RefreshCommitCoin *commit_coin); + (*get_refresh_commit_coins) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + struct RefreshCommitCoin *commit_coin); /** @@ -865,18 +867,18 @@ struct TALER_MINTDB_Plugin * @param db_conn database connection to use * @param refresh_session_pub public key of the refresh session this * commitment belongs with - * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param commit_link link information to store + * @param i set index (1st dimension), relating to kappa + * @param num_links size of the @a commit_link array + * @param commit_links array of link information to store * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success */ int - (*insert_refresh_commit_link) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - const struct RefreshCommitLink *commit_link); + (*insert_refresh_commit_links) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int num_links, + const struct RefreshCommitLink *commit_links); /** * Obtain the commited (encrypted) refresh link data @@ -887,19 +889,19 @@ struct TALER_MINTDB_Plugin * @param refresh_session_pub public key of the refresh session this * commitment belongs with * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to melted (old) coins - * @param cc[OUT] link information to return + * @param num_links size of the @links array to return + * @param links[OUT] array link information to return * @return #GNUNET_SYSERR on internal error, * #GNUNET_NO if commitment was not found * #GNUNET_OK on success */ int - (*get_refresh_commit_link) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - unsigned int i, - unsigned int j, - struct RefreshCommitLink *cc); + (*get_refresh_commit_links) (void *cls, + struct TALER_MINTDB_Session *db_conn, + const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + unsigned int i, + unsigned int j, + struct RefreshCommitLink *links); /** -- cgit v1.2.3 From b1133719bb712b1c90573f310aa97bd2f4d8bfc2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 14:24:52 +0100 Subject: forgot to add file earlier --- src/mint/plugin_mintdb_common.c | 89 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 src/mint/plugin_mintdb_common.c diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c new file mode 100644 index 000000000..34aefb872 --- /dev/null +++ b/src/mint/plugin_mintdb_common.c @@ -0,0 +1,89 @@ +/* + This file is part of TALER + Copyright (C) 2015 Christian Grothoff (and other contributing authors) + + 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, If not, see +*/ +/** + * @file mint/plugin_mintdb_common.c + * @brief Functions shared across plugins, this file is meant to be + * #include-d in each plugin. + * @author Christian Grothoff + */ + +/** + * Free memory associated with the given reserve history. + * + * @param cls the @e cls of this struct with the plugin-specific state (unused) + * @param rh history to free. + */ +static void +common_free_reserve_history (void *cls, + struct ReserveHistory *rh) +{ + struct BankTransfer *bt; + struct CollectableBlindcoin *cbc; + struct ReserveHistory *backref; + + while (NULL != rh) + { + switch(rh->type) + { + case TALER_MINT_DB_RO_BANK_TO_MINT: + bt = rh->details.bank; + if (NULL != bt->wire) + json_decref ((json_t *) bt->wire); /* FIXME: avoid cast? */ + GNUNET_free (bt); + break; + case TALER_MINT_DB_RO_WITHDRAW_COIN: + cbc = rh->details.withdraw; + GNUNET_CRYPTO_rsa_signature_free (cbc->sig); + GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); + GNUNET_free (cbc); + break; + } + backref = rh; + rh = rh->next; + GNUNET_free (backref); + } +} + + +/** + * Free memory of the link data list. + * + * @param cls the @e cls of this struct with the plugin-specific state (unused) + * @param ldl link data list to release + */ +static void +common_free_link_data_list (void *cls, + struct LinkDataList *ldl) +{ + GNUNET_break (0); // FIXME +} + + +/** + * Free linked list of transactions. + * + * @param cls the @e cls of this struct with the plugin-specific state (unused) + * @param list list to free + */ +static void +common_free_coin_transaction_list (void *cls, + struct TALER_MINT_DB_TransactionList *list) +{ + // FIXME: check logic! + GNUNET_break (0); +} + +/* end of plugin_mintdb_common.c */ -- cgit v1.2.3 From c2a42d5475daf23889c720734edbafc8c2ce4e4f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 14:58:40 +0100 Subject: this is actually OK --- src/mint/taler-mint-httpd_db.c | 3 --- src/util/crypto.c | 1 - 2 files changed, 4 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index a7a603288..d347126d9 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -919,9 +919,6 @@ check_commitment (struct MHD_Connection *connection, GNUNET_CRYPTO_ecdsa_key_get_public (&link_data->coin_priv, &coin_pub); - /* FIXME: we had envisioned a more complex scheme to derive - the message to sign for a blinded coin... - FIXME: we should have a function in util/ to do this! */ GNUNET_CRYPTO_hash (&coin_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &h_msg); diff --git a/src/util/crypto.c b/src/util/crypto.c index 5e75d674a..c7a00b9ab 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -308,7 +308,6 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) { struct GNUNET_HashCode c_hash; - /* FIXME: we had envisioned a more complex scheme... */ GNUNET_CRYPTO_hash (&coin_public_info->coin_pub, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), &c_hash); -- cgit v1.2.3 From 1277f8445d0497107c5bd41b35007480d6a4472a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 16:09:01 +0100 Subject: include fees in amounts being signed, check available balance on refresh --- src/include/taler_signatures.h | 44 +++++++-- src/mint/plugin_mintdb_postgres.c | 2 +- src/mint/taler-mint-httpd_db.c | 178 +++++++++++++++++++++------------- src/mint/taler-mint-httpd_db.h | 2 +- src/mint/taler-mint-httpd_deposit.c | 6 +- src/mint/taler-mint-httpd_refresh.c | 10 +- src/mint/taler-mint-httpd_responses.c | 14 +-- src/mint/taler_mintdb_plugin.h | 28 +++--- src/mint/test_mint_db.c | 2 +- src/mint/test_mint_deposits.c | 8 +- 10 files changed, 183 insertions(+), 111 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index b91639321..4566764d0 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -131,6 +131,15 @@ struct TALER_WithdrawRequest */ struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + /** + * Value of the coin being minted (matching the denomination key) + * plus the transaction fee. We include this in what is being + * signed so that we can verify a reserve's remaining total balance + * without needing to access the respective denomination key + * information each time. + */ + struct TALER_AmountNBO amount_with_fee; + /** * Hash of the denomination public key for the coin that is withdrawn. */ @@ -171,9 +180,11 @@ struct TALER_DepositRequest uint64_t transaction_id GNUNET_PACKED; /** - * Amount to be deposited. + * Amount to be deposited, including fee. */ - struct TALER_AmountNBO amount; + struct TALER_AmountNBO amount_with_fee; + /* FIXME: we should probably also include the value of + the depositing fee here as well! */ /** * The coin's public key. @@ -211,9 +222,12 @@ struct TALER_DepositConfirmation uint64_t transaction_id GNUNET_PACKED; /** - * Amount to be deposited. + * Amount to be deposited, including fee. */ - struct TALER_AmountNBO amount; + struct TALER_AmountNBO amount_with_fee; + + /* FIXME: we should probably also include the value of + the depositing fee here as well! */ /** * The coin's public key. @@ -245,11 +259,17 @@ struct RefreshMeltCoinSignature struct GNUNET_HashCode melt_hash; /** - * How much of the value of the coin should be melted? - * This amount includes the fees, so the final amount contributed - * to the melt is this value minus the fee for melting the coin. + * How much of the value of the coin should be melted? This amount + * includes the fees, so the final amount contributed to the melt is + * this value minus the fee for melting the coin. We include the + * fee in what is being signed so that we can verify a reserve's + * remaining total balance without needing to access the respective + * denomination key information each time. */ - struct TALER_AmountNBO amount; + struct TALER_AmountNBO amount_with_fee; + + /* FIXME: we should probably also include the value of + the melting fee here as well! */ /** * The coin's public key. @@ -282,9 +302,13 @@ struct RefreshMeltSessionSignature /** * What is the total value of the coins created during the - * refresh, excluding fees? + * refresh, including melting fee! */ - struct TALER_AmountNBO amount; + struct TALER_AmountNBO amount_with_fee; + + /* FIXME: we should probably also include the value of + the melting fee here as well! */ + }; diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 16b134350..1d7a965cf 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -1401,7 +1401,7 @@ postgres_insert_deposit (void *cls, &denom_sig_enc); json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); TALER_amount_hton (&amount_nbo, - &deposit->amount); + &deposit->amount_with_fee); struct TALER_DB_QueryParam params[]= { TALER_DB_QUERY_PARAM_PTR (&deposit->coin.coin_pub), TALER_DB_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index d347126d9..b3e239c89 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -34,6 +34,64 @@ #include "plugin.h" +/** + * Calculate the total value of all transactions performed. + * Stores @a off plus the cost of all transactions in @a tl + * in @a ret. + * + * @param pos transaction list to process + * @param off offset to use as the starting value + * @param ret where the resulting total is to be stored + * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors + */ +static int +calculate_transaction_list_totals (struct TALER_MINT_DB_TransactionList *tl, + const struct TALER_Amount *off, + struct TALER_Amount *ret) +{ + struct TALER_Amount spent = *off; + struct TALER_MINT_DB_TransactionList *pos; + + for (pos = tl; NULL != pos; pos = pos->next) + { + switch (pos->type) + { + case TALER_MINT_DB_TT_DEPOSIT: + if (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &pos->details.deposit->amount_with_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + break; + case TALER_MINT_DB_TT_REFRESH_MELT: + if (GNUNET_OK != + TALER_amount_add (&spent, + &spent, + &pos->details.melt->amount_with_fee)) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + break; + case TALER_MINT_DB_TT_LOCK: + /* should check if lock is still active, + and if it is for THIS operation; if + lock is inactive, delete it; if lock + is for THIS operation, ignore it; + if lock is for another operation, + count it! */ + GNUNET_assert (0); // FIXME: not implemented! (#3625) + return GNUNET_SYSERR; + } + } + *ret = spent; + return GNUNET_OK; +} + + /** * Execute a deposit. The validity of the coin and signature * have already been checked. The database must now check that @@ -50,11 +108,9 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, { struct TALER_MINTDB_Session *session; struct TALER_MINT_DB_TransactionList *tl; - struct TALER_MINT_DB_TransactionList *pos; struct TALER_Amount spent; struct TALER_Amount value; struct TALER_Amount fee_deposit; - struct TALER_Amount fee_refresh; struct MintKeyState *mks; struct TALER_MINT_DenomKeyIssuePriv *dki; int ret; @@ -76,7 +132,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &deposit->h_contract, deposit->transaction_id, &deposit->merchant_pub, - &deposit->amount); + &deposit->amount_with_fee); } mks = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (mks, @@ -85,8 +141,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &dki->issue.value); TALER_amount_ntoh (&fee_deposit, &dki->issue.fee_deposit); - TALER_amount_ntoh (&fee_refresh, - &dki->issue.fee_refresh); TALER_MINT_key_state_release (mks); if (GNUNET_OK != @@ -96,69 +150,29 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, GNUNET_break (0); return TALER_MINT_reply_internal_db_error (connection); } + /* fee for THIS transaction */ + spent = deposit->amount_with_fee; + if (TALER_amount_cmp (&fee_deposit, + &spent) < 0) + { + return (MHD_YES == + TALER_MINT_reply_external_error (connection, + "deposited amount smaller than depositing fee")) + ? GNUNET_NO : GNUNET_SYSERR; + } + /* add cost of all previous transactions */ tl = plugin->get_coin_transactions (plugin->cls, session, &deposit->coin.coin_pub); - spent = fee_deposit; /* fee for THIS transaction */ if (GNUNET_OK != - TALER_amount_add (&spent, - &spent, - &deposit->amount)) + calculate_transaction_list_totals (tl, + &spent, + &spent)) { - GNUNET_break (0); plugin->free_coin_transaction_list (plugin->cls, tl); return TALER_MINT_reply_internal_db_error (connection); } - - for (pos = tl; NULL != pos; pos = pos->next) - { - switch (pos->type) - { - case TALER_MINT_DB_TT_DEPOSIT: - if ( (GNUNET_OK != - TALER_amount_add (&spent, - &spent, - &pos->details.deposit->amount)) || - (GNUNET_OK != - TALER_amount_add (&spent, - &spent, - &fee_deposit)) ) - { - GNUNET_break (0); - plugin->free_coin_transaction_list (plugin->cls, - tl); - return TALER_MINT_reply_internal_db_error (connection); - } - break; - case TALER_MINT_DB_TT_REFRESH_MELT: - if ( (GNUNET_OK != - TALER_amount_add (&spent, - &spent, - &pos->details.melt->amount)) || - (GNUNET_OK != - TALER_amount_add (&spent, - &spent, - &fee_refresh)) ) - { - GNUNET_break (0); - plugin->free_coin_transaction_list (plugin->cls, - tl); - return TALER_MINT_reply_internal_db_error (connection); - } - break; - case TALER_MINT_DB_TT_LOCK: - /* should check if lock is still active, - and if it is for THIS operation; if - lock is inactive, delete it; if lock - is for THIS operation, ignore it; - if lock is for another operation, - count it! */ - GNUNET_assert (0); // FIXME: not implemented! (#3625) - break; - } - } - if (0 < TALER_amount_cmp (&spent, &value)) { @@ -197,7 +211,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, &deposit->h_contract, deposit->transaction_id, &deposit->merchant_pub, - &deposit->amount); + &deposit->amount_with_fee); } @@ -501,8 +515,11 @@ refresh_accept_melts (struct MHD_Connection *connection, { struct TALER_MINT_DenomKeyIssue *dki; struct TALER_MINT_DB_TransactionList *tl; + struct TALER_Amount fee_deposit; + struct TALER_Amount fee_refresh; struct TALER_Amount coin_value; struct TALER_Amount coin_residual; + struct TALER_Amount spent; struct RefreshMelt melt; int res; @@ -518,26 +535,51 @@ refresh_accept_melts (struct MHD_Connection *connection, "denom not found")) ? GNUNET_NO : GNUNET_SYSERR; + TALER_amount_ntoh (&fee_deposit, + &dki->fee_deposit); + TALER_amount_ntoh (&fee_refresh, + &dki->fee_refresh); TALER_amount_ntoh (&coin_value, &dki->value); + /* fee for THIS transaction; the melt amount includes the fee! */ + spent = coin_details->melt_amount_with_fee; + if (TALER_amount_cmp (&fee_refresh, + &spent) < 0) + { + return (MHD_YES == + TALER_MINT_reply_external_error (connection, + "melt amount smaller than melting fee")) + ? GNUNET_NO : GNUNET_SYSERR; + } + /* add historic transaction costs of this coin */ tl = plugin->get_coin_transactions (plugin->cls, session, &coin_public_info->coin_pub); - /* FIXME: #3636: compute how much value is left with this coin and - compare to `expected_value`! (subtract from "coin_value") */ - coin_residual = coin_value; + if (GNUNET_OK != + calculate_transaction_list_totals (tl, + &spent, + &spent)) + { + GNUNET_break (0); + plugin->free_coin_transaction_list (plugin->cls, + tl); + return TALER_MINT_reply_internal_db_error (connection); + } /* Refuse to refresh when the coin does not have enough money left to * pay the refreshing fees of the coin. */ - - if (TALER_amount_cmp (&coin_residual, - &coin_details->melt_amount) < 0) + if (TALER_amount_cmp (&coin_value, + &spent) < 0) { + GNUNET_assert (GNUNET_OK == + TALER_amount_subtract (&coin_residual, + &spent, + &coin_details->melt_amount_with_fee)); res = (MHD_YES == TALER_MINT_reply_refresh_melt_insufficient_funds (connection, &coin_public_info->coin_pub, coin_value, tl, - coin_details->melt_amount, + coin_details->melt_amount_with_fee, coin_residual)) ? GNUNET_NO : GNUNET_SYSERR; plugin->free_coin_transaction_list (plugin->cls, @@ -550,7 +592,7 @@ refresh_accept_melts (struct MHD_Connection *connection, melt.coin = *coin_public_info; melt.coin_sig = coin_details->melt_sig; melt.melt_hash = *melt_hash; - melt.amount = coin_details->melt_amount; + melt.amount_with_fee = coin_details->melt_amount_with_fee; if (GNUNET_OK != plugin->insert_refresh_melt (plugin->cls, session, diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index aefbfc424..52e86f898 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -95,7 +95,7 @@ struct MeltDetails * This amount includes the fees, so the final amount contributed * to the melt is this value minus the fee for melting the coin. */ - struct TALER_Amount melt_amount; + struct TALER_Amount melt_amount_with_fee; }; diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index e411e0d8e..647cd8242 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -65,8 +65,8 @@ verify_and_execute_deposit (struct MHD_Connection *connection, dr.h_contract = deposit->h_contract; dr.h_wire = deposit->h_wire; dr.transaction_id = GNUNET_htonll (deposit->transaction_id); - TALER_amount_hton (&dr.amount, - &deposit->amount); + TALER_amount_hton (&dr.amount_with_fee, + &deposit->amount_with_fee); dr.coin_pub = deposit->coin.coin_pub; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_WALLET_DEPOSIT, @@ -167,7 +167,7 @@ parse_and_handle_deposit_request (struct MHD_Connection *connection, GNUNET_free (wire_enc); deposit.wire = wire; - deposit.amount = *amount; + deposit.amount_with_fee = *amount; res = verify_and_execute_deposit (connection, &deposit); TALER_MINT_release_parsed_data (spec); diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index d4979288d..602fc67f6 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -109,8 +109,8 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); body.melt_hash = melt_hash; - TALER_amount_hton (&body.amount, - &coin_melt_details->melt_amount); + TALER_amount_hton (&body.amount_with_fee, + &coin_melt_details->melt_amount_with_fee); if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, &body.purpose, @@ -252,7 +252,7 @@ get_coin_public_info (struct MHD_Connection *connection, ? GNUNET_NO : GNUNET_SYSERR; } r_melt_detail->melt_sig = melt_sig; - r_melt_detail->melt_amount = amount; + r_melt_detail->melt_amount_with_fee = amount; TALER_MINT_release_parsed_data (spec); return GNUNET_OK; } @@ -288,8 +288,8 @@ verify_coin_public_info (struct MHD_Connection *connection, body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); body.melt_hash = *melt_hash; - TALER_amount_hton (&body.amount, - &r_melt_detail->melt_amount); + TALER_amount_hton (&body.amount_with_fee, + &r_melt_detail->melt_amount_with_fee); body.coin_pub = r_public_info->coin_pub; if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN, diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c index a4b442152..681b2b922 100644 --- a/src/mint/taler-mint-httpd_responses.c +++ b/src/mint/taler-mint-httpd_responses.c @@ -299,7 +299,7 @@ TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, dc.h_contract = *h_contract; dc.h_wire = *h_wire; dc.transaction_id = GNUNET_htonll (transaction_id); - TALER_amount_hton (&dc.amount, + TALER_amount_hton (&dc.amount_with_fee, amount); dc.coin_pub = *coin_pub; dc.merchant = *merchant; @@ -341,14 +341,14 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) const struct Deposit *deposit = pos->details.deposit; type = "deposit"; - value = deposit->amount; + value = deposit->amount_with_fee; dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); dr.h_contract = deposit->h_contract; dr.h_wire = deposit->h_wire; dr.transaction_id = GNUNET_htonll (deposit->transaction_id); - TALER_amount_hton (&dr.amount, - &deposit->amount); + TALER_amount_hton (&dr.amount_with_fee, + &deposit->amount_with_fee); dr.coin_pub = deposit->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&dr.purpose, &deposit->csig); @@ -360,12 +360,12 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) const struct RefreshMelt *melt = pos->details.melt; type = "melt"; - value = melt->amount; + value = melt->amount_with_fee; ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); ms.melt_hash = melt->melt_hash; - TALER_amount_hton (&ms.amount, - &melt->amount); + TALER_amount_hton (&ms.amount_with_fee, + &melt->amount_with_fee); ms.coin_pub = melt->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, &melt->coin_sig); diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index bc5cd69a6..83e373340 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -14,13 +14,13 @@ TALER; see the file COPYING. If not, If not, see */ /** - * @file mint/mint_db.h + * @file mint/taler_mintdb_plugin.h * @brief Low-level (statement-level) database access for the mint * @author Florian Dold * @author Christian Grothoff */ -#ifndef MINT_DB_H -#define MINT_DB_H +#ifndef TALER_MINTDB_PLUGIN_H +#define TALER_MINTDB_PLUGIN_H #include #include "taler_util.h" @@ -87,6 +87,9 @@ struct CollectableBlindcoin /** * Denomination key (which coin was generated). + * FIXME: we should probably instead have the + * AMOUNT *including* fee in what is being signed + * as well! */ struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; @@ -217,10 +220,10 @@ struct Deposit uint64_t transaction_id; /** - * Fraction of the coin's remaining value to be deposited. - * The coin is identified by @e coin_pub. + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. */ - struct TALER_Amount amount; + struct TALER_Amount amount_with_fee; }; @@ -296,11 +299,14 @@ struct RefreshMelt struct GNUNET_HashCode melt_hash; /** - * How much value is being melted? - * This amount includes the fees, so the final amount contributed - * to the melt is this value minus the fee for melting the coin. + * How much value is being melted? This amount includes the fees, + * so the final amount contributed to the melt is this value minus + * the fee for melting the coin. We include the fee in what is + * being signed so that we can verify a reserve's remaining total + * balance without needing to access the respective denomination key + * information each time. */ - struct TALER_Amount amount; + struct TALER_Amount amount_with_fee; }; @@ -397,7 +403,7 @@ struct Lock const struct GNUNET_CRYPTO_EcdsaSignature coin_sig; /** - * How much value is being melted? + * How much value is being locked? */ struct TALER_Amount amount; diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index e4d312927..c80be70c3 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -286,7 +286,7 @@ run (void *cls, deposit.wire = wire; deposit.transaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); - deposit.amount = amount; + deposit.amount_with_fee = amount; FAILIF (GNUNET_OK != plugin->insert_deposit (plugin->cls, session, &deposit)); diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c index c829e6e10..4107c1aee 100644 --- a/src/mint/test_mint_deposits.c +++ b/src/mint/test_mint_deposits.c @@ -94,12 +94,12 @@ run (void *cls, UINT64_MAX); deposit->transaction_id = GNUNET_htonll (transaction_id); /* Random amount */ - deposit->amount.value = + deposit->amount_with_fee.value = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); - deposit->amount.fraction = + deposit->amount_with_fee.fraction = htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); - GNUNET_assert (strlen (MINT_CURRENCY) < sizeof (deposit->amount.currency)); - strcpy (deposit->amount.currency, MINT_CURRENCY); + GNUNET_assert (strlen (MINT_CURRENCY) < sizeof (deposit->amount_with_fee.currency)); + strcpy (deposit->amount_with_fee.currency, MINT_CURRENCY); /* Copy wireformat */ deposit->wire = json_loads (wire, 0, NULL); EXITIF (GNUNET_OK != -- cgit v1.2.3 From 4ec78fba4e4cc4d1c3cc6e44da42dc43bef20ef7 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 16:10:16 +0100 Subject: this was finished --- src/mint/taler-mint-httpd_db.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index b3e239c89..cd418fa58 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -17,11 +17,6 @@ * @file taler-mint-httpd_db.c * @brief High-level (transactional-layer) database operations for the mint. * @author Christian Grothoff - * - * TODO: - * - actually abstract DB implementation (i.e. via plugin logic) - * (this file should remain largely unchanged with the exception - * of the PQ-specific DB handle types) */ #include "platform.h" #include -- cgit v1.2.3 From 3fe9a76098607656d95b6d9843dc77bc948a46a2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 16:17:22 +0100 Subject: move refresh fee check to earlier --- src/mint/taler-mint-httpd_db.c | 18 ++---------------- src/mint/taler-mint-httpd_refresh.c | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index cd418fa58..f99a98598 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -510,8 +510,6 @@ refresh_accept_melts (struct MHD_Connection *connection, { struct TALER_MINT_DenomKeyIssue *dki; struct TALER_MINT_DB_TransactionList *tl; - struct TALER_Amount fee_deposit; - struct TALER_Amount fee_refresh; struct TALER_Amount coin_value; struct TALER_Amount coin_residual; struct TALER_Amount spent; @@ -530,22 +528,10 @@ refresh_accept_melts (struct MHD_Connection *connection, "denom not found")) ? GNUNET_NO : GNUNET_SYSERR; - TALER_amount_ntoh (&fee_deposit, - &dki->fee_deposit); - TALER_amount_ntoh (&fee_refresh, - &dki->fee_refresh); TALER_amount_ntoh (&coin_value, &dki->value); /* fee for THIS transaction; the melt amount includes the fee! */ spent = coin_details->melt_amount_with_fee; - if (TALER_amount_cmp (&fee_refresh, - &spent) < 0) - { - return (MHD_YES == - TALER_MINT_reply_external_error (connection, - "melt amount smaller than melting fee")) - ? GNUNET_NO : GNUNET_SYSERR; - } /* add historic transaction costs of this coin */ tl = plugin->get_coin_transactions (plugin->cls, session, @@ -560,8 +546,8 @@ refresh_accept_melts (struct MHD_Connection *connection, tl); return TALER_MINT_reply_internal_db_error (connection); } - /* Refuse to refresh when the coin does not have enough money left to - * pay the refreshing fees of the coin. */ + /* Refuse to refresh when the coin's value is insufficient + for the cost of all transactions. */ if (TALER_amount_cmp (&coin_value, &spent) < 0) { diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 602fc67f6..ed229bf65 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -282,9 +282,8 @@ verify_coin_public_info (struct MHD_Connection *connection, struct RefreshMeltCoinSignature body; struct MintKeyState *key_state; struct TALER_MINT_DenomKeyIssuePriv *dki; + struct TALER_Amount fee_refresh; - /* FIXME: include amount of coin value to be melted here (#3636!) and - in what we return!? */ body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); body.melt_hash = *melt_hash; @@ -308,8 +307,6 @@ verify_coin_public_info (struct MHD_Connection *connection, key_state = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (key_state, r_public_info->denom_pub); - /* FIXME: need to check if denomination key is still - valid for issuing! (#3634) */ if (NULL == dki) { TALER_MINT_key_state_release (key_state); @@ -317,6 +314,20 @@ verify_coin_public_info (struct MHD_Connection *connection, return TALER_MINT_reply_arg_invalid (connection, "denom_pub"); } + /* FIXME: need to check if denomination key is still + valid for issuing! (#3634) */ + TALER_amount_ntoh (&fee_refresh, + &dki->issue.fee_refresh); + if (TALER_amount_cmp (&fee_refresh, + &r_melt_detail->melt_amount_with_fee) < 0) + { + TALER_MINT_key_state_release (key_state); + return (MHD_YES == + TALER_MINT_reply_external_error (connection, + "melt amount smaller than melting fee")) + ? GNUNET_NO : GNUNET_SYSERR; + } + TALER_MINT_key_state_release (key_state); return GNUNET_OK; } -- cgit v1.2.3 From 41478aea76fdcbd11f0fb2225aae4b184053ab5f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 16:20:03 +0100 Subject: move deposit fee check to earlier --- src/mint/taler-mint-httpd_db.c | 13 ++----------- src/mint/taler-mint-httpd_deposit.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index f99a98598..43b226e64 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -105,7 +105,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, struct TALER_MINT_DB_TransactionList *tl; struct TALER_Amount spent; struct TALER_Amount value; - struct TALER_Amount fee_deposit; struct MintKeyState *mks; struct TALER_MINT_DenomKeyIssuePriv *dki; int ret; @@ -134,8 +133,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, deposit->coin.denom_pub); TALER_amount_ntoh (&value, &dki->issue.value); - TALER_amount_ntoh (&fee_deposit, - &dki->issue.fee_deposit); TALER_MINT_key_state_release (mks); if (GNUNET_OK != @@ -147,14 +144,6 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, } /* fee for THIS transaction */ spent = deposit->amount_with_fee; - if (TALER_amount_cmp (&fee_deposit, - &spent) < 0) - { - return (MHD_YES == - TALER_MINT_reply_external_error (connection, - "deposited amount smaller than depositing fee")) - ? GNUNET_NO : GNUNET_SYSERR; - } /* add cost of all previous transactions */ tl = plugin->get_coin_transactions (plugin->cls, session, @@ -168,6 +157,8 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, tl); return TALER_MINT_reply_internal_db_error (connection); } + /* Check that cost of all transactions is smaller than + the value of the coin. */ if (0 < TALER_amount_cmp (&spent, &value)) { diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index 647cd8242..810d1c328 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -59,6 +59,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, struct MintKeyState *key_state; struct TALER_DepositRequest dr; struct TALER_MINT_DenomKeyIssuePriv *dki; + struct TALER_Amount fee_deposit; dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_DEPOSIT); dr.purpose.size = htonl (sizeof (struct TALER_DepositRequest)); @@ -97,6 +98,17 @@ verify_and_execute_deposit (struct MHD_Connection *connection, TALER_MINT_key_state_release (key_state); return TALER_MINT_reply_coin_invalid (connection); } + TALER_amount_ntoh (&fee_deposit, + &dki->issue.fee_deposit); + if (TALER_amount_cmp (&fee_deposit, + &deposit->amount_with_fee) < 0) + { + TALER_MINT_key_state_release (key_state); + return (MHD_YES == + TALER_MINT_reply_external_error (connection, + "deposited amount smaller than depositing fee")) + ? GNUNET_NO : GNUNET_SYSERR; + } TALER_MINT_key_state_release (key_state); return TALER_MINT_db_execute_deposit (connection, -- cgit v1.2.3 From 884fff1297f7da95eed0646a510c3561ba2bfc15 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 16:58:15 +0100 Subject: fix #3637 --- src/mint/taler-mint-httpd_refresh.c | 47 ++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index ed229bf65..3253bad8d 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -84,11 +84,12 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct TALER_Amount melt; struct TALER_Amount value; struct TALER_Amount fee_withdraw; + struct TALER_Amount fee_melt; struct TALER_Amount total_melt; /* check that signature from the session public key is ok */ hash_context = GNUNET_CRYPTO_hash_context_start (); - /* FIXME: also hash session public key here!? */ + /* FIXME: also hash session public key here!? #3708 */ for (i = 0; i < num_new_denoms; i++) { buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i], @@ -104,7 +105,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); GNUNET_CRYPTO_hash_context_finish (hash_context, &melt_hash); - // FIXME: what about the `commit_hash`? + /* FIXME: what about the `commit_hash`? #3708 */ body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); @@ -125,9 +126,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, "error", "invalid signature (verification)"); } - - // FIXME: badness, use proper way to set to zero... - memset (&total_cost, 0, sizeof (struct TALER_Amount)); + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (MINT_CURRENCY, + &total_cost)); key_state = TALER_MINT_key_state_acquire (); for (i=0;ivalue); TALER_amount_ntoh (&fee_withdraw, &dki->fee_withdraw); - // FIXME: #3637 if ( (GNUNET_OK != TALER_amount_add (&cost, &value, @@ -147,31 +147,46 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, &cost, &total_cost)) ) { - // FIXME... + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_internal_error (connection, + "cost calculation failure"); } } - // FIXME: badness, use proper way to set to zero... - memset (&total_melt, 0, sizeof (struct TALER_Amount)); + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (MINT_CURRENCY, + &total_melt)); for (i=0;iissue; + TALER_amount_ntoh (&fee_melt, + &dki->fee_refresh); + if (GNUNET_OK != + TALER_amount_subtract (&melt, + &coin_melt_details->melt_amount_with_fee, + &fee_melt)) + { + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_external_error (connection, + "Melt contribution below melting fee"); + } if (GNUNET_OK != TALER_amount_add (&total_melt, &melt, &total_melt)) { - // FIXME ... + TALER_MINT_key_state_release (key_state); + return TALER_MINT_reply_internal_error (connection, + "balance calculation failure"); } } TALER_MINT_key_state_release (key_state); if (0 != TALER_amount_cmp (&total_cost, - &total_melt) ) + &total_melt)) { /* We require total value of coins being melted and total value of coins being generated to match! */ -- cgit v1.2.3 From 1d7bb2d091fc6a87cb2b5b2f2e584ed6c3cc56db Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 17:10:45 +0100 Subject: fix #3636, and add amount parsing functionality to spec-parser --- src/mint/taler-mint-httpd_parsing.c | 37 +++++++++++++++++++++++++++---------- src/mint/taler-mint-httpd_parsing.h | 16 +++++++++++++++- src/mint/taler-mint-httpd_refresh.c | 6 +----- 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/src/mint/taler-mint-httpd_parsing.c b/src/mint/taler-mint-httpd_parsing.c index b8bc043ec..dedf4af9a 100644 --- a/src/mint/taler-mint-httpd_parsing.c +++ b/src/mint/taler-mint-httpd_parsing.c @@ -680,6 +680,16 @@ GNUNET_MINT_parse_navigate_json (struct MHD_Connection *connection, break; } + case JNAV_RET_AMOUNT: + { + struct TALER_Amount *where = va_arg (argp, void *); + + ret = TALER_MINT_parse_amount_json (connection, + (json_t *) root, + where); + break; + } + default: GNUNET_break (0); ret = (MHD_YES == @@ -721,6 +731,8 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, ret = GNUNET_YES; for (i=0; NULL != spec[i].field_name; i++) { + if (GNUNET_YES != ret) + break; switch (spec[i].command) { case JNAV_FIELD: @@ -730,8 +742,6 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, GNUNET_break (0); return GNUNET_SYSERR; case JNAV_RET_DATA: - if (GNUNET_YES != ret) - break; ret = GNUNET_MINT_parse_navigate_json (connection, root, JNAV_FIELD, @@ -741,8 +751,6 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, spec[i].destination_size_in); break; case JNAV_RET_DATA_VAR: - if (GNUNET_YES != ret) - break; ptr = NULL; ret = GNUNET_MINT_parse_navigate_json (connection, root, @@ -754,8 +762,6 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, spec[i].destination = ptr; break; case JNAV_RET_TYPED_JSON: - if (GNUNET_YES != ret) - break; ptr = NULL; ret = GNUNET_MINT_parse_navigate_json (connection, root, @@ -767,8 +773,6 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, *((void**)spec[i].destination) = ptr; break; case JNAV_RET_RSA_PUBLIC_KEY: - if (GNUNET_YES != ret) - break; ptr = NULL; ret = GNUNET_MINT_parse_navigate_json (connection, root, @@ -779,8 +783,6 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, spec[i].destination = ptr; break; case JNAV_RET_RSA_SIGNATURE: - if (GNUNET_YES != ret) - break; ptr = NULL; ret = GNUNET_MINT_parse_navigate_json (connection, root, @@ -790,6 +792,16 @@ TALER_MINT_parse_json_data (struct MHD_Connection *connection, &ptr); spec[i].destination = ptr; break; + case JNAV_RET_AMOUNT: + GNUNET_assert (sizeof (struct TALER_Amount) == + spec[i].destination_size_in); + ret = GNUNET_MINT_parse_navigate_json (connection, + root, + JNAV_FIELD, + spec[i].field_name, + JNAV_RET_AMOUNT, + &spec[i].destination); + break; } } if (GNUNET_YES != ret) @@ -854,6 +866,11 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec) *(void**) spec[i].destination = NULL; } break; + case JNAV_RET_AMOUNT: + memset (spec[i].destination, + 0, + sizeof (struct TALER_Amount)); + break; } } } diff --git a/src/mint/taler-mint-httpd_parsing.h b/src/mint/taler-mint-httpd_parsing.h index 94e2927d8..7a322d4d7 100644 --- a/src/mint/taler-mint-httpd_parsing.h +++ b/src/mint/taler-mint-httpd_parsing.h @@ -120,7 +120,13 @@ enum TALER_MINT_JsonNavigationCommand * Return a `struct GNUNET_CRYPTO_rsa_Signature` which was * encoded as variable-size base32crockford encoded data. */ - JNAV_RET_RSA_SIGNATURE + JNAV_RET_RSA_SIGNATURE, + + /** + * Return a `struct TALER_Amount` which was + * encoded within its own json object. + */ + JNAV_RET_AMOUNT }; @@ -270,6 +276,14 @@ TALER_MINT_release_parsed_data (struct GNUNET_MINT_ParseFieldSpec *spec); */ #define TALER_MINT_PARSE_RSA_SIGNATURE(field,ptrsig) { field, ptrsig, 0, 0, JNAV_RET_RSA_SIGNATURE, 0 } +/** + * Generate line in parser specification for an amount. + * + * @param field name of the field + * @param amount a `struct TALER_Amount *` to initialize + */ +#define TALER_MINT_PARSE_AMOUNT(field,amount) { field, amount, sizeof(*amount), 0, JNAV_RET_AMOUNT, 0 } + /** * Generate line in parser specification indicating the end of the spec. */ diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 3253bad8d..1fafd9481 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -237,19 +237,15 @@ get_coin_public_info (struct MHD_Connection *connection, TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig), TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk), TALER_MINT_PARSE_FIXED ("confirm_sig", &melt_sig), - /* FIXME: #3636! */ + TALER_MINT_PARSE_AMOUNT ("value_with_fee", &amount), TALER_MINT_PARSE_END }; - memset (&amount, 0, sizeof (amount)); // FIXME: #3636! ret = TALER_MINT_parse_json_data (connection, coin_info, spec); if (GNUNET_OK != ret) return ret; - /* FIXME: include amount of coin value to be melted here (#3636!) and - in what we return!? */ - /* check mint signature on the coin */ r_public_info->denom_sig = sig; r_public_info->denom_pub = pk; -- cgit v1.2.3 From 6c1081f1b50770d18df998915d8d74be383ad1bf Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 22 Mar 2015 17:14:47 +0100 Subject: fix #3642 --- src/mint/taler-mint-httpd_refresh.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 1fafd9481..d6bf3c428 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -493,6 +493,28 @@ handle_refresh_melt_json (struct MHD_Connection *connection, GNUNET_free (denom_pubs); return (GNUNET_NO == res) ? MHD_YES : MHD_NO; } + /* Check that the client does not try to melt the same coin twice + into the same session! */ + for (j=0;j Date: Sun, 22 Mar 2015 22:14:30 +0100 Subject: fix #3638 --- src/include/taler_crypto_lib.h | 304 +++++++++++++++++++++++++++++++++- src/include/taler_mint_service.h | 22 +-- src/include/taler_signatures.h | 31 ++-- src/lib/mint_api.c | 64 ++++--- src/mint/key_io.c | 10 +- src/mint/key_io.h | 6 +- src/mint/plugin_mintdb_common.c | 4 +- src/mint/plugin_mintdb_postgres.c | 129 ++++++++------- src/mint/taler-mint-httpd_db.c | 132 ++++++++------- src/mint/taler-mint-httpd_db.h | 22 +-- src/mint/taler-mint-httpd_deposit.c | 6 +- src/mint/taler-mint-httpd_keystate.c | 18 +- src/mint/taler-mint-httpd_keystate.h | 4 +- src/mint/taler-mint-httpd_refresh.c | 101 +++++------ src/mint/taler-mint-httpd_responses.c | 43 ++--- src/mint/taler-mint-httpd_responses.h | 10 +- src/mint/taler-mint-httpd_withdraw.c | 27 +-- src/mint/taler-mint-keycheck.c | 10 +- src/mint/taler-mint-keyup.c | 51 +++--- src/mint/taler_mintdb_plugin.h | 180 ++++++++++---------- src/mint/test_mint_common.c | 25 +-- src/mint/test_mint_db.c | 47 +++--- src/util/crypto.c | 15 +- 23 files changed, 794 insertions(+), 467 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index db663612c..0c0ad8865 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -27,6 +27,296 @@ /* ****************** Coin crypto primitives ************* */ +/** + * Type of public keys for Taler reserves. + */ +struct TALER_ReservePublicKey +{ + /** + * Taler uses EdDSA for reserves. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * Type of private keys for Taler reserves. + */ +struct TALER_ReservePrivateKey +{ + /** + * Taler uses EdDSA for reserves. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * Type of signatures used with Taler reserves. + */ +struct TALER_ReserveSignature +{ + /** + * Taler uses EdDSA for reserves. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * Type of public keys to for merchant authorizations. + * Merchants can issue refunds using the corresponding + * private key. + */ +struct TALER_MerchantPublicKey +{ + /** + * Taler uses EdDSA for merchants. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * Type of private keys for merchant authorizations. + * Merchants can issue refunds using the corresponding + * private key. + */ +struct TALER_MerchantPrivateKey +{ + /** + * Taler uses EdDSA for merchants. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * Type of public keys used by clients to sign + * messages during a melting session. + */ +struct TALER_SessionPublicKey +{ + /** + * Taler uses EdDSA for melting session keys. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * Type of public keys used by clients to sign + * messages during a melting session. + */ +struct TALER_SessionPrivateKey +{ + /** + * Taler uses EdDSA for melting session keys. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * Type of transfer public keys used during refresh + * operations. + */ +struct TALER_TransferPublicKey +{ + /** + * Taler uses ECDSA for transfer keys. + * FIXME: should this not be ECDHE? + */ + struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub; +}; + + +/** + * Type of transfer public keys used during refresh + * operations. + */ +struct TALER_TransferPrivateKey +{ + /** + * Taler uses ECDSA for melting session keys. + * FIXME: should this not be ECDHE? + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey ecdsa_priv; +}; + + +/** + * Type of signatures used by clients to sign + * messages during a melting session. + */ +struct TALER_SessionSignature +{ + /** + * Taler uses EdDSA for melting session keys. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * Type of online public keys used by the mint to sign + * messages. + */ +struct TALER_MintPublicKey +{ + /** + * Taler uses EdDSA for online mint message signing. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * Type of online public keys used by the mint to + * sign messages. + */ +struct TALER_MintPrivateKey +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * Type of signatures used by the mint to sign messages online. + */ +struct TALER_MintSignature +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * Type of the offline master public key used by the mint. + */ +struct TALER_MasterPublicKey +{ + /** + * Taler uses EdDSA for the long-term offline master key. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * Type of the offline master public keys used by the mint. + */ +struct TALER_MasterPrivateKey +{ + /** + * Taler uses EdDSA for the long-term offline master key. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * Type of signatures by the offline master public key used by the mint. + */ +struct TALER_MasterSignature +{ + /** + * Taler uses EdDSA for the long-term offline master key. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + + +/** + * Type of public keys for Taler coins. + */ +struct TALER_CoinSpendPublicKey +{ + /** + * Taler uses ECDSA for coins. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey ecdsa_pub; +}; + + +/** + * Type of private keys for Taler coins. + */ +struct TALER_CoinSpendPrivateKey +{ + /** + * Taler uses ECDSA for coins. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey ecdsa_priv; +}; + + +/** + * Type of signatures made with Taler coins. + */ +struct TALER_CoinSpendSignature +{ + /** + * Taler uses ECDSA for coins. + */ + struct GNUNET_CRYPTO_EcdsaSignature ecdsa_signature; +}; + + +/** + * Type of blinding keys for Taler. + */ +struct TALER_DenominationBlindingKey +{ + /** + * Taler uses RSA for blinding. + */ + struct GNUNET_CRYPTO_rsa_BlindingKey *rsa_blinding_key; +}; + + +/** + * Type of (unblinded) coin signatures for Taler. + */ +struct TALER_DenominationSignature +{ + /** + * Taler uses RSA for blinding. + */ + struct GNUNET_CRYPTO_rsa_Signature *rsa_signature; +}; + + +/** + * Type of public signing keys for verifying blindly signed coins. + */ +struct TALER_DenominationPublicKey +{ + /** + * Taler uses RSA for signing coins. + */ + struct GNUNET_CRYPTO_rsa_PublicKey *rsa_public_key; +}; + + +/** + * Type of private signing keys for blind signing of coins. + */ +struct TALER_DenominationPrivateKey +{ + /** + * Taler uses RSA for signing coins. + */ + struct GNUNET_CRYPTO_rsa_PrivateKey *rsa_private_key; +}; + + /** * Public information about a coin (including the public key * of the coin, the denomination key and the signature with @@ -37,19 +327,19 @@ struct TALER_CoinPublicInfo /** * The coin's public key. */ - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + struct TALER_CoinSpendPublicKey coin_pub; /** * Public key representing the denomination of the coin * that is being deposited. */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct TALER_DenominationPublicKey denom_pub; /** * (Unblinded) signature over @e coin_pub with @e denom_pub, * which demonstrates that the coin is valid. */ - struct GNUNET_CRYPTO_rsa_Signature *denom_sig; + struct TALER_DenominationSignature denom_sig; }; @@ -126,7 +416,7 @@ struct TALER_RefreshLinkEncrypted /** * Encrypted private key of the coin. */ - char coin_priv_enc[sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)]; + char coin_priv_enc[sizeof (struct TALER_CoinSpendPrivateKey)]; }; @@ -140,12 +430,12 @@ struct TALER_RefreshLinkDecrypted /** * Private key of the coin. */ - struct GNUNET_CRYPTO_EcdsaPrivateKey coin_priv; + struct TALER_CoinSpendPrivateKey coin_priv; /** - * Blinding key with @e blinding_key_enc_size bytes. + * Blinding key. */ - struct GNUNET_CRYPTO_rsa_BlindingKey *blinding_key; + struct TALER_DenominationBlindingKey blinding_key; }; diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index f300a5cfb..30aaad38e 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -42,7 +42,7 @@ struct TALER_MINT_SigningPublicKey /** * The signing public key */ - struct GNUNET_CRYPTO_EddsaPublicKey key; + struct TALER_MintPublicKey key; /** * Validity start time @@ -64,7 +64,7 @@ struct TALER_MINT_DenomPublicKey /** * The public key */ - struct GNUNET_CRYPTO_rsa_PublicKey *key; + struct TALER_DenominationPublicKey key; /** * Timestamp indicating when the denomination key becomes valid @@ -132,7 +132,7 @@ TALER_MINT_cleanup (struct TALER_MINT_Context *ctx); * @param hostname the hostname of the mint * @param port the point where the mint's HTTP service is running. If port is * given as 0, ports 80 or 443 are chosen depending on @a url. - * @param mint_key the public key of the mint. This is used to verify the + * @param master_key the public master key of the mint. This is used to verify the * responses of the mint. * @return the mint handle; NULL upon error */ @@ -140,7 +140,7 @@ struct TALER_MINT_Handle * TALER_MINT_connect (struct TALER_MINT_Context *ctx, const char *hostname, uint16_t port, - struct GNUNET_CRYPTO_EddsaPublicKey *mint_key); + const struct TALER_MasterPublicKey *master_key); /** * Disconnect from the mint @@ -282,15 +282,15 @@ struct TALER_MINT_DepositHandle * TALER_MINT_deposit_submit_json_ (struct TALER_MINT_Handle *mint, TALER_MINT_DepositResultCallback *cb, void *cls, - struct GNUNET_CRYPTO_EddsaPublicKey *coin_pub, - struct TALER_BLIND_SigningPublicKey *denom_pub, + const struct TALER_CoinPublicKey *coin_pub, + const struct TALER_BLIND_SigningPublicKey *denom_pub, struct TALER_BLIND_Signature *ubsig, uint64_t transaction_id, struct TALER_Amount *amount, - struct GNUNET_CRYPTO_EddsaPublicKey *merchant_pub, - struct GNUNET_HashCode *h_contract, - struct GNUNET_HashCode *h_wire, - struct GNUNET_CRYPTO_EddsaSignature *csig, + const struct TALER_MerchantPublicKey *merchant_pub, + const struct GNUNET_HashCode *h_contract, + const struct GNUNET_HashCode *h_wire, + const struct TALER_CoinSignature *csig, json_t *wire_obj); #endif diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 4566764d0..51134bf26 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014 Christian Grothoff (and other contributing authors) + Copyright (C) 2014, 2015 Christian Grothoff (and other contributing authors) 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 @@ -28,7 +28,6 @@ #ifndef TALER_SIGNATURES_H #define TALER_SIGNATURES_H -#include #include "taler_util.h" /** @@ -129,7 +128,7 @@ struct TALER_WithdrawRequest * Reserve public key (which reserve to withdraw from). This is * the public key which must match the signature. */ - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + struct TALER_ReservePublicKey reserve_pub; /** * Value of the coin being minted (matching the denomination key) @@ -189,7 +188,7 @@ struct TALER_DepositRequest /** * The coin's public key. */ - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + struct TALER_CoinSpendPublicKey coin_pub; }; @@ -232,12 +231,12 @@ struct TALER_DepositConfirmation /** * The coin's public key. */ - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + struct TALER_CoinSpendPublicKey coin_pub; /** * The Merchant's public key. */ - struct GNUNET_CRYPTO_EddsaPublicKey merchant; + struct TALER_MerchantPublicKey merchant; }; @@ -274,7 +273,7 @@ struct RefreshMeltCoinSignature /** * The coin's public key. */ - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + struct TALER_CoinSpendPublicKey coin_pub; }; @@ -298,7 +297,7 @@ struct RefreshMeltSessionSignature * Public key of the refresh session for which * @e melt_client_signature must be a valid signature. */ - struct GNUNET_CRYPTO_EddsaPublicKey session_key; + struct TALER_SessionPublicKey session_key; /** * What is the total value of the coins created during the @@ -348,10 +347,12 @@ struct RefreshMeltConfirmSignRequestBody */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + // FIXME: We probably need more info in here... + /** - * FIXME. + * Public key the client uses for this session. */ - struct GNUNET_CRYPTO_EddsaPublicKey session_pub; + struct TALER_SessionPublicKey session_pub; }; @@ -365,7 +366,7 @@ struct TALER_MINT_SignKeyIssue /** * Signature over the signing key (by the master key of the mint). */ - struct GNUNET_CRYPTO_EddsaSignature signature; + struct TALER_MasterSignature signature; /** * Purpose is #TALER_SIGNATURE_MASTER_SIGNKEY. @@ -376,7 +377,7 @@ struct TALER_MINT_SignKeyIssue * Master public key of the mint corresponding to @e signature. * This is the long-term offline master key of the mint. */ - struct GNUNET_CRYPTO_EddsaPublicKey master_pub; + struct TALER_MasterPublicKey master_pub; /** * When does this signing key begin to be valid? @@ -395,7 +396,7 @@ struct TALER_MINT_SignKeyIssue * The public online signing key that the mint will use * between @e start and @e expire. */ - struct GNUNET_CRYPTO_EddsaPublicKey signkey_pub; + struct TALER_MintPublicKey signkey_pub; }; @@ -409,7 +410,7 @@ struct TALER_MINT_DenomKeyIssue * Signature over this struct to affirm the validity * of the key. */ - struct GNUNET_CRYPTO_EddsaSignature signature; + struct TALER_MasterSignature signature; /** * Purpose ist #TALER_SIGNATURE_MASTER_DENOM. @@ -420,7 +421,7 @@ struct TALER_MINT_DenomKeyIssue * The long-term offline master key of the mint that was * used to create @e signature. */ - struct GNUNET_CRYPTO_EddsaPublicKey master; + struct TALER_MasterPublicKey master; /** * Start time of the validity period for this key. diff --git a/src/lib/mint_api.c b/src/lib/mint_api.c index eb2697a2e..305fc95d9 100644 --- a/src/lib/mint_api.c +++ b/src/lib/mint_api.c @@ -179,9 +179,11 @@ struct TALER_MINT_KeysGetHandle char *url; TALER_MINT_KeysGetCallback cb; - void *cls; + + void *cb_cls; TALER_MINT_ContinuationCallback cont_cb; + void *cont_cls; }; @@ -202,7 +204,8 @@ struct TALER_MINT_DepositHandle char *url; TALER_MINT_DepositResultCallback cb; - void *cls; + + void *cb_cls; char *json_enc; @@ -219,7 +222,8 @@ struct TALER_MINT_DepositHandle * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ static int -parse_timestamp (struct GNUNET_TIME_Absolute *abs, const char *tstamp_enc) +parse_timestamp (struct GNUNET_TIME_Absolute *abs, + const char *tstamp_enc) { unsigned long tstamp; @@ -242,7 +246,7 @@ parse_timestamp (struct GNUNET_TIME_Absolute *abs, const char *tstamp_enc) static int parse_json_signkey (struct TALER_MINT_SigningPublicKey **_sign_key, json_t *sign_key_obj, - struct GNUNET_CRYPTO_EddsaPublicKey *master_key) + struct TALER_MasterPublicKey *master_key) { json_t *valid_from_obj; json_t *valid_until_obj; @@ -281,7 +285,7 @@ parse_json_signkey (struct TALER_MINT_SigningPublicKey **_sign_key, EXITIF (GNUNET_SYSERR == GNUNET_CRYPTO_eddsa_public_key_from_string (key_enc, 52, - &sign_key_issue.signkey_pub)); + &sign_key_issue.signkey_pub.eddsa_pub)); sign_key_issue.purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY); sign_key_issue.purpose.size = htonl (sizeof (sign_key_issue) @@ -293,7 +297,7 @@ parse_json_signkey (struct TALER_MINT_SigningPublicKey **_sign_key, GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY, &sign_key_issue.purpose, &sig, - master_key)); + &master_key->eddsa_pub)); sign_key = GNUNET_new (struct TALER_MINT_SigningPublicKey); sign_key->valid_from = valid_from; sign_key->valid_until = valid_until; @@ -337,7 +341,7 @@ parse_json_amount (json_t *amount_obj, struct TALER_Amount *amt) static int parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, json_t *denom_key_obj, - struct GNUNET_CRYPTO_EddsaPublicKey *master_key) + struct TALER_MasterPublicKey *master_key) { json_t *obj; const char *sig_enc; @@ -424,9 +428,9 @@ parse_json_denomkey (struct TALER_MINT_DenomPublicKey **_denom_key, GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOM, &denom_key_issue.purpose, &sig, - master_key)); + &master_key->eddsa_pub)); denom_key = GNUNET_new (struct TALER_MINT_DenomPublicKey); - denom_key->key = pk; + denom_key->key.rsa_public_key = pk; denom_key->valid_from = valid_from; denom_key->withdraw_valid_until = withdraw_valid_until; denom_key->deposit_valid_until = deposit_valid_until; @@ -451,7 +455,7 @@ parse_response_keys_get (const char *in, size_t size, { json_t *resp_obj; struct TALER_MINT_DenomPublicKey **denom_keys; - struct GNUNET_CRYPTO_EddsaPublicKey master_key; + struct TALER_MasterPublicKey master_key; struct GNUNET_TIME_Absolute list_issue_date; struct TALER_MINT_SigningPublicKey **sign_keys; unsigned int n_denom_keys; @@ -487,7 +491,7 @@ parse_response_keys_get (const char *in, size_t size, EXITIF (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (master_key_enc, 52, - &master_key)); + &master_key.eddsa_pub)); } { /* parse the issue date of the response */ @@ -664,7 +668,8 @@ request_failed (struct TALER_MINT_Handle *mint, long resp_code) { struct TALER_MINT_DepositHandle *dh = mint->req.deposit; TALER_MINT_DepositResultCallback cb = dh->cb; - void *cls = dh->cls; + void *cls = dh->cb_cls; + GNUNET_assert (NULL != dh); cleanup_deposit (dh); mint_disconnect (mint); @@ -705,7 +710,7 @@ request_succeeded (struct TALER_MINT_Handle *mint, long resp_code) parse_response_keys_get (mint->buf, mint->buf_size, &sign_keys, &n_sign_keys, &denom_keys, &n_denom_keys)) - gh->cb (gh->cls, sign_keys, denom_keys); + gh->cb (gh->cb_cls, sign_keys, denom_keys); else emsg = GNUNET_strdup ("Error parsing response"); } @@ -727,7 +732,7 @@ request_succeeded (struct TALER_MINT_Handle *mint, long resp_code) GNUNET_assert (NULL != dh); obj = NULL; cb = dh->cb; - cls = dh->cls; + cls = dh->cb_cls; status = 0; if (200 == resp_code) { @@ -903,15 +908,15 @@ download (char *bufptr, size_t size, size_t nitems, void *cls) * @param ctx the context * @param hostname the hostname of the mint * @param port the point where the mint's HTTP service is running. - * @param mint_key the public key of the mint. This is used to verify the - * responses of the mint. + * @param mint_key the offline master public key of the mint. + * This is used to verify the responses of the mint. * @return the mint handle; NULL upon error */ struct TALER_MINT_Handle * TALER_MINT_connect (struct TALER_MINT_Context *ctx, const char *hostname, uint16_t port, - struct GNUNET_CRYPTO_EddsaPublicKey *mint_key) + const struct TALER_MasterPublicKey *mint_key) { struct TALER_MINT_Handle *mint; @@ -952,15 +957,17 @@ TALER_MINT_disconnect (struct TALER_MINT_Handle *mint) * * @param mint handle to the mint * @param cb the callback to call with each retrieved denomination key - * @param cls closure for the above callback + * @param cb_cls closure for the above callback * @param cont_cb the callback to call after completing this asynchronous call * @param cont_cls the closure for the continuation callback * @return a handle to this asynchronous call; NULL upon eror */ struct TALER_MINT_KeysGetHandle * TALER_MINT_keys_get (struct TALER_MINT_Handle *mint, - TALER_MINT_KeysGetCallback cb, void *cls, - TALER_MINT_ContinuationCallback cont_cb, void *cont_cls) + TALER_MINT_KeysGetCallback cb, + void *cb_cls, + TALER_MINT_ContinuationCallback cont_cb, + void *cont_cls) { struct TALER_MINT_KeysGetHandle *gh; @@ -970,12 +977,17 @@ TALER_MINT_keys_get (struct TALER_MINT_Handle *mint, mint->req_type = REQUEST_TYPE_KEYSGET; mint->req.keys_get = gh; gh->cb = cb; - gh->cls = cls; + gh->cb_cls = cb_cls; gh->cont_cb = cont_cb; gh->cont_cls = cont_cls; - GNUNET_asprintf (&gh->url, "http://%s:%hu/keys", mint->hostname, mint->port); + GNUNET_asprintf (&gh->url, + "http://%s:%hu/keys", + mint->hostname, + mint->port); GNUNET_assert (CURLE_OK == - curl_easy_setopt (mint->curl, CURLOPT_URL, gh->url)); + curl_easy_setopt (mint->curl, + CURLOPT_URL, + gh->url)); if (GNUNET_NO == mint->connected) mint_connect (mint); perform_now (mint->ctx); @@ -1005,7 +1017,7 @@ TALER_MINT_keys_get_cancel (struct TALER_MINT_KeysGetHandle *get) * * @param mint the mint handle * @param cb the callback to call when a reply for this request is available - * @param cls closure for the above callback + * @param cb_cls closure for the above callback * @param deposit_obj the deposit permission received from the customer along * with the wireformat JSON object * @return a handle for this request; NULL if the JSON object could not be @@ -1015,7 +1027,7 @@ TALER_MINT_keys_get_cancel (struct TALER_MINT_KeysGetHandle *get) struct TALER_MINT_DepositHandle * TALER_MINT_deposit_submit_json (struct TALER_MINT_Handle *mint, TALER_MINT_DepositResultCallback cb, - void *cls, + void *cb_cls, json_t *deposit_obj) { struct TALER_MINT_DepositHandle *dh; @@ -1026,7 +1038,7 @@ TALER_MINT_deposit_submit_json (struct TALER_MINT_Handle *mint, mint->req_type = REQUEST_TYPE_DEPOSIT; mint->req.deposit = dh; dh->cb = cb; - dh->cls = cls; + dh->cb_cls = cb_cls; GNUNET_asprintf (&dh->url, "http://%s:%hu/deposit", mint->hostname, mint->port); GNUNET_assert (NULL != (dh->json_enc = json_dumps (deposit_obj, JSON_COMPACT))); GNUNET_assert (CURLE_OK == diff --git a/src/mint/key_io.c b/src/mint/key_io.c index d267ce2a2..182d6f3de 100644 --- a/src/mint/key_io.c +++ b/src/mint/key_io.c @@ -164,8 +164,9 @@ TALER_MINT_read_denom_key (const char *filename, GNUNET_free (data); return GNUNET_SYSERR; } - dki->denom_priv = priv; - dki->denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv); + dki->denom_priv.rsa_private_key = priv; + dki->denom_pub.rsa_public_key + = GNUNET_CRYPTO_rsa_private_key_get_public (priv); memcpy (&dki->issue, data, offset); @@ -193,8 +194,9 @@ TALER_MINT_write_denom_key (const char *filename, int ret; fh = NULL; - priv_enc_size = GNUNET_CRYPTO_rsa_private_key_encode (dki->denom_priv, - &priv_enc); + priv_enc_size + = GNUNET_CRYPTO_rsa_private_key_encode (dki->denom_priv.rsa_private_key, + &priv_enc); ret = GNUNET_SYSERR; if (NULL == (fh = GNUNET_DISK_file_open (filename, diff --git a/src/mint/key_io.h b/src/mint/key_io.h index b204629a2..6c6722a8a 100644 --- a/src/mint/key_io.h +++ b/src/mint/key_io.h @@ -52,7 +52,7 @@ struct TALER_MINT_SignKeyIssuePriv /** * Private key part of the mint's signing key. */ - struct GNUNET_CRYPTO_EddsaPrivateKey signkey_priv; + struct TALER_MintPrivateKey signkey_priv; /** * Public information about a mint signing key. @@ -75,13 +75,13 @@ struct TALER_MINT_DenomKeyIssuePriv * key is not available (this is the case after the key has expired * for signing coins, but is still valid for depositing coins). */ - struct GNUNET_CRYPTO_rsa_PrivateKey *denom_priv; + struct TALER_DenominationPrivateKey denom_priv; /** * Decoded denomination public key (the hash of it is in * @e issue, but we sometimes need the full public key as well). */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct TALER_DenominationPublicKey denom_pub; /** * Signed public information about a denomination key. diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c index 34aefb872..6e52a3bc4 100644 --- a/src/mint/plugin_mintdb_common.c +++ b/src/mint/plugin_mintdb_common.c @@ -46,8 +46,8 @@ common_free_reserve_history (void *cls, break; case TALER_MINT_DB_RO_WITHDRAW_COIN: cbc = rh->details.withdraw; - GNUNET_CRYPTO_rsa_signature_free (cbc->sig); - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); + 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; } diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 1d7a965cf..1c0388427 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -758,15 +758,10 @@ postgres_reserve_get (void *cls, PGresult *result; uint64_t expiration_date_nbo; struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(reserve->pub), + TALER_DB_QUERY_PARAM_PTR(&reserve->pub), TALER_DB_QUERY_PARAM_END }; - if (NULL == reserve->pub) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } result = TALER_DB_exec_prepared (session->conn, "get_reserve", params); @@ -821,11 +816,11 @@ postgres_reserves_update (void *cls, struct GNUNET_TIME_AbsoluteNBO expiry_nbo; int ret; - if ((NULL == reserve) || (NULL == reserve->pub)) + if (NULL == reserve) return GNUNET_SYSERR; ret = GNUNET_OK; struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&reserve->pub), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), TALER_DB_QUERY_PARAM_PTR (&expiry_nbo), @@ -901,7 +896,7 @@ postgres_reserves_in_insert (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reserve does not exist; creating a new one\n"); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&reserve->pub), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), TALER_DB_QUERY_PARAM_PTR_SIZED (balance_nbo.currency, @@ -923,7 +918,7 @@ postgres_reserves_in_insert (void *cls, result = NULL; /* create new incoming transaction */ struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR (reserve->pub), + TALER_DB_QUERY_PARAM_PTR (&reserve->pub), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.value), TALER_DB_QUERY_PARAM_PTR (&balance_nbo.fraction), TALER_DB_QUERY_PARAM_PTR_SIZED (&balance_nbo.currency, @@ -1053,8 +1048,8 @@ postgres_get_collectable_blindcoin (void *cls, GNUNET_break (0); goto cleanup; } - collectable->denom_pub = denom_pub; - collectable->sig = denom_sig; + collectable->denom_pub.rsa_public_key = denom_pub; + collectable->sig.rsa_signature = denom_sig; ret = GNUNET_YES; cleanup: @@ -1103,10 +1098,10 @@ postgres_insert_collectable_blindcoin (void *cls, ret = GNUNET_SYSERR; denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub, + GNUNET_CRYPTO_rsa_public_key_encode (collectable->denom_pub.rsa_public_key, &denom_pub_enc); denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (collectable->sig, + GNUNET_CRYPTO_rsa_signature_encode (collectable->sig.rsa_signature, &denom_sig_enc); struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR (h_blind), @@ -1127,8 +1122,7 @@ postgres_insert_collectable_blindcoin (void *cls, QUERY_ERR (result); goto rollback; } - reserve.pub = (struct GNUNET_CRYPTO_EddsaPublicKey *) - &collectable->reserve_pub; + reserve.pub = collectable->reserve_pub; if (GNUNET_OK != postgres_reserve_get (cls, session, &reserve)) @@ -1172,7 +1166,7 @@ postgres_insert_collectable_blindcoin (void *cls, static struct ReserveHistory * postgres_get_reserve_history (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) + const struct TALER_ReservePublicKey *reserve_pub) { PGresult *result; struct ReserveHistory *rh; @@ -1219,7 +1213,7 @@ postgres_get_reserve_history (void *cls, GNUNET_break (0); goto cleanup; } - (void) memcpy (&bt->reserve_pub, reserve_pub, sizeof (bt->reserve_pub)); + bt->reserve_pub = *reserve_pub; if (NULL != rh_head) { rh_head->next = GNUNET_new (struct ReserveHistory); @@ -1238,7 +1232,7 @@ postgres_get_reserve_history (void *cls, result = NULL; { struct GNUNET_HashCode blind_ev; - struct GNUNET_CRYPTO_EddsaSignature reserve_sig; + struct TALER_ReserveSignature reserve_sig; struct CollectableBlindcoin *cbc; char *denom_pub_enc; char *denom_sig_enc; @@ -1280,20 +1274,23 @@ postgres_get_reserve_history (void *cls, goto cleanup; } cbc = GNUNET_new (struct CollectableBlindcoin); - cbc->sig = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, - denom_sig_enc_size); + cbc->sig.rsa_signature + = GNUNET_CRYPTO_rsa_signature_decode (denom_sig_enc, + denom_sig_enc_size); GNUNET_free (denom_sig_enc); denom_sig_enc = NULL; - cbc->denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, - denom_pub_enc_size); + cbc->denom_pub.rsa_public_key + = GNUNET_CRYPTO_rsa_public_key_decode (denom_pub_enc, + denom_pub_enc_size); GNUNET_free (denom_pub_enc); denom_pub_enc = NULL; - if ((NULL == cbc->sig) || (NULL == cbc->denom_pub)) + if ( (NULL == cbc->sig.rsa_signature) || + (NULL == cbc->denom_pub.rsa_public_key) ) { - if (NULL != cbc->sig) - GNUNET_CRYPTO_rsa_signature_free (cbc->sig); - if (NULL != cbc->denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub); + if (NULL != cbc->sig.rsa_signature) + GNUNET_CRYPTO_rsa_signature_free (cbc->sig.rsa_signature); + if (NULL != cbc->denom_pub.rsa_public_key) + GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub.rsa_public_key); GNUNET_free (cbc); GNUNET_break (0); goto cleanup; @@ -1394,10 +1391,10 @@ postgres_insert_deposit (void *cls, ret = GNUNET_SYSERR; denom_pub_enc_size = - GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub, + GNUNET_CRYPTO_rsa_public_key_encode (deposit->coin.denom_pub.rsa_public_key, &denom_pub_enc); denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig, + GNUNET_CRYPTO_rsa_signature_encode (deposit->coin.denom_sig.rsa_signature, &denom_sig_enc); json_wire_enc = json_dumps (deposit->wire, JSON_COMPACT); TALER_amount_hton (&amount_nbo, @@ -1450,7 +1447,7 @@ postgres_insert_deposit (void *cls, static int postgres_get_refresh_session (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, struct RefreshSession *refresh_session) { // FIXME: check logic! @@ -1526,7 +1523,7 @@ postgres_get_refresh_session (void *cls, static int postgres_create_refresh_session (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct TALER_SessionPublicKey *session_pub, const struct RefreshSession *refresh_session) { // FIXME: actually store session data! @@ -1570,7 +1567,7 @@ postgres_create_refresh_session (void *cls, static int postgres_insert_refresh_melt (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, const struct RefreshMelt *melt) { @@ -1580,7 +1577,7 @@ postgres_insert_refresh_melt (void *cls, size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub, + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (melt->coin.denom_pub.rsa_public_key, &buf); { struct TALER_DB_QueryParam params[] = { @@ -1620,7 +1617,7 @@ postgres_insert_refresh_melt (void *cls, static int postgres_get_refresh_melt (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, struct RefreshMelt *melt) { @@ -1645,9 +1642,9 @@ postgres_get_refresh_melt (void *cls, static int postgres_insert_refresh_order (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct TALER_SessionPublicKey *session_pub, uint16_t num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs) + const struct TALER_DenominationPublicKey *denom_pubs) { // FIXME: check logic: was written for just one COIN! uint16_t newcoin_index_nbo = htons (num_newcoins); @@ -1655,7 +1652,7 @@ postgres_insert_refresh_order (void *cls, size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (*denom_pubs, + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs->rsa_public_key, &buf); { @@ -1701,9 +1698,9 @@ postgres_insert_refresh_order (void *cls, static int postgres_get_refresh_order (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct TALER_SessionPublicKey *session_pub, uint16_t num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs) + struct TALER_DenominationPublicKey *denom_pubs) { // FIXME: check logic -- was written for just one coin! char *buf; @@ -1744,7 +1741,9 @@ postgres_get_refresh_order (void *cls, return GNUNET_SYSERR; } PQclear (result); - denom_pubs[0] = GNUNET_CRYPTO_rsa_public_key_decode (buf, buf_size); + denom_pubs->rsa_public_key + = GNUNET_CRYPTO_rsa_public_key_decode (buf, + buf_size); GNUNET_free (buf); return GNUNET_OK; } @@ -1767,7 +1766,7 @@ postgres_get_refresh_order (void *cls, static int postgres_insert_refresh_commit_coins (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, unsigned int num_newcoins, const struct RefreshCommitCoin *commit_coins) @@ -1780,9 +1779,9 @@ postgres_insert_refresh_commit_coins (void *cls, TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coins->coin_ev, commit_coins->coin_ev_size), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coins->refresh_link->coin_priv_enc, - commit_coins->refresh_link->blinding_key_enc_size + - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)), + TALER_DB_QUERY_PARAM_PTR_SIZED (commit_coins->refresh_link->coin_priv_enc, + commit_coins->refresh_link->blinding_key_enc_size + + sizeof (struct TALER_CoinSpendPrivateKey)), TALER_DB_QUERY_PARAM_END }; @@ -1825,7 +1824,7 @@ postgres_insert_refresh_commit_coins (void *cls, static int postgres_get_refresh_commit_coins (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int cnc_index, unsigned int newcoin_index, struct RefreshCommitCoin *cc) @@ -1873,7 +1872,7 @@ postgres_get_refresh_commit_coins (void *cls, return GNUNET_SYSERR; } PQclear (result); - if (rl_buf_size < sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)) + if (rl_buf_size < sizeof (struct TALER_CoinSpendPrivateKey)) { GNUNET_free (c_buf); GNUNET_free (rl_buf); @@ -1896,7 +1895,7 @@ postgres_get_refresh_commit_coins (void *cls, * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use * @param refresh_session_pub public key of the refresh session this - * commitment belongs with + * commitment belongs with -- FIXME: should not be needed! * @param i set index (1st dimension) * @param j coin index (2nd dimension), corresponds to melted (old) coins * @param commit_link link information to store @@ -1905,7 +1904,7 @@ postgres_get_refresh_commit_coins (void *cls, static int postgres_insert_refresh_commit_links (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, unsigned int j, const struct RefreshCommitLink *commit_link) @@ -1950,7 +1949,7 @@ postgres_insert_refresh_commit_links (void *cls, * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use * @param refresh_session_pub public key of the refresh session this - * commitment belongs with + * commitment belongs with -- FIXME: should not be needed! * @param i set index (1st dimension) * @param num_links size of the @a commit_link array * @param links[OUT] array of link information to return @@ -1961,7 +1960,7 @@ postgres_insert_refresh_commit_links (void *cls, static int postgres_get_refresh_commit_links (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, unsigned int num_links, struct RefreshCommitLink *links) @@ -2026,9 +2025,9 @@ postgres_get_refresh_commit_links (void *cls, static int postgres_insert_refresh_collectable (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct TALER_SessionPublicKey *session_pub, uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig) + const struct TALER_DenominationSignature *ev_sig) { // FIXME: check logic! uint16_t newcoin_index_nbo = htons (newcoin_index); @@ -2036,7 +2035,7 @@ postgres_insert_refresh_collectable (void *cls, size_t buf_size; PGresult *result; - buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig, + buf_size = GNUNET_CRYPTO_rsa_signature_encode (ev_sig->rsa_signature, &buf); { struct TALER_DB_QueryParam params[] = { @@ -2073,7 +2072,7 @@ postgres_insert_refresh_collectable (void *cls, static struct LinkDataList * postgres_get_link_data_list (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) + const struct TALER_CoinSpendPublicKey *coin_pub) { // FIXME: check logic! struct LinkDataList *ldl; @@ -2146,10 +2145,12 @@ postgres_get_link_data_list (void *cls, ld_buf, ld_buf_size); - sig = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, - sig_buf_size); - denom_pub = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, - pk_buf_size); + sig + = GNUNET_CRYPTO_rsa_signature_decode (sig_buf, + sig_buf_size); + denom_pub + = GNUNET_CRYPTO_rsa_public_key_decode (pk_buf, + pk_buf_size); GNUNET_free (pk_buf); GNUNET_free (sig_buf); GNUNET_free (ld_buf); @@ -2170,8 +2171,8 @@ postgres_get_link_data_list (void *cls, pos = GNUNET_new (struct LinkDataList); pos->next = ldl; pos->link_data_enc = link_enc; - pos->denom_pub = denom_pub; - pos->ev_sig = sig; + pos->denom_pub.rsa_public_key = denom_pub; + pos->ev_sig.rsa_signature = sig; ldl = pos; } return ldl; @@ -2196,8 +2197,8 @@ postgres_get_link_data_list (void *cls, static int postgres_get_transfer (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + const struct TALER_CoinSpendPublicKey *coin_pub, + struct TALER_TransferPublicKey *transfer_pub, struct TALER_EncryptedLinkSecret *shared_secret_enc) { // FIXME: check logic! @@ -2260,7 +2261,7 @@ postgres_get_transfer (void *cls, static struct TALER_MINT_DB_TransactionList * postgres_get_coin_transactions (void *cls, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub) + const struct TALER_CoinSpendPublicKey *coin_pub) { // FIXME: check logic! GNUNET_break (0); // FIXME: implement! diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 43b226e64..039e74ff7 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -130,7 +130,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, } mks = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (mks, - deposit->coin.denom_pub); + &deposit->coin.denom_pub); TALER_amount_ntoh (&value, &dki->issue.value); TALER_MINT_key_state_release (mks); @@ -211,7 +211,7 @@ TALER_MINT_db_execute_deposit (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub) + const struct TALER_ReservePublicKey *reserve_pub) { struct TALER_MINTDB_Session *session; struct ReserveHistory *rh; @@ -255,11 +255,11 @@ TALER_MINT_db_execute_withdraw_status (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve, - const struct GNUNET_CRYPTO_rsa_PublicKey *denomination_pub, + const struct TALER_ReservePublicKey *reserve, + const struct TALER_DenominationPublicKey *denomination_pub, const char *blinded_msg, size_t blinded_msg_len, - const struct GNUNET_CRYPTO_EddsaSignature *signature) + const struct TALER_ReserveSignature *signature) { struct TALER_MINTDB_Session *session; struct ReserveHistory *rh; @@ -303,8 +303,8 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, { res = TALER_MINT_reply_withdraw_sign_success (connection, &collectable); - GNUNET_CRYPTO_rsa_signature_free (collectable.sig); - GNUNET_CRYPTO_rsa_public_key_free (collectable.denom_pub); + GNUNET_CRYPTO_rsa_signature_free (collectable.sig.rsa_signature); + GNUNET_CRYPTO_rsa_public_key_free (collectable.denom_pub.rsa_public_key); return res; } GNUNET_assert (GNUNET_NO == res); @@ -387,7 +387,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, break; case TALER_MINT_DB_RO_WITHDRAW_COIN: tdki = TALER_MINT_get_denom_key (key_state, - pos->details.withdraw->denom_pub); + &pos->details.withdraw->denom_pub); TALER_amount_ntoh (&value, &tdki->issue.value); if (0 == (res & 2)) @@ -428,7 +428,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, rh); /* Balance is good, sign the coin! */ - sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, + sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv.rsa_private_key, blinded_msg, blinded_msg_len); TALER_MINT_key_state_release (key_state); @@ -440,8 +440,9 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, return TALER_MINT_reply_internal_error (connection, "Internal error"); } - collectable.sig = sig; - collectable.denom_pub = (struct GNUNET_CRYPTO_rsa_PublicKey *) denomination_pub; + /* FIXME: this signature is still blinded, bad name... */ + collectable.sig.rsa_signature = sig; + collectable.denom_pub = *denomination_pub; collectable.reserve_pub = *reserve; GNUNET_CRYPTO_hash (blinded_msg, blinded_msg_len, @@ -494,7 +495,7 @@ refresh_accept_melts (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, const struct MintKeyState *key_state, const struct GNUNET_HashCode *melt_hash, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + const struct TALER_SessionPublicKey *session_pub, const struct TALER_CoinPublicInfo *coin_public_info, const struct MeltDetails *coin_details, uint16_t oldcoin_index) @@ -508,7 +509,7 @@ refresh_accept_melts (struct MHD_Connection *connection, int res; dki = &TALER_MINT_get_denom_key (key_state, - coin_public_info->denom_pub)->issue; + &coin_public_info->denom_pub)->issue; if (NULL == dki) return (MHD_YES == @@ -607,10 +608,10 @@ refresh_accept_melts (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_HashCode *melt_hash, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, - const struct GNUNET_CRYPTO_EddsaSignature *client_signature, + const struct TALER_SessionPublicKey *refresh_session_pub, + const struct TALER_SessionSignature *client_signature, unsigned int num_new_denoms, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, + const struct TALER_DenominationPublicKey *denom_pubs, unsigned int coin_count, const struct TALER_CoinPublicInfo *coin_public_infos, const struct MeltDetails *coin_melt_details, @@ -773,7 +774,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * @param transfer_privs private transfer keys * @param melts array of melted coins * @param num_newcoins number of newcoins being generated - * @param denom_pub array of @a num_newcoins keys for the new coins + * @param denom_pubs array of @a num_newcoins keys for the new coins * @return #GNUNET_OK if the committment was honest, * #GNUNET_NO if there was a problem and we generated an error message * #GNUNET_SYSERR if we could not even generate an error message @@ -781,13 +782,13 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, static int check_commitment (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + const struct TALER_SessionPublicKey *refresh_session, unsigned int off, unsigned int num_oldcoins, - const struct GNUNET_CRYPTO_EcdsaPrivateKey *transfer_privs, + const struct TALER_TransferPrivateKey *transfer_privs, const struct RefreshMelt *melts, unsigned int num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs) + const struct TALER_DenominationPublicKey *denom_pubs) { unsigned int j; struct TALER_LinkSecret last_shared_secret; @@ -817,14 +818,14 @@ check_commitment (struct MHD_Connection *connection, { struct TALER_TransferSecret transfer_secret; struct TALER_LinkSecret shared_secret; - struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub_check; + struct TALER_TransferPublicKey transfer_pub_check; - GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_privs[j], - &transfer_pub_check); + GNUNET_CRYPTO_ecdsa_key_get_public (&transfer_privs[j].ecdsa_priv, + &transfer_pub_check.ecdsa_pub); if (0 != memcmp (&transfer_pub_check, &commit_links[j].transfer_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) + sizeof (struct TALER_TransferPublicKey))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "transfer keys do not match\n"); @@ -840,9 +841,9 @@ check_commitment (struct MHD_Connection *connection, /* We're converting key types here, which is not very nice * but necessary and harmless (keys will be thrown away later). */ - GNUNET_CRYPTO_ecdsa_public_to_ecdhe (&melts[j].coin.coin_pub, + GNUNET_CRYPTO_ecdsa_public_to_ecdhe (&melts[j].coin.coin_pub.ecdsa_pub, &coin_ecdhe); - GNUNET_CRYPTO_ecdsa_private_to_ecdhe (&transfer_privs[j], + GNUNET_CRYPTO_ecdsa_private_to_ecdhe (&transfer_privs[j].ecdsa_priv, &transfer_ecdhe); if (GNUNET_OK != GNUNET_CRYPTO_ecc_ecdh (&transfer_ecdhe, @@ -915,7 +916,7 @@ check_commitment (struct MHD_Connection *connection, for (j = 0; j < num_newcoins; j++) { struct TALER_RefreshLinkDecrypted *link_data; - struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; + struct TALER_CoinSpendPublicKey coin_pub; struct GNUNET_HashCode h_msg; char *buf; size_t buf_len; @@ -931,15 +932,15 @@ check_commitment (struct MHD_Connection *connection, ? GNUNET_NO : GNUNET_SYSERR; } - GNUNET_CRYPTO_ecdsa_key_get_public (&link_data->coin_priv, - &coin_pub); + GNUNET_CRYPTO_ecdsa_key_get_public (&link_data->coin_priv.ecdsa_priv, + &coin_pub.ecdsa_pub); GNUNET_CRYPTO_hash (&coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + sizeof (struct TALER_CoinSpendPublicKey), &h_msg); if (0 == (buf_len = GNUNET_CRYPTO_rsa_blind (&h_msg, - link_data->blinding_key, - denom_pubs[j], + link_data->blinding_key.rsa_blinding_key, + denom_pubs[j].rsa_public_key, &buf))) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, @@ -989,42 +990,45 @@ check_commitment (struct MHD_Connection *connection, * @param coin_off number of the coin * @return NULL on error, otherwise signature over the coin */ -static struct GNUNET_CRYPTO_rsa_Signature * +static struct TALER_DenominationSignature refresh_mint_coin (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + const struct TALER_SessionPublicKey *refresh_session, struct MintKeyState *key_state, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub, + const struct TALER_DenominationPublicKey *denom_pub, const struct RefreshCommitCoin *commit_coin, unsigned int coin_off) { struct TALER_MINT_DenomKeyIssuePriv *dki; - struct GNUNET_CRYPTO_rsa_Signature *ev_sig; + struct TALER_DenominationSignature ev_sig; - dki = TALER_MINT_get_denom_key (key_state, denom_pub); + dki = TALER_MINT_get_denom_key (key_state, + denom_pub); if (NULL == dki) { GNUNET_break (0); - return NULL; + ev_sig.rsa_signature = NULL; + return ev_sig; } - ev_sig = GNUNET_CRYPTO_rsa_sign (dki->denom_priv, - commit_coin->coin_ev, - commit_coin->coin_ev_size); - if (NULL == ev_sig) + ev_sig.rsa_signature + = GNUNET_CRYPTO_rsa_sign (dki->denom_priv.rsa_private_key, + commit_coin->coin_ev, + commit_coin->coin_ev_size); + if (NULL == ev_sig.rsa_signature) { GNUNET_break (0); - return NULL; + return ev_sig; } if (GNUNET_OK != plugin->insert_refresh_collectable (plugin->cls, session, refresh_session, coin_off, - ev_sig)) + &ev_sig)) { GNUNET_break (0); - GNUNET_CRYPTO_rsa_signature_free (ev_sig); - return NULL; + GNUNET_CRYPTO_rsa_signature_free (ev_sig.rsa_signature); + ev_sig.rsa_signature = NULL; } return ev_sig; } @@ -1046,18 +1050,18 @@ refresh_mint_coin (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int kappa, unsigned int num_oldcoins, - struct GNUNET_CRYPTO_EcdsaPrivateKey *const*transfer_privs) + struct TALER_TransferPrivateKey **transfer_privs) { int res; struct TALER_MINTDB_Session *session; struct RefreshSession refresh_session; struct MintKeyState *key_state; struct RefreshMelt *melts; - struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs; - struct GNUNET_CRYPTO_rsa_Signature **ev_sigs; + struct TALER_DenominationPublicKey *denom_pubs; + struct TALER_DenominationSignature *ev_sigs; struct RefreshCommitCoin *commit_coins; unsigned int i; unsigned int j; @@ -1102,7 +1106,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, } } denom_pubs = GNUNET_malloc (refresh_session.num_newcoins * - sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *)); + sizeof (struct TALER_DenominationPublicKey)); if (GNUNET_OK != plugin->get_refresh_order (plugin->cls, session, @@ -1135,7 +1139,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, denom_pubs))) { for (j=0;jcsig, - &deposit->coin.coin_pub)) + &deposit->csig.ecdsa_signature, + &deposit->coin.coin_pub.ecdsa_pub)) { LOG_WARNING ("Invalid signature on /deposit request\n"); return TALER_MINT_reply_arg_invalid (connection, @@ -82,7 +82,7 @@ verify_and_execute_deposit (struct MHD_Connection *connection, /* check denomination exists and is valid */ key_state = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (key_state, - deposit->coin.denom_pub); + &deposit->coin.denom_pub); if (NULL == dki) { TALER_MINT_key_state_release (key_state); diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index ca802e2d3..b795323ee 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -111,7 +111,7 @@ static int reload_pipe[2]; * @return a JSON object describing the denomination key isue (public part) */ static json_t * -denom_key_issue_to_json (struct GNUNET_CRYPTO_rsa_PublicKey *pk, +denom_key_issue_to_json (const struct TALER_DenominationPublicKey *pk, const struct TALER_MINT_DenomKeyIssue *dki) { struct TALER_Amount value; @@ -139,7 +139,7 @@ denom_key_issue_to_json (struct GNUNET_CRYPTO_rsa_PublicKey *pk, "stamp_expire_deposit", TALER_JSON_from_abs (GNUNET_TIME_absolute_ntoh (dki->expire_spend)), "denom_pub", - TALER_JSON_from_rsa_public_key (pk), + TALER_JSON_from_rsa_public_key (pk->rsa_public_key), "value", TALER_JSON_from_amount (&value), "fee_withdraw", @@ -217,7 +217,7 @@ reload_keys_denom_iter (void *cls, return GNUNET_OK; } - GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, &denom_key_hash); d2 = GNUNET_memdup (dki, sizeof (struct TALER_MINT_DenomKeyIssuePriv)); @@ -234,7 +234,7 @@ reload_keys_denom_iter (void *cls, return GNUNET_OK; } json_array_append_new (ctx->denom_keys_array, - denom_key_issue_to_json (dki->denom_pub, + denom_key_issue_to_json (&dki->denom_pub, &dki->issue)); return GNUNET_OK; } @@ -435,11 +435,11 @@ TALER_MINT_key_state_acquire (void) */ struct TALER_MINT_DenomKeyIssuePriv * TALER_MINT_get_denom_key (const struct MintKeyState *key_state, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub) + const struct TALER_DenominationPublicKey *denom_pub) { struct GNUNET_HashCode hc; - GNUNET_CRYPTO_rsa_public_key_hash (denom_pub, + GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key, &hc); return GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map, &hc); @@ -564,16 +564,16 @@ read_again: */ void TALER_MINT_keys_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct GNUNET_CRYPTO_EddsaSignature *sig) + struct TALER_MintSignature *sig) { struct MintKeyState *key_state; key_state = TALER_MINT_key_state_acquire (); GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv, + GNUNET_CRYPTO_eddsa_sign (&key_state->current_sign_key_issue.signkey_priv.eddsa_priv, purpose, - sig)); + &sig->eddsa_signature)); TALER_MINT_key_state_release (key_state); } diff --git a/src/mint/taler-mint-httpd_keystate.h b/src/mint/taler-mint-httpd_keystate.h index 4bb468ea0..faccc8f00 100644 --- a/src/mint/taler-mint-httpd_keystate.h +++ b/src/mint/taler-mint-httpd_keystate.h @@ -67,7 +67,7 @@ TALER_MINT_key_state_release (struct MintKeyState *key_state); */ struct TALER_MINT_DenomKeyIssuePriv * TALER_MINT_get_denom_key (const struct MintKeyState *key_state, - const struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub); + const struct TALER_DenominationPublicKey *denom_pub); /** @@ -90,7 +90,7 @@ TALER_MINT_key_reload_loop (void); */ void TALER_MINT_keys_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, - struct GNUNET_CRYPTO_EddsaSignature *sig); + struct TALER_MintSignature *sig); /** diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index d6bf3c428..8a024dff2 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -58,14 +58,14 @@ */ static int handle_refresh_melt_binary (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int num_new_denoms, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs, + const struct TALER_DenominationPublicKey *denom_pubs, unsigned int coin_count, struct TALER_CoinPublicInfo *coin_public_infos, const struct MeltDetails *coin_melt_details, const struct GNUNET_HashCode *commit_hash, - const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, + const struct TALER_SessionSignature *commit_client_sig, unsigned int kappa, struct RefreshCommitCoin *const* commit_coin, struct RefreshCommitLink *const* commit_link) @@ -92,7 +92,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, /* FIXME: also hash session public key here!? #3708 */ for (i = 0; i < num_new_denoms; i++) { - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i], + buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i].rsa_public_key, &buf); GNUNET_CRYPTO_hash_context_read (hash_context, buf, @@ -113,10 +113,11 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, TALER_amount_hton (&body.amount_with_fee, &coin_melt_details->melt_amount_with_fee); - if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, - &body.purpose, - commit_client_sig, - refresh_session_pub)) + if (GNUNET_OK != + GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, + &body.purpose, + &commit_client_sig->eddsa_signature, + &refresh_session_pub->eddsa_pub)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "signature invalid (did not verify)\n"); @@ -133,7 +134,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, for (i=0;iissue; + &denom_pubs[i])->issue; TALER_amount_ntoh (&value, &dki->value); TALER_amount_ntoh (&fee_withdraw, @@ -161,7 +162,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, /* calculate contribution of the i-th melt by subtracting the fee; add the rest to the total_melt value */ dki = &TALER_MINT_get_denom_key (key_state, - coin_public_infos[i].denom_pub)->issue; + &coin_public_infos[i].denom_pub)->issue; TALER_amount_ntoh (&fee_melt, &dki->fee_refresh); if (GNUNET_OK != @@ -228,14 +229,14 @@ get_coin_public_info (struct MHD_Connection *connection, struct MeltDetails *r_melt_detail) { int ret; - struct GNUNET_CRYPTO_EcdsaSignature melt_sig; - struct GNUNET_CRYPTO_rsa_Signature *sig; - struct GNUNET_CRYPTO_rsa_PublicKey *pk; + struct TALER_CoinSpendSignature melt_sig; + struct TALER_DenominationSignature sig; + struct TALER_DenominationPublicKey pk; struct TALER_Amount amount; struct GNUNET_MINT_ParseFieldSpec spec[] = { TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), - TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig), - TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk), + TALER_MINT_PARSE_RSA_SIGNATURE ("denom_sig", &sig.rsa_signature), + TALER_MINT_PARSE_RSA_PUBLIC_KEY ("denom_pub", &pk.rsa_public_key), TALER_MINT_PARSE_FIXED ("confirm_sig", &melt_sig), TALER_MINT_PARSE_AMOUNT ("value_with_fee", &amount), TALER_MINT_PARSE_END @@ -253,8 +254,8 @@ get_coin_public_info (struct MHD_Connection *connection, TALER_test_coin_valid (r_public_info)) { TALER_MINT_release_parsed_data (spec); - r_public_info->denom_sig = NULL; - r_public_info->denom_pub = NULL; + r_public_info->denom_sig.rsa_signature = NULL; + r_public_info->denom_pub.rsa_public_key = NULL; return (MHD_YES == TALER_MINT_reply_json_pack (connection, MHD_HTTP_NOT_FOUND, @@ -304,8 +305,8 @@ verify_coin_public_info (struct MHD_Connection *connection, if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN, &body.purpose, - &r_melt_detail->melt_sig, - &r_public_info->coin_pub)) + &r_melt_detail->melt_sig.ecdsa_signature, + &r_public_info->coin_pub.ecdsa_pub)) { if (MHD_YES != TALER_MINT_reply_json_pack (connection, @@ -317,7 +318,7 @@ verify_coin_public_info (struct MHD_Connection *connection, } key_state = TALER_MINT_key_state_acquire (); dki = TALER_MINT_get_denom_key (key_state, - r_public_info->denom_pub); + &r_public_info->denom_pub); if (NULL == dki) { TALER_MINT_key_state_release (key_state); @@ -420,7 +421,7 @@ free_commit_links (struct RefreshCommitLink **commit_link, */ static int handle_refresh_melt_json (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + const struct TALER_SessionPublicKey *refresh_session_pub, const json_t *new_denoms, const json_t *melt_coins, const json_t *melt_sig_json, @@ -437,7 +438,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, int res; unsigned int i; unsigned int j; - struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs; + struct TALER_DenominationPublicKey *denom_pubs; unsigned int num_new_denoms; struct TALER_CoinPublicInfo *coin_public_infos; struct MeltDetails *coin_melt_details; @@ -446,20 +447,22 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct GNUNET_HashContext *hash_context; struct RefreshCommitCoin *commit_coin[kappa]; struct RefreshCommitLink *commit_link[kappa]; - const struct GNUNET_CRYPTO_EddsaSignature commit_client_sig; + const struct TALER_SessionSignature commit_client_sig; num_new_denoms = json_array_size (new_denoms); denom_pubs = GNUNET_malloc (num_new_denoms * - sizeof (struct GNUNET_CRYPTO_rsa_PublicKey *)); + sizeof (struct TALER_DenominationPublicKey)); for (i=0;iamount_with_fee); dr.coin_pub = deposit->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&dr.purpose, - &deposit->csig); + &deposit->csig.ecdsa_signature); break; } case TALER_MINT_DB_TT_REFRESH_MELT: @@ -368,7 +369,7 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl) &melt->amount_with_fee); ms.coin_pub = melt->coin.coin_pub; transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, - &melt->coin_sig); + &melt->coin_sig.ecdsa_signature); } break; case TALER_MINT_DB_TT_LOCK: @@ -480,7 +481,7 @@ compile_reserve_history (const struct ReserveHistory *rh, case TALER_MINT_DB_RO_WITHDRAW_COIN: dki = TALER_MINT_get_denom_key (key_state, - pos->details.withdraw->denom_pub); + &pos->details.withdraw->denom_pub); TALER_amount_ntoh (&value, &dki->issue.value); if (0 == ret) @@ -499,12 +500,12 @@ compile_reserve_history (const struct ReserveHistory *rh, wr.purpose.purpose = htonl (TALER_SIGNATURE_WITHDRAW); wr.purpose.size = htonl (sizeof (struct TALER_WithdrawRequest)); wr.reserve_pub = pos->details.withdraw->reserve_pub; - GNUNET_CRYPTO_rsa_public_key_hash (pos->details.withdraw->denom_pub, + GNUNET_CRYPTO_rsa_public_key_hash (pos->details.withdraw->denom_pub.rsa_public_key, &wr.h_denomination_pub); wr.h_coin_envelope = pos->details.withdraw->h_coin_envelope; transaction = TALER_JSON_from_eddsa_sig (&wr.purpose, - &pos->details.withdraw->reserve_sig); + &pos->details.withdraw->reserve_sig.eddsa_signature); json_array_append_new (json_history, json_pack ("{s:s, s:o, s:o}", @@ -613,7 +614,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, json_t *sig_json; int ret; - sig_json = TALER_JSON_from_rsa_signature (collectable->sig); + sig_json = TALER_JSON_from_rsa_signature (collectable->sig.rsa_signature); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", @@ -640,7 +641,7 @@ TALER_MINT_reply_withdraw_sign_success (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + const struct TALER_CoinSpendPublicKey *coin_pub, struct TALER_Amount coin_value, struct TALER_MINT_DB_TransactionList *tl, struct TALER_Amount requested, @@ -654,7 +655,7 @@ TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connect "{s:s, s:o, s:o, s:o, s:o, s:o}", "error", "insufficient funds", "coin-pub", TALER_JSON_from_data (coin_pub, - sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)), + sizeof (struct TALER_CoinSpendPublicKey)), "original-value", TALER_JSON_from_amount (&coin_value), "residual-value", TALER_JSON_from_amount (&residual), "requested-value", TALER_JSON_from_amount (&requested), @@ -676,7 +677,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, uint16_t noreveal_index) { struct RefreshMeltResponseSignatureBody body; - struct GNUNET_CRYPTO_EddsaSignature sig; + struct TALER_MintSignature sig; json_t *sig_json; int ret; @@ -687,7 +688,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, TALER_MINT_keys_sign (&body.purpose, &sig); sig_json = TALER_JSON_from_eddsa_sig (&body.purpose, - &sig); + &sig.eddsa_signature); GNUNET_assert (NULL != sig_json); ret = TALER_MINT_reply_json_pack (connection, MHD_HTTP_OK, @@ -710,7 +711,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, int TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, unsigned int num_newcoins, - struct GNUNET_CRYPTO_rsa_Signature **sigs) + const struct TALER_DenominationSignature *sigs) { int newcoin_index; json_t *root; @@ -724,7 +725,7 @@ TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, list); for (newcoin_index = 0; newcoin_index < num_newcoins; newcoin_index++) json_array_append_new (list, - TALER_JSON_from_rsa_signature (sigs[newcoin_index])); + TALER_JSON_from_rsa_signature (sigs[newcoin_index].rsa_signature)); ret = TALER_MINT_reply_json (connection, root, MHD_HTTP_OK); @@ -777,7 +778,7 @@ TALER_MINT_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + const struct TALER_TransferPublicKey *transfer_pub, const struct TALER_EncryptedLinkSecret *shared_secret_enc, const struct LinkDataList *ldl) { @@ -794,14 +795,14 @@ TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, obj = json_object (); json_object_set_new (obj, "link_enc", TALER_JSON_from_data (ldl->link_data_enc->coin_priv_enc, - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey) + + sizeof (struct TALER_CoinSpendPrivateKey) + ldl->link_data_enc->blinding_key_enc_size)); json_object_set_new (obj, "denom_pub", - TALER_JSON_from_rsa_public_key (ldl->denom_pub)); + TALER_JSON_from_rsa_public_key (ldl->denom_pub.rsa_public_key)); json_object_set_new (obj, "ev_sig", - TALER_JSON_from_rsa_signature (ldl->ev_sig)); + TALER_JSON_from_rsa_signature (ldl->ev_sig.rsa_signature)); json_array_append_new (list, obj); } @@ -812,7 +813,7 @@ TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, json_object_set_new (root, "transfer_pub", TALER_JSON_from_data (transfer_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))); + sizeof (struct TALER_TransferPublicKey))); json_object_set_new (root, "secret_enc", TALER_JSON_from_data (shared_secret_enc, diff --git a/src/mint/taler-mint-httpd_responses.h b/src/mint/taler-mint-httpd_responses.h index d42aa29b6..d7e563505 100644 --- a/src/mint/taler-mint-httpd_responses.h +++ b/src/mint/taler-mint-httpd_responses.h @@ -185,11 +185,11 @@ TALER_MINT_reply_invalid_json (struct MHD_Connection *connection); */ int TALER_MINT_reply_deposit_success (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + const struct TALER_CoinSpendPublicKey *coin_pub, const struct GNUNET_HashCode *h_wire, const struct GNUNET_HashCode *h_contract, uint64_t transaction_id, - const struct GNUNET_CRYPTO_EddsaPublicKey *merchant, + const struct TALER_MerchantPublicKey *merchant, const struct TALER_Amount *amount); @@ -276,7 +276,7 @@ TALER_MINT_reply_refresh_melt_success (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, + const struct TALER_CoinSpendPublicKey *coin_pub, struct TALER_Amount coin_value, struct TALER_MINT_DB_TransactionList *tl, struct TALER_Amount requested, @@ -294,7 +294,7 @@ TALER_MINT_reply_refresh_melt_insufficient_funds (struct MHD_Connection *connect int TALER_MINT_reply_refresh_reveal_success (struct MHD_Connection *connection, unsigned int num_newcoins, - struct GNUNET_CRYPTO_rsa_Signature **sigs); + const struct TALER_DenominationSignature *sigs); /** @@ -332,7 +332,7 @@ TALER_MINT_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, */ int TALER_MINT_reply_refresh_link_success (struct MHD_Connection *connection, - const struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + const struct TALER_TransferPublicKey *transfer_pub, const struct TALER_EncryptedLinkSecret *shared_secret_enc, const struct LinkDataList *ldl); diff --git a/src/mint/taler-mint-httpd_withdraw.c b/src/mint/taler-mint-httpd_withdraw.c index b796af946..7d7ca8060 100644 --- a/src/mint/taler-mint-httpd_withdraw.c +++ b/src/mint/taler-mint-httpd_withdraw.c @@ -49,13 +49,13 @@ TALER_MINT_handler_withdraw_status (struct RequestHandler *rh, const char *upload_data, size_t *upload_data_size) { - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + struct TALER_ReservePublicKey reserve_pub; int res; res = TALER_MINT_mhd_request_arg_data (connection, "reserve_pub", &reserve_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + sizeof (struct TALER_ReservePublicKey)); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) @@ -90,17 +90,17 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, { struct TALER_WithdrawRequest wsrd; int res; - struct GNUNET_CRYPTO_rsa_PublicKey *denomination_pub; + struct TALER_DenominationPublicKey denomination_pub; char *denomination_pub_data; size_t denomination_pub_data_size; char *blinded_msg; size_t blinded_msg_len; - struct GNUNET_CRYPTO_EddsaSignature signature; + struct TALER_ReserveSignature signature; res = TALER_MINT_mhd_request_arg_data (connection, "reserve_pub", &wsrd.reserve_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); + sizeof (struct TALER_ReservePublicKey)); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) @@ -108,7 +108,7 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, res = TALER_MINT_mhd_request_arg_data (connection, "reserve_sig", &signature, - sizeof (struct GNUNET_CRYPTO_EddsaSignature)); + sizeof (struct TALER_ReserveSignature)); if (GNUNET_SYSERR == res) return MHD_NO; /* internal error */ if (GNUNET_NO == res) @@ -148,8 +148,8 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WITHDRAW, &wsrd.purpose, - &signature, - &wsrd.reserve_pub)) + &signature.eddsa_signature, + &wsrd.reserve_pub.eddsa_pub)) { LOG_WARNING ("Client supplied invalid signature for /withdraw/sign request\n"); GNUNET_free (denomination_pub_data); @@ -157,10 +157,11 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, return TALER_MINT_reply_arg_invalid (connection, "reserve_sig"); } - denomination_pub = GNUNET_CRYPTO_rsa_public_key_decode (denomination_pub_data, - denomination_pub_data_size); + denomination_pub.rsa_public_key + = GNUNET_CRYPTO_rsa_public_key_decode (denomination_pub_data, + denomination_pub_data_size); GNUNET_free (denomination_pub_data); - if (NULL == denomination_pub) + if (NULL == denomination_pub.rsa_public_key) { LOG_WARNING ("Client supplied ill-formed denomination public key for /withdraw/sign request\n"); GNUNET_free (blinded_msg); @@ -169,12 +170,12 @@ TALER_MINT_handler_withdraw_sign (struct RequestHandler *rh, } res = TALER_MINT_db_execute_withdraw_sign (connection, &wsrd.reserve_pub, - denomination_pub, + &denomination_pub, blinded_msg, blinded_msg_len, &signature); GNUNET_free (blinded_msg); - GNUNET_CRYPTO_rsa_public_key_free (denomination_pub); + GNUNET_CRYPTO_rsa_public_key_free (denomination_pub.rsa_public_key); return res; } diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c index cb46c14e7..370b1c51a 100644 --- a/src/mint/taler-mint-keycheck.c +++ b/src/mint/taler-mint-keycheck.c @@ -70,8 +70,8 @@ signkeys_iter (void *cls, if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_SIGNKEY, &ski->issue.purpose, - &ski->issue.signature, - &ski->issue.master_pub)) + &ski->issue.signature.eddsa_signature, + &ski->issue.master_pub.eddsa_pub)) { fprintf (stderr, "Signing key `%s' has invalid signature\n", @@ -130,15 +130,15 @@ denomkeys_iter (void *cls, if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MASTER_DENOM, &dki->issue.purpose, - &dki->issue.signature, - &dki->issue.master)) + &dki->issue.signature.eddsa_signature, + &dki->issue.master.eddsa_pub)) { fprintf (stderr, "Denomination key for `%s' has invalid signature\n", alias); return GNUNET_SYSERR; } - GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, &hc); if (0 != memcmp (&hc, &dki->issue.denom_hash, diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 759e7c1b3..019ae5b3f 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -179,12 +179,12 @@ static struct GNUNET_TIME_Absolute now; /** * Master private key of the mint. */ -static struct GNUNET_CRYPTO_EddsaPrivateKey *master_priv; +static struct TALER_MasterPrivateKey master_priv; /** * Master public key of the mint. */ -static struct GNUNET_CRYPTO_EddsaPublicKey *master_pub; +static struct TALER_MasterPublicKey master_pub; /** * Until what time do we provide keys? @@ -440,23 +440,23 @@ create_signkey_issue_priv (struct GNUNET_TIME_Absolute start, struct TALER_MINT_SignKeyIssue *issue = &pi->issue; priv = GNUNET_CRYPTO_eddsa_key_create (); - pi->signkey_priv = *priv; + pi->signkey_priv.eddsa_priv = *priv; GNUNET_free (priv); - issue->master_pub = *master_pub; + issue->master_pub = master_pub; issue->start = GNUNET_TIME_absolute_hton (start); issue->expire = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (start, duration)); - GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv, - &issue->signkey_pub); + GNUNET_CRYPTO_eddsa_key_get_public (&pi->signkey_priv.eddsa_priv, + &issue->signkey_pub.eddsa_pub); issue->purpose.purpose = htonl (TALER_SIGNATURE_MASTER_SIGNKEY); issue->purpose.size = htonl (sizeof (struct TALER_MINT_SignKeyIssue) - offsetof (struct TALER_MINT_SignKeyIssue, purpose)); GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign (master_priv, + GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, &issue->purpose, - &issue->signature)); + &issue->signature.eddsa_signature)); } @@ -678,12 +678,14 @@ static void create_denomkey_issue (const struct CoinTypeParams *params, struct TALER_MINT_DenomKeyIssuePriv *dki) { - GNUNET_assert (NULL != - (dki->denom_priv = GNUNET_CRYPTO_rsa_private_key_create (params->rsa_keysize))); - dki->denom_pub = GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv); - GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub, + dki->denom_priv.rsa_private_key + = GNUNET_CRYPTO_rsa_private_key_create (params->rsa_keysize); + GNUNET_assert (NULL != dki->denom_priv.rsa_private_key); + dki->denom_pub.rsa_public_key + = GNUNET_CRYPTO_rsa_private_key_get_public (dki->denom_priv.rsa_private_key); + GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key, &dki->issue.denom_hash); - dki->issue.master = *master_pub; + dki->issue.master = master_pub; dki->issue.start = GNUNET_TIME_absolute_hton (params->anchor); dki->issue.expire_withdraw = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, @@ -704,9 +706,9 @@ create_denomkey_issue (const struct CoinTypeParams *params, offsetof (struct TALER_MINT_DenomKeyIssuePriv, issue.purpose)); GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign (master_priv, + GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, &dki->issue.purpose, - &dki->issue.signature)); + &dki->issue.signature.eddsa_signature)); } @@ -764,10 +766,10 @@ mint_keys_update_cointype (void *cls, "Failed to write denomination key information to file `%s'.\n", dkf); *ret = GNUNET_SYSERR; - GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); + GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key); return; } - GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv); + GNUNET_CRYPTO_rsa_private_key_free (denomkey_issue.denom_priv.rsa_private_key); p.anchor = GNUNET_TIME_absolute_add (p.anchor, p.duration_spend); p.anchor = GNUNET_TIME_absolute_subtract (p.anchor, @@ -825,6 +827,7 @@ main (int argc, GNUNET_GETOPT_OPTION_END }; struct GNUNET_TIME_Relative lookahead_sign; + struct GNUNET_CRYPTO_EddsaPrivateKey *eddsa_priv; GNUNET_assert (GNUNET_OK == GNUNET_log_setup ("taler-mint-keyup", @@ -872,18 +875,18 @@ main (int argc, "Master key file not given\n"); return 1; } - master_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile); - if (NULL == master_priv) + eddsa_priv = GNUNET_CRYPTO_eddsa_key_create_from_file (masterkeyfile); + if (NULL == eddsa_priv) { fprintf (stderr, "Failed to initialize master key from file `%s'\n", masterkeyfile); return 1; } - - master_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey); - GNUNET_CRYPTO_eddsa_key_get_public (master_priv, - master_pub); + master_priv.eddsa_priv = *eddsa_priv; + GNUNET_free (eddsa_priv); + GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv, + &master_pub.eddsa_pub); /* check if key from file matches the one from the configuration */ { @@ -902,7 +905,7 @@ main (int argc, return 1; } if (0 != - memcmp (master_pub, + memcmp (&master_pub, &master_pub_from_cfg, sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) { diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index 83e373340..225228812 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -35,7 +35,7 @@ struct BankTransfer /** * Public key of the reserve that was filled. */ - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + struct TALER_ReservePublicKey reserve_pub; /** * Amount that was transferred to the mint. @@ -58,7 +58,7 @@ struct Reserve /** * The reserve's public key. This uniquely identifies the reserve */ - struct GNUNET_CRYPTO_EddsaPublicKey *pub; + struct TALER_ReservePublicKey pub; /** * The balance amount existing in the reserve @@ -83,7 +83,7 @@ struct CollectableBlindcoin /** * Our signature over the (blinded) coin. */ - struct GNUNET_CRYPTO_rsa_Signature *sig; + struct TALER_DenominationSignature sig; /** * Denomination key (which coin was generated). @@ -91,12 +91,12 @@ struct CollectableBlindcoin * AMOUNT *including* fee in what is being signed * as well! */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct TALER_DenominationPublicKey denom_pub; /** * Public key of the reserve that was drained. */ - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + struct TALER_ReservePublicKey reserve_pub; /** * Hash over the blinded message, needed to verify @@ -108,7 +108,7 @@ struct CollectableBlindcoin * Signature confirming the withdrawl, matching @e reserve_pub, * @e denom_pub and @e h_coin_envelope. */ - struct GNUNET_CRYPTO_EddsaSignature reserve_sig; + struct TALER_ReserveSignature reserve_sig; }; @@ -186,13 +186,13 @@ struct Deposit * by @e h_wire in relation to the contract identified * by @e h_contract. */ - struct GNUNET_CRYPTO_EcdsaSignature csig; + struct TALER_CoinSpendSignature csig; /** * Public key of the merchant. Enables later identification * of the merchant in case of a need to rollback transactions. */ - struct GNUNET_CRYPTO_EddsaPublicKey merchant_pub; + struct TALER_MerchantPublicKey merchant_pub; /** * Hash over the contract between merchant and customer @@ -238,8 +238,10 @@ struct RefreshSession /** * Signature over the commitments by the client, * only valid if @e has_commit_sig is set. + * + * FIXME: The above comment is clearly confused. */ - struct GNUNET_CRYPTO_EddsaSignature commit_sig; + struct TALER_SessionSignature commit_sig; /** * Hash over coins to melt and coins to create of the @@ -250,7 +252,7 @@ struct RefreshSession /** * Signature over the melt by the client. */ - struct GNUNET_CRYPTO_EddsaSignature melt_sig; + struct TALER_SessionSignature melt_sig; /** * Number of coins we are melting. @@ -291,7 +293,7 @@ struct RefreshMelt /** * Signature over the melting operation. */ - struct GNUNET_CRYPTO_EcdsaSignature coin_sig; + struct TALER_CoinSpendSignature coin_sig; /** * Which melting operation should the coin become a part of. @@ -350,7 +352,7 @@ struct RefreshCommitLink /** * Transfer public key (FIXME: explain!) */ - struct GNUNET_CRYPTO_EcdsaPublicKey transfer_pub; + struct TALER_TransferPublicKey transfer_pub; /** * Encrypted shared secret to decrypt the link. @@ -378,12 +380,12 @@ struct LinkDataList /** * Denomination public key, determines the value of the coin. */ - struct GNUNET_CRYPTO_rsa_PublicKey *denom_pub; + struct TALER_DenominationPublicKey denom_pub; /** * Signature over the blinded envelope. */ - struct GNUNET_CRYPTO_rsa_Signature *ev_sig; + struct TALER_DenominationSignature ev_sig; }; @@ -393,14 +395,14 @@ struct LinkDataList struct Lock { /** - * Information about the coin that is being melted. + * Information about the coin that is being locked. */ struct TALER_CoinPublicInfo coin; /** - * Signature over the melting operation. + * Signature over the locking operation. */ - const struct GNUNET_CRYPTO_EcdsaSignature coin_sig; + struct TALER_CoinSpendSignature coin_sig; /** * How much value is being locked? @@ -535,35 +537,35 @@ struct TALER_MINTDB_Plugin * Start a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn connection to use + * @param sesssion connection to use * @return #GNUNET_OK on success */ int (*start) (void *cls, - struct TALER_MINTDB_Session *db_conn); + struct TALER_MINTDB_Session *sesssion); /** * Commit a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn connection to use + * @param sesssion connection to use * @return #GNUNET_OK on success */ int (*commit) (void *cls, - struct TALER_MINTDB_Session *db_conn); + struct TALER_MINTDB_Session *sesssion); /** * Abort/rollback a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn connection to use + * @param sesssion connection to use */ void (*rollback) (void *cls, - struct TALER_MINTDB_Session *db_conn); + struct TALER_MINTDB_Session *sesssion); /** @@ -611,7 +613,7 @@ struct TALER_MINTDB_Plugin * key of the hash of the blinded message. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param h_blind hash of the blinded message * @param collectable corresponding collectable coin (blind signature) * if a coin is found @@ -621,7 +623,7 @@ struct TALER_MINTDB_Plugin */ int (*get_collectable_blindcoin) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct GNUNET_HashCode *h_blind, struct CollectableBlindcoin *collectable); @@ -631,7 +633,7 @@ struct TALER_MINTDB_Plugin * hash of the blinded message. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param h_blind hash of the blinded message * @param withdraw amount by which the reserve will be withdrawn with this * transaction @@ -643,7 +645,7 @@ struct TALER_MINTDB_Plugin */ int (*insert_collectable_blindcoin) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct GNUNET_HashCode *h_blind, struct TALER_Amount withdraw, const struct CollectableBlindcoin *collectable); @@ -654,14 +656,14 @@ struct TALER_MINTDB_Plugin * reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn connection to use + * @param sesssion connection to use * @param reserve_pub public key of the reserve * @return known transaction history (NULL if reserve is unknown) */ struct ReserveHistory * (*get_reserve_history) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub); + struct TALER_MINTDB_Session *sesssion, + const struct TALER_ReservePublicKey *reserve_pub); /** @@ -679,7 +681,7 @@ struct TALER_MINTDB_Plugin * Check if we have the specified deposit already in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param deposit deposit to search for * @return #GNUNET_YES if we know this operation, * #GNUNET_NO if this deposit is unknown to us, @@ -687,7 +689,7 @@ struct TALER_MINTDB_Plugin */ int (*have_deposit) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct Deposit *deposit); @@ -696,13 +698,13 @@ struct TALER_MINTDB_Plugin * database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn connection to the database + * @param sesssion connection to the database * @param deposit deposit information to store * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ int (*insert_deposit) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct Deposit *deposit); @@ -710,7 +712,7 @@ struct TALER_MINTDB_Plugin * Lookup refresh session data under the given public key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database handle to use + * @param sesssion database handle to use * @param refresh_session_pub public key to use for the lookup * @param refresh_session[OUT] where to store the result * @return #GNUNET_YES on success, @@ -719,8 +721,8 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_session) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session_pub, struct RefreshSession *refresh_session); @@ -728,7 +730,7 @@ struct TALER_MINTDB_Plugin * Store new refresh session data under the given public key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database handle to use + * @param sesssion database handle to use * @param refresh_session_pub public key to use to locate the session * @param refresh_session session data to store * @return #GNUNET_YES on success, @@ -736,8 +738,8 @@ struct TALER_MINTDB_Plugin */ int (*create_refresh_session) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *session_pub, const struct RefreshSession *refresh_session); @@ -746,7 +748,7 @@ struct TALER_MINTDB_Plugin * Store the given /refresh/melt request in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param refresh_session session key of the melt operation * @param oldcoin_index index of the coin to store * @param melt coin melt operation details to store @@ -755,8 +757,8 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_melt) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, const struct RefreshMelt *melt); @@ -765,7 +767,7 @@ struct TALER_MINTDB_Plugin * Get information about melted coin details from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param refresh_session session key of the melt operation * @param oldcoin_index index of the coin to retrieve * @param melt melt data to fill in @@ -774,8 +776,8 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_melt) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, struct RefreshMelt *melt); @@ -785,7 +787,7 @@ struct TALER_MINTDB_Plugin * in a given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param session_pub refresh session key * @param num_newcoins number of coins to generate, size of the @a denom_pubs array * @param denom_pubs array denominations of the coins to create @@ -794,10 +796,10 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_order) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *session_pub, uint16_t num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey *const*denom_pubs); + const struct TALER_DenominationPublicKey *denom_pubs); /** @@ -805,7 +807,7 @@ struct TALER_MINTDB_Plugin * create in the given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param session_pub refresh session key * @param num_newcoins size of the @a denom_pubs array * @param denom_pubs[OUT] where to write @a num_newcoins denomination keys @@ -814,10 +816,10 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_order) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *session_pub, uint16_t num_newcoins, - struct GNUNET_CRYPTO_rsa_PublicKey **denom_pubs); + struct TALER_DenominationPublicKey *denom_pubs); /** @@ -825,7 +827,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param refresh_session_pub refresh session this commitment belongs to * @param i set index (1st dimension), relating to kappa * @param num_newcoins coin index size of the @a commit_coins array @@ -835,8 +837,8 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_commit_coins) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, unsigned int num_newcoins, const struct RefreshCommitCoin *commit_coins); @@ -847,22 +849,22 @@ struct TALER_MINTDB_Plugin * given coin of the given refresh session from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param refresh_session_pub refresh session the commitment belongs to * @param i set index (1st dimension) - * @param j coin index (2nd dimension), corresponds to refreshed (new) coins - * @param commit_coin[OUT] coin commitment to return + * @param num_coins size of the @a commit_coins array + * @param commit_coin[OUT] array of coin commitments to return * @return #GNUNET_OK on success * #GNUNET_NO if not found * #GNUNET_SYSERR on error */ int (*get_refresh_commit_coins) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, - unsigned int j, - struct RefreshCommitCoin *commit_coin); + unsigned int num_coins, + struct RefreshCommitCoin *commit_coins); /** @@ -870,7 +872,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param refresh_session_pub public key of the refresh session this * commitment belongs with * @param i set index (1st dimension), relating to kappa @@ -880,8 +882,8 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_commit_links) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, unsigned int num_links, const struct RefreshCommitLink *commit_links); @@ -891,7 +893,7 @@ struct TALER_MINTDB_Plugin * for the given refresh session. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection to use + * @param sesssion database connection to use * @param refresh_session_pub public key of the refresh session this * commitment belongs with * @param i set index (1st dimension) @@ -903,10 +905,10 @@ struct TALER_MINTDB_Plugin */ int (*get_refresh_commit_links) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *refresh_session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int i, - unsigned int j, + unsigned int num_links, struct RefreshCommitLink *links); @@ -917,7 +919,7 @@ struct TALER_MINTDB_Plugin * be used to try to obtain the private keys during "/refresh/link". * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param session_pub refresh session * @param newcoin_index coin index * @param ev_sig coin signature @@ -925,10 +927,10 @@ struct TALER_MINTDB_Plugin */ int (*insert_refresh_collectable) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_SessionPublicKey *session_pub, uint16_t newcoin_index, - const struct GNUNET_CRYPTO_rsa_Signature *ev_sig); + const struct TALER_DenominationSignature *ev_sig); /** @@ -936,14 +938,14 @@ struct TALER_MINTDB_Plugin * information, the denomination keys and the signatures. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param coin_pub public key to use to retrieve linkage data * @return all known link data for the coin */ struct LinkDataList * (*get_link_data_list) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + struct TALER_MINTDB_Session *sesssion, + const struct TALER_CoinSpendPublicKey *coin_pub); /** @@ -965,7 +967,7 @@ struct TALER_MINTDB_Plugin * * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param coin_pub public key of the coin * @param transfer_pub[OUT] public transfer key * @param shared_secret_enc[OUT] set to shared secret @@ -975,9 +977,9 @@ struct TALER_MINTDB_Plugin */ int (*get_transfer) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub, - struct GNUNET_CRYPTO_EcdsaPublicKey *transfer_pub, + struct TALER_MINTDB_Session *sesssion, + const struct TALER_CoinSpendPublicKey *coin_pub, + struct TALER_TransferPublicKey *transfer_pub, struct TALER_EncryptedLinkSecret *shared_secret_enc); @@ -985,7 +987,7 @@ struct TALER_MINTDB_Plugin * Test if the given /lock request is known to us. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param lock lock operation * @return #GNUNET_YES if known, * #GNUENT_NO if not, @@ -993,7 +995,7 @@ struct TALER_MINTDB_Plugin */ int (*have_lock) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct Lock *lock); @@ -1001,14 +1003,14 @@ struct TALER_MINTDB_Plugin * Store the given /lock request in the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param lock lock operation * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ int (*insert_lock) (void *cls, - struct TALER_MINTDB_Session *db_conn, + struct TALER_MINTDB_Session *sesssion, const struct Lock *lock); @@ -1017,14 +1019,14 @@ struct TALER_MINTDB_Plugin * with the given coin (/refresh/melt and /deposit operations). * * @param cls the @e cls of this struct with the plugin-specific state - * @param db_conn database connection + * @param sesssion database connection * @param coin_pub coin to investigate * @return list of transactions, NULL if coin is fresh */ struct TALER_MINT_DB_TransactionList * (*get_coin_transactions) (void *cls, - struct TALER_MINTDB_Session *db_conn, - const struct GNUNET_CRYPTO_EcdsaPublicKey *coin_pub); + struct TALER_MINTDB_Session *sesssion, + const struct TALER_CoinSpendPublicKey *coin_pub); /** diff --git a/src/mint/test_mint_common.c b/src/mint/test_mint_common.c index aa72dfdcd..f6771474c 100644 --- a/src/mint/test_mint_common.c +++ b/src/mint/test_mint_common.c @@ -31,8 +31,10 @@ if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ } while (0) + int -main (int argc, const char *const argv[]) +main (int argc, + const char *const argv[]) { struct TALER_MINT_DenomKeyIssuePriv dki; char *enc; @@ -41,25 +43,26 @@ main (int argc, const char *const argv[]) char *enc_read; size_t enc_read_size; char *tmpfile; - int ret; ret = 1; enc = NULL; enc_read = NULL; tmpfile = NULL; - dki.denom_priv = NULL; - dki_read.denom_priv = NULL; + dki.denom_priv.rsa_private_key = NULL; + dki_read.denom_priv.rsa_private_key = NULL; GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &dki.issue.signature, sizeof (dki) - offsetof (struct TALER_MINT_DenomKeyIssue, signature)); - dki.denom_priv = GNUNET_CRYPTO_rsa_private_key_create (RSA_KEY_SIZE); - enc_size = GNUNET_CRYPTO_rsa_private_key_encode (dki.denom_priv, &enc); + dki.denom_priv.rsa_private_key + = GNUNET_CRYPTO_rsa_private_key_create (RSA_KEY_SIZE); + enc_size = GNUNET_CRYPTO_rsa_private_key_encode (dki.denom_priv.rsa_private_key, + &enc); EXITIF (NULL == (tmpfile = GNUNET_DISK_mktemp ("test_mint_common"))); EXITIF (GNUNET_OK != TALER_MINT_write_denom_key (tmpfile, &dki)); EXITIF (GNUNET_OK != TALER_MINT_read_denom_key (tmpfile, &dki_read)); - enc_read_size = GNUNET_CRYPTO_rsa_private_key_encode (dki_read.denom_priv, + enc_read_size = GNUNET_CRYPTO_rsa_private_key_encode (dki_read.denom_priv.rsa_private_key, &enc_read); EXITIF (enc_size != enc_read_size); EXITIF (0 != memcmp (enc, @@ -75,9 +78,9 @@ main (int argc, const char *const argv[]) GNUNET_free (tmpfile); } GNUNET_free_non_null (enc_read); - if (NULL != dki.denom_priv) - GNUNET_CRYPTO_rsa_private_key_free (dki.denom_priv); - if (NULL != dki_read.denom_priv) - GNUNET_CRYPTO_rsa_private_key_free (dki_read.denom_priv); + if (NULL != dki.denom_priv.rsa_private_key) + GNUNET_CRYPTO_rsa_private_key_free (dki.denom_priv.rsa_private_key); + if (NULL != dki_read.denom_priv.rsa_private_key) + GNUNET_CRYPTO_rsa_private_key_free (dki_read.denom_priv.rsa_private_key); return ret; } diff --git a/src/mint/test_mint_db.c b/src/mint/test_mint_db.c index c80be70c3..0b61818f1 100644 --- a/src/mint/test_mint_db.c +++ b/src/mint/test_mint_db.c @@ -54,14 +54,15 @@ static int result; */ static int check_reserve (struct TALER_MINTDB_Session *session, - struct GNUNET_CRYPTO_EddsaPublicKey *pub, + const struct TALER_ReservePublicKey *pub, uint32_t value, uint32_t fraction, const char *currency, uint64_t expiry) { struct Reserve reserve; - reserve.pub = pub; + + reserve.pub = *pub; FAILIF (GNUNET_OK != plugin->reserve_get (plugin->cls, @@ -80,8 +81,8 @@ check_reserve (struct TALER_MINTDB_Session *session, struct DenomKeyPair { - struct GNUNET_CRYPTO_rsa_PrivateKey *priv; - struct GNUNET_CRYPTO_rsa_PublicKey *pub; + struct TALER_DenominationPrivateKey priv; + struct TALER_DenominationPublicKey pub; }; @@ -91,9 +92,10 @@ create_denom_key_pair (unsigned int size) struct DenomKeyPair *dkp; dkp = GNUNET_new (struct DenomKeyPair); - dkp->priv = GNUNET_CRYPTO_rsa_private_key_create (size); - GNUNET_assert (NULL != dkp->priv); - dkp->pub = GNUNET_CRYPTO_rsa_private_key_get_public (dkp->priv); + dkp->priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (size); + GNUNET_assert (NULL != dkp->priv.rsa_private_key); + dkp->pub.rsa_public_key + = GNUNET_CRYPTO_rsa_private_key_get_public (dkp->priv.rsa_private_key); return dkp; } @@ -101,8 +103,8 @@ create_denom_key_pair (unsigned int size) static void destroy_denon_key_pair (struct DenomKeyPair *dkp) { - GNUNET_CRYPTO_rsa_public_key_free (dkp->pub); - GNUNET_CRYPTO_rsa_private_key_free (dkp->priv); + GNUNET_CRYPTO_rsa_public_key_free (dkp->pub.rsa_public_key); + GNUNET_CRYPTO_rsa_private_key_free (dkp->priv.rsa_private_key); GNUNET_free (dkp); } @@ -121,7 +123,7 @@ run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) { struct TALER_MINTDB_Session *session; - struct GNUNET_CRYPTO_EddsaPublicKey reserve_pub; + struct TALER_ReservePublicKey reserve_pub; struct Reserve reserve; struct GNUNET_TIME_Absolute expiry; struct TALER_Amount amount; @@ -172,7 +174,7 @@ run (void *cls, goto drop; } RND_BLK (&reserve_pub); - reserve.pub = &reserve_pub; + reserve.pub = reserve_pub; amount.value = 1; amount.fraction = 1; strcpy (amount.currency, CURRENCY); @@ -209,7 +211,10 @@ run (void *cls, RND_BLK(&h_blind); RND_BLK(&cbc.reserve_sig); cbc.denom_pub = dkp->pub; - cbc.sig = GNUNET_CRYPTO_rsa_sign (dkp->priv, &h_blind, sizeof (h_blind)); + cbc.sig.rsa_signature + = GNUNET_CRYPTO_rsa_sign (dkp->priv.rsa_private_key, + &h_blind, + sizeof (h_blind)); (void) memcpy (&cbc.reserve_pub, &reserve_pub, sizeof (reserve_pub)); @@ -233,7 +238,7 @@ run (void *cls, session, &h_blind, &cbc2)); - FAILIF (NULL == cbc2.denom_pub); + FAILIF (NULL == cbc2.denom_pub.rsa_public_key); FAILIF (0 != memcmp (&cbc2.reserve_sig, &cbc.reserve_sig, sizeof (cbc2.reserve_sig))); @@ -242,8 +247,8 @@ run (void *cls, sizeof (cbc2.reserve_pub))); FAILIF (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&h_blind, - cbc2.sig, - dkp->pub)); + cbc2.sig.rsa_signature, + dkp->pub.rsa_public_key)); rh = plugin->get_reserve_history (plugin->cls, session, &reserve_pub); @@ -331,12 +336,12 @@ run (void *cls, session)); if (NULL != dkp) destroy_denon_key_pair (dkp); - if (NULL != cbc.sig) - GNUNET_CRYPTO_rsa_signature_free (cbc.sig); - if (NULL != cbc2.denom_pub) - GNUNET_CRYPTO_rsa_public_key_free (cbc2.denom_pub); - if (NULL != cbc2.sig) - GNUNET_CRYPTO_rsa_signature_free (cbc2.sig); + 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/util/crypto.c b/src/util/crypto.c index c7a00b9ab..ffc12fed9 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -52,7 +52,8 @@ fatal_error_handler (void *cls, void TALER_gcrypt_init () { - gcry_set_fatalerror_handler (&fatal_error_handler, NULL); + gcry_set_fatalerror_handler (&fatal_error_handler, + NULL); TALER_assert_as (gcry_check_version (NEED_LIBGCRYPT_VERSION), "libgcrypt version mismatch"); /* Disable secure memory. */ @@ -205,11 +206,11 @@ TALER_refresh_decrypt (const struct TALER_RefreshLinkEncrypted *input, ret = GNUNET_new (struct TALER_RefreshLinkDecrypted); memcpy (&ret->coin_priv, buf, - sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); - ret->blinding_key + sizeof (struct TALER_CoinSpendPrivateKey)); + ret->blinding_key.rsa_blinding_key = GNUNET_CRYPTO_rsa_blinding_key_decode (&buf[sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)], input->blinding_key_enc_size); - if (NULL == ret->blinding_key) + if (NULL == ret->blinding_key.rsa_blinding_key) { GNUNET_free (ret); return NULL; @@ -236,7 +237,7 @@ TALER_refresh_encrypt (const struct TALER_RefreshLinkDecrypted *input, struct TALER_RefreshLinkEncrypted *ret; derive_refresh_key (secret, &iv, &skey); - b_buf_size = GNUNET_CRYPTO_rsa_blinding_key_encode (input->blinding_key, + b_buf_size = GNUNET_CRYPTO_rsa_blinding_key_encode (input->blinding_key.rsa_blinding_key, &b_buf); ret = GNUNET_malloc (sizeof (struct TALER_RefreshLinkEncrypted) + b_buf_size); @@ -313,8 +314,8 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) &c_hash); if (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&c_hash, - coin_public_info->denom_sig, - coin_public_info->denom_pub)) + coin_public_info->denom_sig.rsa_signature, + coin_public_info->denom_pub.rsa_public_key)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "coin signature is invalid\n"); -- cgit v1.2.3 From 38fae8edf241b1a4ef7b647dbd2b87033cc8e324 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 00:00:16 +0100 Subject: -resolving fixmes or annotating to bug tracker notes --- src/mint/taler-mint-httpd_db.c | 3 +-- src/mint/taler-mint-httpd_refresh.c | 2 +- src/mint/taler-mint-keyup.c | 2 +- src/mint/taler-mint-reservemod.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 039e74ff7..30585730b 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -440,7 +440,6 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, return TALER_MINT_reply_internal_error (connection, "Internal error"); } - /* FIXME: this signature is still blinded, bad name... */ collectable.sig.rsa_signature = sig; collectable.denom_pub = *denomination_pub; collectable.reserve_pub = *reserve; @@ -730,7 +729,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, refresh_session.session_hash = *melt_hash; refresh_session.num_oldcoins = coin_count; refresh_session.num_newcoins = num_new_denoms; - refresh_session.kappa = KAPPA; // FIXME... + refresh_session.kappa = KAPPA; // FIXME... (#3711) refresh_session.noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, refresh_session.kappa); diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 8a024dff2..e72a77950 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -470,7 +470,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, coin_count = json_array_size (melt_coins); /* FIXME: make 'struct TALER_CoinPublicInfo' part of `struct MeltDetails` - and combine these two arrays/arguments! */ + and combine these two arrays/arguments! (#3726) */ coin_public_infos = GNUNET_malloc (coin_count * sizeof (struct TALER_CoinPublicInfo)); coin_melt_details = GNUNET_malloc (coin_count * diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c index 019ae5b3f..603154f65 100644 --- a/src/mint/taler-mint-keyup.c +++ b/src/mint/taler-mint-keyup.c @@ -403,7 +403,7 @@ get_anchor (const char *dir, /* FIXME: this check is a bit dubious, as 'now' may be way into the future if we want to generate - many keys... */ + many keys... #3727*/ if ((GNUNET_TIME_absolute_add (*anchor, duration)).abs_value_us < now.abs_value_us) { diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c index 958d234b1..68f736ffb 100644 --- a/src/mint/taler-mint-reservemod.c +++ b/src/mint/taler-mint-reservemod.c @@ -184,7 +184,7 @@ reservemod_add (struct TALER_Amount denom) PQresultErrorMessage (result)); return GNUNET_SYSERR; } - /* FIXME: strcmp!? There must be an API that returns an int! */ + /* Yes, for historic reasons libpq returns a 'const char *'... */ if (0 != strcmp ("1", PQcmdTuples (result))) { -- cgit v1.2.3 From abc63eda98bd64a29413b6daf60c0d2ea47a7132 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 00:01:33 +0100 Subject: avoid cast --- src/mint/plugin_mintdb_common.c | 2 +- src/mint/taler_mintdb_plugin.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c index 6e52a3bc4..34c95bae6 100644 --- a/src/mint/plugin_mintdb_common.c +++ b/src/mint/plugin_mintdb_common.c @@ -41,7 +41,7 @@ common_free_reserve_history (void *cls, case TALER_MINT_DB_RO_BANK_TO_MINT: bt = rh->details.bank; if (NULL != bt->wire) - json_decref ((json_t *) bt->wire); /* FIXME: avoid cast? */ + json_decref (bt->wire); GNUNET_free (bt); break; case TALER_MINT_DB_RO_WITHDRAW_COIN: diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index 225228812..b9c6bdfac 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -45,7 +45,7 @@ struct BankTransfer /** * Detailed wire information about the transaction. */ - const json_t *wire; + json_t *wire; }; -- cgit v1.2.3 From 373fe1c1389c1399217f37746459d0fb2cc0b53a Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 00:03:03 +0100 Subject: avoid cast --- src/mint/plugin_mintdb_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c index 34c95bae6..e326c0f41 100644 --- a/src/mint/plugin_mintdb_common.c +++ b/src/mint/plugin_mintdb_common.c @@ -68,7 +68,7 @@ static void common_free_link_data_list (void *cls, struct LinkDataList *ldl) { - GNUNET_break (0); // FIXME + GNUNET_break (0); // FIXME (#3728) } @@ -82,7 +82,7 @@ static void common_free_coin_transaction_list (void *cls, struct TALER_MINT_DB_TransactionList *list) { - // FIXME: check logic! + // FIXME: implement! // FIXME (#3728) GNUNET_break (0); } -- cgit v1.2.3 From 6e28917a45fbeafe4e6515af07bac9ee484fb86c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 00:08:33 +0100 Subject: -fix comments --- src/pq/db_pq.c | 17 ++++++++++------- src/pq/db_pq.h | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/pq/db_pq.c b/src/pq/db_pq.c index bfa929c4e..bbcf002ee 100644 --- a/src/pq/db_pq.c +++ b/src/pq/db_pq.c @@ -181,13 +181,16 @@ TALER_DB_extract_amount_nbo (PGresult *result, r_amount_nbo->value = *(uint32_t *) PQgetvalue (result, row, val_num); r_amount_nbo->fraction = *(uint32_t *) PQgetvalue (result, row, frac_num); - memset (r_amount_nbo->currency, 0, TALER_CURRENCY_LEN); - // FIXME: overflow? - len = PQgetlength (result, row, curr_num); - len = GNUNET_MIN (TALER_CURRENCY_LEN, len); - memcpy (r_amount_nbo->currency, PQgetvalue (result, row, curr_num), len); - r_amount_nbo->currency[TALER_CURRENCY_LEN - 1] = '\0'; - + memset (r_amount_nbo->currency, + 0, + TALER_CURRENCY_LEN); + len = GNUNET_MIN (TALER_CURRENCY_LEN - 1, + PQgetlength (result, row, curr_num)); + memcpy (r_amount_nbo->currency, + PQgetvalue (result, + row, + curr_num), + len); return GNUNET_OK; } diff --git a/src/pq/db_pq.h b/src/pq/db_pq.h index cb2020b96..720dad5c5 100644 --- a/src/pq/db_pq.h +++ b/src/pq/db_pq.h @@ -14,7 +14,7 @@ TALER; see the file COPYING. If not, If not, see */ /** - * @file include/taler_db_lib.h + * @file pq/db_pq.h * @brief helper functions for DB interactions * @author Sree Harsha Totakura * @author Florian Dold @@ -186,4 +186,4 @@ TALER_DB_extract_amount (PGresult *result, #endif /* TALER_DB_LIB_H_ */ -/* end of include/taler_db_lib.h */ +/* end of db/db_pq.h */ -- cgit v1.2.3 From 7f79310aa153ae18f431d2b125dd91928c9ef03c Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 12:00:40 +0100 Subject: fix #3728 --- src/mint/plugin_mintdb_common.c | 35 ++++++++++++++++++++++++++++++++--- src/mint/taler_mintdb_plugin.h | 2 +- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c index e326c0f41..a95cf4be2 100644 --- a/src/mint/plugin_mintdb_common.c +++ b/src/mint/plugin_mintdb_common.c @@ -68,7 +68,15 @@ static void common_free_link_data_list (void *cls, struct LinkDataList *ldl) { - GNUNET_break (0); // FIXME (#3728) + struct LinkDataList *next; + + while (NULL != ldl) + { + next = ldl->next; + GNUNET_free (ldl->link_data_enc); + GNUNET_free (ldl); + ldl = next; + } } @@ -82,8 +90,29 @@ static void common_free_coin_transaction_list (void *cls, struct TALER_MINT_DB_TransactionList *list) { - // FIXME: implement! // FIXME (#3728) - GNUNET_break (0); + struct TALER_MINT_DB_TransactionList *next; + + while (NULL != list) + { + next = list->next; + + switch (list->type) + { + case TALER_MINT_DB_TT_DEPOSIT: + json_decref (list->details.deposit->wire); + GNUNET_free (list->details.deposit); + break; + case TALER_MINT_DB_TT_REFRESH_MELT: + GNUNET_free (list->details.melt); + break; + case TALER_MINT_DB_TT_LOCK: + GNUNET_free (list->details.lock); + /* FIXME: look at this again once locking is implemented (#3625) */ + break; + } + GNUNET_free (list); + list = next; + } } /* end of plugin_mintdb_common.c */ diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index b9c6bdfac..078238515 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -211,7 +211,7 @@ struct Deposit /** * Detailed wire information for executing the transaction. */ - const json_t *wire; + json_t *wire; /** * Merchant-generated transaction ID to detect duplicate -- cgit v1.2.3 From 73c9949fc5573aed632c9d652bf69ca192b938a3 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 13:19:38 +0100 Subject: formulating coding style --- doc/coding-style.txt | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 doc/coding-style.txt diff --git a/doc/coding-style.txt b/doc/coding-style.txt new file mode 100644 index 000000000..2215ab0ad --- /dev/null +++ b/doc/coding-style.txt @@ -0,0 +1,54 @@ +These are the general coding style rules for Taler. + +* Baseline rules are to follow GNU guidelines, modified or extended + by the GNUnet style: https://gnunet.org/style + +Naming conventions: +=================== + +* include files (very similar to GNUnet): + + if installed, must start with "taler_" (exception: platform.h), + and MUST live in src/include/ + + if NOT installed, must NOT start with "taler_" and + MUST NOT live in src/include/ and + SHOULD NOT be included from outside of their own directory + + end in "_lib" for "simple" libraries + + end in "_plugin" for plugins + + end in "_service" for libraries accessing a service, i.e. the mint + +* binaries: + + taler-mint-xxx: mint programs + + taler-merchant-xxx: merchant programs (demos) + + taler-wallet-xxx: wallet programs + + plugins should be libtaler_plugin_xxx_yyy.so: plugin yyy for API xxx + + libtalerxxx: library for API xxx + +* logging + + tools use their full name in GNUNET_log_setup + (i.e. 'taler-mint-keyup') and log using plain 'GNUNET_log'. + + pure libraries (without associated service) use 'GNUNET_log_from' + with the component set to their library name (without lib or '.so'), + which should also be their directory name (i.e. 'util') + + plugin libraries (without associated service) use 'GNUNET_log_from' + with the component set to their type and plugin name (without lib or '.so'), + which should also be their directory name (i.e. 'mintdb-postgres') + + libraries with associated service) use 'GNUNET_log_from' + with the name of the service, which should also be their + directory name (i.e. 'mint') + +* configuration + + same rules as for GNUnet + +* exported symbols + + must start with TALER_[SUBSYSTEMNAME]_ where SUBSYSTEMNAME + MUST match the subdirectory of src/ in which the symbol is defined + + from libtalerutil start just with TALER_, without subsystemname + +* private (library-internal) symbols (including structs and macros) + + must not start with TALER_ or any other prefix + +* testcases + + must be called "test_module-under-test_case-description.c" + +* performance tests + + must be called "perf_module-under-test_case-description.c" -- cgit v1.2.3 From 55959bd01d636d324077d4201df0beca676e8d58 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 16:56:06 +0100 Subject: address #3708: melt_hash => session_hash, use session_hash for DB access, not session_pub --- doc/coding-style.txt | 7 ++ src/include/taler_crypto_lib.h | 48 +++++++----- src/include/taler_signatures.h | 4 +- src/mint/plugin_mintdb_postgres.c | 139 +++++++++++++++++----------------- src/mint/taler-mint-httpd_db.c | 61 ++++++++------- src/mint/taler-mint-httpd_db.h | 11 +-- src/mint/taler-mint-httpd_deposit.c | 2 +- src/mint/taler-mint-httpd_refresh.c | 113 +++++++++++++-------------- src/mint/taler-mint-httpd_responses.c | 2 +- src/mint/taler_mintdb_plugin.h | 76 +++++++++---------- 10 files changed, 238 insertions(+), 225 deletions(-) diff --git a/doc/coding-style.txt b/doc/coding-style.txt index 2215ab0ad..e9c3a3138 100644 --- a/doc/coding-style.txt +++ b/doc/coding-style.txt @@ -44,6 +44,13 @@ Naming conventions: MUST match the subdirectory of src/ in which the symbol is defined + from libtalerutil start just with TALER_, without subsystemname +* structs: + + structs that are 'packed' and do not contain pointers and are + thus suitable for hashing or similar operations are distinguished + by adding a "P" at the end of the name. (NEW) Note that this + convention does not hold for the GNUnet-structs (yet). + + * private (library-internal) symbols (including structs and macros) + must not start with TALER_ or any other prefix diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 0c0ad8865..a7e902777 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -27,6 +27,8 @@ /* ****************** Coin crypto primitives ************* */ +GNUNET_NETWORK_STRUCT_BEGIN + /** * Type of public keys for Taler reserves. */ @@ -269,6 +271,10 @@ struct TALER_CoinSpendSignature }; +GNUNET_NETWORK_STRUCT_END + + + /** * Type of blinding keys for Taler. */ @@ -358,6 +364,9 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info); /* ****************** Refresh crypto primitives ************* */ + +GNUNET_NETWORK_STRUCT_BEGIN + /** * Secret used to decrypt the key to decrypt link secrets. */ @@ -397,45 +406,48 @@ struct TALER_EncryptedLinkSecret /** - * Representation of an encrypted refresh link. + * Representation of an refresh link in cleartext. */ -struct TALER_RefreshLinkEncrypted +struct TALER_RefreshLinkDecrypted { /** - * Encrypted blinding key with @e blinding_key_enc_size bytes, - * must be allocated at the end of this struct. - */ - const char *blinding_key_enc; - - /** - * Number of bytes in @e blinding_key_enc. + * Private key of the coin. */ - size_t blinding_key_enc_size; + struct TALER_CoinSpendPrivateKey coin_priv; /** - * Encrypted private key of the coin. + * Blinding key. */ - char coin_priv_enc[sizeof (struct TALER_CoinSpendPrivateKey)]; + struct TALER_DenominationBlindingKey blinding_key; }; +GNUNET_NETWORK_STRUCT_END + + /** - * Representation of an refresh link in cleartext. + * Representation of an encrypted refresh link. */ -struct TALER_RefreshLinkDecrypted +struct TALER_RefreshLinkEncrypted { /** - * Private key of the coin. + * Encrypted blinding key with @e blinding_key_enc_size bytes, + * must be allocated at the end of this struct. */ - struct TALER_CoinSpendPrivateKey coin_priv; + const char *blinding_key_enc; /** - * Blinding key. + * Number of bytes in @e blinding_key_enc. */ - struct TALER_DenominationBlindingKey blinding_key; + size_t blinding_key_enc_size; + + /** + * Encrypted private key of the coin. + */ + char coin_priv_enc[sizeof (struct TALER_CoinSpendPrivateKey)]; }; diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 51134bf26..fa713dc42 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -253,9 +253,9 @@ struct RefreshMeltCoinSignature struct GNUNET_CRYPTO_EccSignaturePurpose purpose; /** - * Which melting operation should the coin become a part of. + * Which melting session should the coin become a part of. */ - struct GNUNET_HashCode melt_hash; + struct GNUNET_HashCode session_hash; /** * How much of the value of the coin should be melted? This amount diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 1c0388427..1c6851d86 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -220,11 +220,11 @@ postgres_create_tables (void *cls, ",expended_value INT4 NOT NULL" ",expended_fraction INT4 NOT NULL" ",expended_currency VARCHAR(4) NOT NULL" - ",refresh_session_pub BYTEA" + ",refresh_session_hash BYTEA" ")"); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions " "(" - " session_pub BYTEA PRIMARY KEY CHECK (length(session_pub) = 32)" + " session_hash BYTEA PRIMARY KEY CHECK (length(session_hash) = 32)" ",session_melt_sig BYTEA" ",session_commit_sig BYTEA" ",noreveal_index INT2 NOT NULL" @@ -234,14 +234,14 @@ postgres_create_tables (void *cls, ") "); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_order " "( " - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" + " session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)" ",newcoin_index INT2 NOT NULL " ",denom_pub BYTEA NOT NULL " - ",PRIMARY KEY (session_pub, newcoin_index)" + ",PRIMARY KEY (session_hash, newcoin_index)" ") "); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link" "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub)" + " session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)" ",transfer_pub BYTEA NOT NULL" ",link_secret_enc BYTEA NOT NULL" // index of the old coin in the customer's request @@ -252,7 +252,7 @@ postgres_create_tables (void *cls, ")"); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_coin" "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + " session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) " ",link_vector_enc BYTEA NOT NULL" // index of the new coin in the customer's request ",newcoin_index INT2 NOT NULL" @@ -262,14 +262,14 @@ postgres_create_tables (void *cls, ")"); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_melt" "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + " session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) " ",coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) " ",denom_pub BYTEA NOT NULL " ",oldcoin_index INT2 NOT NULL" ")"); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_collectable" "(" - " session_pub BYTEA NOT NULL REFERENCES refresh_sessions (session_pub) " + " session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) " ",ev_sig BYTEA NOT NULL" ",newcoin_index INT2 NOT NULL" ")"); @@ -393,16 +393,16 @@ postgres_prepare (PGconn *db_conn) #if 0 PREPARE ("get_refresh_session", "SELECT " - " (SELECT count(*) FROM refresh_melt WHERE session_pub = $1)::INT2 as num_oldcoins " + " (SELECT count(*) FROM refresh_melt WHERE session_hash = $1)::INT2 as num_oldcoins " ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_pub = $1 and cnc_index = 0)::INT2 as num_newcoins " + " WHERE session_hash = $1 and cnc_index = 0)::INT2 as num_newcoins " ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_pub = $1 and newcoin_index = 0)::INT2 as kappa " + " WHERE session_hash = $1 and newcoin_index = 0)::INT2 as kappa " ",noreveal_index" ",session_commit_sig " ",reveal_ok " "FROM refresh_sessions " - "WHERE session_pub = $1", + "WHERE session_hash = $1", 1, NULL); #endif @@ -410,7 +410,7 @@ postgres_prepare (PGconn *db_conn) "SELECT " " coin_pub, denom_pub, denom_sig " ",expended_value, expended_fraction, expended_currency " - ",refresh_session_pub " + ",refresh_session_hash " "FROM known_coins " "WHERE coin_pub = $1", 1, NULL); @@ -422,7 +422,7 @@ postgres_prepare (PGconn *db_conn) ",expended_value = $4 " ",expended_fraction = $5 " ",expended_currency = $6 " - ",refresh_session_pub = $7 " + ",refresh_session_hash = $7 " "WHERE " " coin_pub = $1 ", 7, NULL); @@ -434,7 +434,7 @@ postgres_prepare (PGconn *db_conn) ",expended_value" ",expended_fraction" ",expended_currency" - ",refresh_session_pub" + ",refresh_session_hash" ")" "VALUES ($1,$2,$3,$4,$5,$6,$7)", 7, NULL); @@ -443,26 +443,26 @@ postgres_prepare (PGconn *db_conn) " transfer_pub " ",link_secret_enc " "FROM refresh_commit_link " - "WHERE session_pub = $1 AND cnc_index = $2 AND oldcoin_index = $3", + "WHERE session_hash = $1 AND cnc_index = $2 AND oldcoin_index = $3", 3, NULL); PREPARE ("get_refresh_commit_coin", "SELECT " " link_vector_enc " ",coin_ev " "FROM refresh_commit_coin " - "WHERE session_pub = $1 AND cnc_index = $2 AND newcoin_index = $3", + "WHERE session_hash = $1 AND cnc_index = $2 AND newcoin_index = $3", 3, NULL); PREPARE ("insert_refresh_order", "INSERT INTO refresh_order ( " " newcoin_index " - ",session_pub " + ",session_hash " ",denom_pub " ") " "VALUES ($1, $2, $3) ", 3, NULL); PREPARE ("insert_refresh_melt", "INSERT INTO refresh_melt ( " - " session_pub " + " session_hash " ",oldcoin_index " ",coin_pub " ",denom_pub " @@ -472,28 +472,28 @@ postgres_prepare (PGconn *db_conn) PREPARE ("get_refresh_order", "SELECT denom_pub " "FROM refresh_order " - "WHERE session_pub = $1 AND newcoin_index = $2", + "WHERE session_hash = $1 AND newcoin_index = $2", 2, NULL); PREPARE ("get_refresh_collectable", "SELECT ev_sig " "FROM refresh_collectable " - "WHERE session_pub = $1 AND newcoin_index = $2", + "WHERE session_hash = $1 AND newcoin_index = $2", 2, NULL); PREPARE ("get_refresh_melt", "SELECT coin_pub " "FROM refresh_melt " - "WHERE session_pub = $1 AND oldcoin_index = $2", + "WHERE session_hash = $1 AND oldcoin_index = $2", 2, NULL); PREPARE ("insert_refresh_session", "INSERT INTO refresh_sessions ( " - " session_pub " + " session_hash " ",noreveal_index " ") " "VALUES ($1, $2) ", 2, NULL); PREPARE ("insert_refresh_commit_link", "INSERT INTO refresh_commit_link ( " - " session_pub " + " session_hash " ",transfer_pub " ",cnc_index " ",oldcoin_index " @@ -503,7 +503,7 @@ postgres_prepare (PGconn *db_conn) 5, NULL); PREPARE ("insert_refresh_commit_coin", "INSERT INTO refresh_commit_coin ( " - " session_pub " + " session_hash " ",coin_ev " ",cnc_index " ",newcoin_index " @@ -513,7 +513,7 @@ postgres_prepare (PGconn *db_conn) 5, NULL); PREPARE ("insert_refresh_collectable", "INSERT INTO refresh_collectable ( " - " session_pub " + " session_hash " ",newcoin_index " ",ev_sig " ") " @@ -522,33 +522,33 @@ postgres_prepare (PGconn *db_conn) PREPARE ("set_reveal_ok", "UPDATE refresh_sessions " "SET reveal_ok = TRUE " - "WHERE session_pub = $1 ", + "WHERE session_hash = $1 ", 1, NULL); PREPARE ("get_link", "SELECT link_vector_enc, ro.denom_pub, ev_sig " "FROM refresh_melt rm " - " JOIN refresh_order ro USING (session_pub) " - " JOIN refresh_commit_coin rcc USING (session_pub) " - " JOIN refresh_sessions rs USING (session_pub) " - " JOIN refresh_collectable rc USING (session_pub) " + " JOIN refresh_order ro USING (session_hash) " + " JOIN refresh_commit_coin rcc USING (session_hash) " + " JOIN refresh_sessions rs USING (session_hash) " + " JOIN refresh_collectable rc USING (session_hash) " "WHERE rm.coin_pub = $1 " "AND ro.newcoin_index = rcc.newcoin_index " "AND ro.newcoin_index = rc.newcoin_index " "AND rcc.cnc_index = rs.noreveal_index % ( " " SELECT count(*) FROM refresh_commit_coin rcc2 " - " WHERE rcc2.newcoin_index = 0 AND rcc2.session_pub = rs.session_pub " + " WHERE rcc2.newcoin_index = 0 AND rcc2.session_hash = rs.session_hash " " ) ", 1, NULL); PREPARE ("get_transfer", "SELECT transfer_pub, link_secret_enc " "FROM refresh_melt rm " - " JOIN refresh_commit_link rcl USING (session_pub) " - " JOIN refresh_sessions rs USING (session_pub) " + " JOIN refresh_commit_link rcl USING (session_hash) " + " JOIN refresh_sessions rs USING (session_hash) " "WHERE rm.coin_pub = $1 " "AND rm.oldcoin_index = rcl.oldcoin_index " "AND rcl.cnc_index = rs.noreveal_index % ( " " SELECT count(*) FROM refresh_commit_coin rcc2 " - " WHERE newcoin_index = 0 AND rcc2.session_pub = rm.session_pub " + " WHERE newcoin_index = 0 AND rcc2.session_hash = rm.session_hash " " ) ", 1, NULL); PREPARE ("insert_deposit", @@ -1434,11 +1434,11 @@ postgres_insert_deposit (void *cls, /** - * Lookup refresh session data under the given public key. + * Lookup refresh session data under the given @a session_hash. * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database handle to use - * @param refresh_session_pub public key to use for the lookup + * @param session_hash hash over the melt to use to locate the session * @param refresh_session[OUT] where to store the result * @return #GNUNET_YES on success, * #GNUNET_NO if not found, @@ -1447,13 +1447,13 @@ postgres_insert_deposit (void *cls, static int postgres_get_refresh_session (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, struct RefreshSession *refresh_session) { // FIXME: check logic! int res; struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_END }; @@ -1511,11 +1511,11 @@ postgres_get_refresh_session (void *cls, /** - * Store new refresh session data under the given public key. + * Store new refresh session data under the given @a session_hash. * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database handle to use - * @param refresh_session_pub public key to use to locate the session + * @param session_hash hash over the melt to use to locate the session * @param refresh_session session data to store * @return #GNUNET_YES on success, * #GNUNET_SYSERR on DB failure @@ -1523,13 +1523,13 @@ postgres_get_refresh_session (void *cls, static int postgres_create_refresh_session (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, const struct RefreshSession *refresh_session) { // FIXME: actually store session data! uint16_t noreveal_index; struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&noreveal_index), TALER_DB_QUERY_PARAM_END }; @@ -1558,16 +1558,15 @@ postgres_create_refresh_session (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection - * @param refresh_session session key of the melt operation * @param oldcoin_index index of the coin to store - * @param melt melt operation + * @param melt melt operation details to store; includes + * the session hash of the melt * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ static int postgres_insert_refresh_melt (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, const struct RefreshMelt *melt) { @@ -1581,7 +1580,7 @@ postgres_insert_refresh_melt (void *cls, &buf); { struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session), + TALER_DB_QUERY_PARAM_PTR(&melt->session_hash), TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), TALER_DB_QUERY_PARAM_PTR(&melt->coin.coin_pub), TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), @@ -1617,7 +1616,7 @@ postgres_insert_refresh_melt (void *cls, static int postgres_get_refresh_melt (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session, + const struct GNUNET_HashCode *session_hash, uint16_t oldcoin_index, struct RefreshMelt *melt) { @@ -1633,7 +1632,7 @@ postgres_get_refresh_melt (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection - * @param session_pub refresh session key + * @param session_hash hash to identify refresh session * @param num_newcoins number of coins to generate, size of the @a denom_pubs array * @param denom_pubs array denominations of the coins to create * @return #GNUNET_OK on success @@ -1642,7 +1641,7 @@ postgres_get_refresh_melt (void *cls, static int postgres_insert_refresh_order (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, const struct TALER_DenominationPublicKey *denom_pubs) { @@ -1658,7 +1657,7 @@ postgres_insert_refresh_order (void *cls, { struct TALER_DB_QueryParam params[] = { TALER_DB_QUERY_PARAM_PTR (&newcoin_index_nbo), - TALER_DB_QUERY_PARAM_PTR (session_pub), + TALER_DB_QUERY_PARAM_PTR (session_hash), TALER_DB_QUERY_PARAM_PTR_SIZED (buf, buf_size), TALER_DB_QUERY_PARAM_END }; @@ -1689,7 +1688,7 @@ postgres_insert_refresh_order (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection - * @param session_pub refresh session key + * @param session_hash hash to identify refresh session * @param newcoin_index array of the @a denom_pubs array * @param denom_pubs where to store the deomination keys * @return #GNUNET_OK on success @@ -1698,7 +1697,7 @@ postgres_insert_refresh_order (void *cls, static int postgres_get_refresh_order (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, struct TALER_DenominationPublicKey *denom_pubs) { @@ -1708,7 +1707,7 @@ postgres_get_refresh_order (void *cls, uint16_t newcoin_index_nbo = htons (num_newcoins); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), TALER_DB_QUERY_PARAM_END }; @@ -1756,7 +1755,7 @@ postgres_get_refresh_order (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use - * @param refresh_session_pub refresh session this commitment belongs to + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param num_newcoins coin index size of the @a commit_coins array * @param commit_coins array of coin commitments to store @@ -1766,7 +1765,7 @@ postgres_get_refresh_order (void *cls, static int postgres_insert_refresh_commit_coins (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_newcoins, const struct RefreshCommitCoin *commit_coins) @@ -1775,7 +1774,7 @@ postgres_insert_refresh_commit_coins (void *cls, uint16_t cnc_index_nbo = htons (i); uint16_t newcoin_index_nbo = htons (num_newcoins); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR_SIZED(commit_coins->coin_ev, commit_coins->coin_ev_size), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), @@ -1813,7 +1812,7 @@ postgres_insert_refresh_commit_coins (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use - * @param refresh_session_pub refresh session the commitment belongs to + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param j coin index (2nd dimension), corresponds to refreshed (new) coins * @param commit_coin[OUT] coin commitment to return @@ -1824,7 +1823,7 @@ postgres_insert_refresh_commit_coins (void *cls, static int postgres_get_refresh_commit_coins (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int cnc_index, unsigned int newcoin_index, struct RefreshCommitCoin *cc) @@ -1833,7 +1832,7 @@ postgres_get_refresh_commit_coins (void *cls, uint16_t cnc_index_nbo = htons (cnc_index); uint16_t newcoin_index_nbo = htons (newcoin_index); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), TALER_DB_QUERY_PARAM_END @@ -1894,8 +1893,7 @@ postgres_get_refresh_commit_coins (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with -- FIXME: should not be needed! + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param j coin index (2nd dimension), corresponds to melted (old) coins * @param commit_link link information to store @@ -1904,7 +1902,7 @@ postgres_get_refresh_commit_coins (void *cls, static int postgres_insert_refresh_commit_links (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int j, const struct RefreshCommitLink *commit_link) @@ -1913,7 +1911,7 @@ postgres_insert_refresh_commit_links (void *cls, uint16_t cnc_index_nbo = htons (i); uint16_t oldcoin_index_nbo = htons (j); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&commit_link->transfer_pub), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), @@ -1948,8 +1946,7 @@ postgres_insert_refresh_commit_links (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with -- FIXME: should not be needed! + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param num_links size of the @a commit_link array * @param links[OUT] array of link information to return @@ -1960,7 +1957,7 @@ postgres_insert_refresh_commit_links (void *cls, static int postgres_get_refresh_commit_links (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_links, struct RefreshCommitLink *links) @@ -1970,7 +1967,7 @@ postgres_get_refresh_commit_links (void *cls, uint16_t oldcoin_index_nbo = htons (num_links); struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(refresh_session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&cnc_index_nbo), TALER_DB_QUERY_PARAM_PTR(&oldcoin_index_nbo), TALER_DB_QUERY_PARAM_END @@ -2017,7 +2014,7 @@ postgres_get_refresh_commit_links (void *cls, * * @param cls the `struct PostgresClosure` with the plugin-specific state * @param session database connection - * @param session_pub refresh session + * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature * @return #GNUNET_OK on success @@ -2025,7 +2022,7 @@ postgres_get_refresh_commit_links (void *cls, static int postgres_insert_refresh_collectable (void *cls, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t newcoin_index, const struct TALER_DenominationSignature *ev_sig) { @@ -2039,7 +2036,7 @@ postgres_insert_refresh_collectable (void *cls, &buf); { struct TALER_DB_QueryParam params[] = { - TALER_DB_QUERY_PARAM_PTR(session_pub), + TALER_DB_QUERY_PARAM_PTR(session_hash), TALER_DB_QUERY_PARAM_PTR(&newcoin_index_nbo), TALER_DB_QUERY_PARAM_PTR_SIZED(buf, buf_size), TALER_DB_QUERY_PARAM_END diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 30585730b..7592403da 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -481,7 +481,7 @@ TALER_MINT_db_execute_withdraw_sign (struct MHD_Connection *connection, * @param connection the connection to send errors to * @param session the database connection * @param key_state the mint's key state - * @param session_pub the refresh session's public key + * @param session_hash hash identifying the refresh session * @param coin_public_info the coin to melt * @param coin_details details about the coin being melted * @param oldcoin_index what is the number assigned to this coin @@ -493,7 +493,7 @@ static int refresh_accept_melts (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, const struct MintKeyState *key_state, - const struct GNUNET_HashCode *melt_hash, + const struct GNUNET_HashCode *session_hash, const struct TALER_SessionPublicKey *session_pub, const struct TALER_CoinPublicInfo *coin_public_info, const struct MeltDetails *coin_details, @@ -563,12 +563,11 @@ refresh_accept_melts (struct MHD_Connection *connection, melt.coin = *coin_public_info; melt.coin_sig = coin_details->melt_sig; - melt.melt_hash = *melt_hash; + melt.session_hash = *session_hash; melt.amount_with_fee = coin_details->melt_amount_with_fee; if (GNUNET_OK != plugin->insert_refresh_melt (plugin->cls, session, - session_pub, oldcoin_index, &melt)) { @@ -587,7 +586,7 @@ refresh_accept_melts (struct MHD_Connection *connection, * melted and confirm the melting operation to the client. * * @param connection the MHD connection to handle - * @param melt_hash hash code of the session the coins are melted into + * @param session_hash hash code of the session the coins are melted into * @param refresh_session_pub public key of the refresh session * @param client_signature signature of the client (matching @a refresh_session_pub) * over the melting request @@ -606,7 +605,7 @@ refresh_accept_melts (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, - const struct GNUNET_HashCode *melt_hash, + const struct GNUNET_HashCode *session_hash, const struct TALER_SessionPublicKey *refresh_session_pub, const struct TALER_SessionSignature *client_signature, unsigned int num_new_denoms, @@ -639,14 +638,14 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, } res = plugin->get_refresh_session (plugin->cls, session, - refresh_session_pub, + session_hash, &refresh_session); if (GNUNET_YES == res) { plugin->rollback (plugin->cls, session); res = TALER_MINT_reply_refresh_melt_success (connection, - &refresh_session.session_hash, + session_hash, refresh_session.noreveal_index); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } @@ -665,7 +664,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, (res = refresh_accept_melts (connection, session, key_state, - melt_hash, + session_hash, refresh_session_pub, &coin_public_infos[i], &coin_melt_details[i], @@ -683,7 +682,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_OK != plugin->insert_refresh_order (plugin->cls, session, - refresh_session_pub, + session_hash, num_new_denoms, denom_pubs)) { @@ -697,7 +696,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_OK != plugin->insert_refresh_commit_coins (plugin->cls, session, - refresh_session_pub, + session_hash, i, num_new_denoms, commit_coin[i])) @@ -712,7 +711,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_OK != plugin->insert_refresh_commit_links (plugin->cls, session, - refresh_session_pub, + session_hash, i, coin_count, commit_link[i])) @@ -726,7 +725,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, /* store 'global' session data */ refresh_session.melt_sig = *client_signature; - refresh_session.session_hash = *melt_hash; + refresh_session.refresh_session_pub = *refresh_session_pub; refresh_session.num_oldcoins = coin_count; refresh_session.num_newcoins = num_new_denoms; refresh_session.kappa = KAPPA; // FIXME... (#3711) @@ -736,7 +735,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_OK != (res = plugin->create_refresh_session (plugin->cls, session, - refresh_session_pub, + session_hash, &refresh_session))) { plugin->rollback (plugin->cls, @@ -754,7 +753,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return TALER_MINT_reply_commit_error (connection); } return TALER_MINT_reply_refresh_melt_success (connection, - &refresh_session.session_hash, + session_hash, refresh_session.noreveal_index); } @@ -767,7 +766,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param session database connection to use - * @param refresh_session session to query + * @param session_hash hash of session to query * @param off commitment offset to check * @param num_oldcoins size of the @a transfer_privs and @a melts arrays * @param transfer_privs private transfer keys @@ -781,7 +780,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, static int check_commitment (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session, + const struct GNUNET_HashCode *session_hash, unsigned int off, unsigned int num_oldcoins, const struct TALER_TransferPrivateKey *transfer_privs, @@ -802,7 +801,7 @@ check_commitment (struct MHD_Connection *connection, if (GNUNET_OK != plugin->get_refresh_commit_links (plugin->cls, session, - refresh_session, + session_hash, off, num_oldcoins, commit_links)) @@ -901,7 +900,7 @@ check_commitment (struct MHD_Connection *connection, if (GNUNET_OK != plugin->get_refresh_commit_coins (plugin->cls, session, - refresh_session, + session_hash, off, num_newcoins, commit_coins)) @@ -982,7 +981,7 @@ check_commitment (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param session database connection to use - * @param refresh_session session to query + * @param session_hash hash of session to query * @param key_state key state to lookup denomination pubs * @param denom_pub denomination key for the coin to create * @param commit_coin the coin that was committed @@ -992,7 +991,7 @@ check_commitment (struct MHD_Connection *connection, static struct TALER_DenominationSignature refresh_mint_coin (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, - const struct TALER_SessionPublicKey *refresh_session, + const struct GNUNET_HashCode *session_hash, struct MintKeyState *key_state, const struct TALER_DenominationPublicKey *denom_pub, const struct RefreshCommitCoin *commit_coin, @@ -1021,7 +1020,7 @@ refresh_mint_coin (struct MHD_Connection *connection, if (GNUNET_OK != plugin->insert_refresh_collectable (plugin->cls, session, - refresh_session, + session_hash, coin_off, &ev_sig)) { @@ -1041,7 +1040,7 @@ refresh_mint_coin (struct MHD_Connection *connection, * coins that was not chosen. * * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the refresh session + * @param session_hash hash identifying the refresh session * @param kappa size of x-dimension of @transfer_privs array plus one (!) * @param num_oldcoins size of y-dimension of @transfer_privs array * @param transfer_pubs array with the revealed transfer keys @@ -1049,7 +1048,7 @@ refresh_mint_coin (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int kappa, unsigned int num_oldcoins, struct TALER_TransferPrivateKey **transfer_privs) @@ -1075,11 +1074,11 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, res = plugin->get_refresh_session (plugin->cls, session, - refresh_session_pub, + session_hash, &refresh_session); if (GNUNET_NO == res) return TALER_MINT_reply_arg_invalid (connection, - "session_pub"); + "session_hash"); if (GNUNET_SYSERR == res) return TALER_MINT_reply_internal_db_error (connection); if (0 == refresh_session.num_oldcoins) @@ -1095,7 +1094,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, if (GNUNET_OK != plugin->get_refresh_melt (plugin->cls, session, - refresh_session_pub, + session_hash, j, &melts[j])) { @@ -1109,7 +1108,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, if (GNUNET_OK != plugin->get_refresh_order (plugin->cls, session, - refresh_session_pub, + session_hash, refresh_session.num_newcoins, denom_pubs)) { @@ -1129,7 +1128,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, if (GNUNET_OK != (res = check_commitment (connection, session, - refresh_session_pub, + session_hash, i + off, refresh_session.num_oldcoins, transfer_privs[i + off], @@ -1163,7 +1162,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, if (GNUNET_OK != plugin->get_refresh_commit_coins (plugin->cls, session, - refresh_session_pub, + session_hash, refresh_session.noreveal_index, refresh_session.num_newcoins, commit_coins)) @@ -1182,7 +1181,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, { ev_sigs[j] = refresh_mint_coin (connection, session, - refresh_session_pub, + session_hash, key_state, &denom_pubs[j], &commit_coins[j], diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index fd420bd9b..edf8248c7 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -106,11 +106,8 @@ struct MeltDetails * required value left and if so, store that they have been * melted and confirm the melting operation to the client. * - * FIXME: some arguments are redundant here... - * * @param connection the MHD connection to handle - * @param melt_hash hash code of the session the coins are melted into - * @param refresh_session_pub public key of the refresh session + * @param session_hash hash code of the session the coins are melted into * @param client_signature signature of the client (matching @a refresh_session_pub) * over the melting request * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @commit_coin array @@ -128,7 +125,7 @@ struct MeltDetails */ int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, - const struct GNUNET_HashCode *melt_hash, + const struct GNUNET_HashCode *session_hash, const struct TALER_SessionPublicKey *refresh_session_pub, const struct TALER_SessionSignature *client_signature, unsigned int num_new_denoms, @@ -149,7 +146,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * coins that was not chosen. * * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the refresh session + * @param session_hash hash over the refresh session * @param kappa size of x-dimension of @transfer_privs array plus one (!) * @param num_oldcoins size of y-dimension of @transfer_privs array * @param transfer_pubs array with the revealed transfer keys @@ -157,7 +154,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, */ int TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int kappa, unsigned int num_oldcoins, struct TALER_TransferPrivateKey **transfer_privs); diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index bf8121037..7ecf8bfe6 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -131,7 +131,7 @@ static int parse_and_handle_deposit_request (struct MHD_Connection *connection, const json_t *root, const struct TALER_Amount *amount, - const json_t *wire) + json_t *wire) { int res; struct Deposit deposit; diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index e72a77950..775ffd4ce 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -72,11 +72,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, { unsigned int i; - struct GNUNET_HashContext *hash_context; - struct GNUNET_HashCode melt_hash; struct RefreshMeltSessionSignature body; - char *buf; - size_t buf_size; struct MintKeyState *key_state; struct TALER_MINT_DenomKeyIssue *dki; struct TALER_Amount cost; @@ -88,28 +84,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct TALER_Amount total_melt; /* check that signature from the session public key is ok */ - hash_context = GNUNET_CRYPTO_hash_context_start (); - /* FIXME: also hash session public key here!? #3708 */ - for (i = 0; i < num_new_denoms; i++) - { - buf_size = GNUNET_CRYPTO_rsa_public_key_encode (denom_pubs[i].rsa_public_key, - &buf); - GNUNET_CRYPTO_hash_context_read (hash_context, - buf, - buf_size); - GNUNET_free (buf); - } - for (i = 0; i < coin_count; i++) - GNUNET_CRYPTO_hash_context_read (hash_context, - &coin_public_infos[i].coin_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); - GNUNET_CRYPTO_hash_context_finish (hash_context, - &melt_hash); - /* FIXME: what about the `commit_hash`? #3708 */ - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); - body.melt_hash = melt_hash; + body.melt_hash = *commit_hash; TALER_amount_hton (&body.amount_with_fee, &coin_melt_details->melt_amount_with_fee); @@ -197,7 +174,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, "error", "value mismatch"); } return TALER_MINT_db_execute_refresh_melt (connection, - &melt_hash, + commit_hash, refresh_session_pub, commit_client_sig, num_new_denoms, @@ -278,7 +255,7 @@ get_coin_public_info (struct MHD_Connection *connection, * be done before the transaction starts. * * @param connection the connection to send error responses to - * @param melt_hash hash over refresh session the coin is melted into + * @param session_hash hash over refresh session the coin is melted into * @param r_public_info the coin's public information * @param r_melt_detail details about the coin's melting permission (if valid) * @return #GNUNET_YES if coin public info in JSON was valid @@ -287,7 +264,7 @@ get_coin_public_info (struct MHD_Connection *connection, */ static int verify_coin_public_info (struct MHD_Connection *connection, - const struct GNUNET_HashCode *melt_hash, + const struct GNUNET_HashCode *session_hash, const struct TALER_CoinPublicInfo *r_public_info, const struct MeltDetails *r_melt_detail) { @@ -298,7 +275,7 @@ verify_coin_public_info (struct MHD_Connection *connection, body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); - body.melt_hash = *melt_hash; + body.session_hash = *session_hash; TALER_amount_hton (&body.amount_with_fee, &r_melt_detail->melt_amount_with_fee); body.coin_pub = r_public_info->coin_pub; @@ -449,11 +426,21 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct RefreshCommitLink *commit_link[kappa]; const struct TALER_SessionSignature commit_client_sig; + /* For the signature check, we hash most of the inputs together + (except for the signatures on the coins). */ + hash_context = GNUNET_CRYPTO_hash_context_start (); + GNUNET_CRYPTO_hash_context_read (hash_context, + refresh_session_pub, + sizeof (struct TALER_SessionPublicKey)); + num_new_denoms = json_array_size (new_denoms); denom_pubs = GNUNET_malloc (num_new_denoms * sizeof (struct TALER_DenominationPublicKey)); for (i=0;icoin_ev, + &rcc->coin_ev_size); if (GNUNET_OK != res) { @@ -550,8 +553,8 @@ handle_refresh_melt_json (struct MHD_Connection *connection, return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } GNUNET_CRYPTO_hash_context_read (hash_context, - commit_coin[i][j].coin_ev, - commit_coin[i][j].coin_ev_size); + rcc->coin_ev, + rcc->coin_ev_size); res = GNUNET_MINT_parse_navigate_json (connection, link_encs, JNAV_INDEX, (int) i, @@ -565,9 +568,9 @@ handle_refresh_melt_json (struct MHD_Connection *connection, free_commit_coins (commit_coin, kappa, num_newcoins); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } - commit_coin[i][j].refresh_link = TALER_refresh_link_encrypted_decode (link_enc, - link_enc_size); - + rcc->refresh_link + = TALER_refresh_link_encrypted_decode (link_enc, + link_enc_size); GNUNET_CRYPTO_hash_context_read (hash_context, link_enc, link_enc_size); @@ -580,12 +583,14 @@ handle_refresh_melt_json (struct MHD_Connection *connection, sizeof (struct RefreshCommitLink)); for (j = 0; j < num_oldcoins; j++) { + struct RefreshCommitLink *rcl = &commit_link[i][j]; + res = GNUNET_MINT_parse_navigate_json (connection, transfer_pubs, JNAV_INDEX, (int) i, JNAV_INDEX, (int) j, JNAV_RET_DATA, - &commit_link[i][j].transfer_pub, + &rcl->transfer_pub, sizeof (struct TALER_TransferPublicKey)); if (GNUNET_OK != res) @@ -596,17 +601,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection, free_commit_links (commit_link, kappa, num_oldcoins); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } - - GNUNET_CRYPTO_hash_context_read (hash_context, - &commit_link[i][j].transfer_pub, - sizeof (struct TALER_TransferPublicKey)); - res = GNUNET_MINT_parse_navigate_json (connection, secret_encs, JNAV_INDEX, (int) i, JNAV_INDEX, (int) j, JNAV_RET_DATA, - &commit_link[i][j].shared_secret_enc, + &rcl->shared_secret_enc, sizeof (struct GNUNET_HashCode)); if (GNUNET_OK != res) @@ -619,12 +619,13 @@ handle_refresh_melt_json (struct MHD_Connection *connection, } GNUNET_CRYPTO_hash_context_read (hash_context, - &commit_link[i][j].shared_secret_enc, - sizeof (struct GNUNET_HashCode)); + rcl, + sizeof (struct RefreshCommitLink)); } - } - GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); + } + GNUNET_CRYPTO_hash_context_finish (hash_context, + &commit_hash); res = GNUNET_MINT_parse_navigate_json (connection, commit_signature, @@ -640,7 +641,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, for (i=0;iamount_with_fee; ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN); ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature)); - ms.melt_hash = melt->melt_hash; + ms.session_hash = melt->session_hash; TALER_amount_hton (&ms.amount_with_fee, &melt->amount_with_fee); ms.coin_pub = melt->coin.coin_pub; diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index 078238515..326737e61 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -236,18 +236,15 @@ struct Deposit struct RefreshSession { /** - * Signature over the commitments by the client, - * only valid if @e has_commit_sig is set. - * - * FIXME: The above comment is clearly confused. + * Signature over the commitments by the client. */ struct TALER_SessionSignature commit_sig; /** - * Hash over coins to melt and coins to create of the - * refresh session. + * Public key the client uses to sign messages in + * this exchange. */ - struct GNUNET_HashCode session_hash; + struct TALER_SessionPublicKey refresh_session_pub; /** * Signature over the melt by the client. @@ -296,9 +293,9 @@ struct RefreshMelt struct TALER_CoinSpendSignature coin_sig; /** - * Which melting operation should the coin become a part of. + * Hash of the refresh session this coin is melted into. */ - struct GNUNET_HashCode melt_hash; + struct GNUNET_HashCode session_hash; /** * How much value is being melted? This amount includes the fees, @@ -341,6 +338,8 @@ struct RefreshCommitCoin }; +GNUNET_NETWORK_STRUCT_BEGIN + /** * For each (old) coin being melted, we have a `struct * RefreshCommitLink` that allows the user to find the shared secret @@ -350,7 +349,9 @@ struct RefreshCommitCoin struct RefreshCommitLink { /** - * Transfer public key (FIXME: explain!) + * Transfer public key, used to decrypt the @e shared_secret_enc + * in combintation with the corresponding private key of the + * coin. */ struct TALER_TransferPublicKey transfer_pub; @@ -360,6 +361,9 @@ struct RefreshCommitLink struct TALER_EncryptedLinkSecret shared_secret_enc; }; +GNUNET_NETWORK_STRUCT_END + + /** * Linked list of refresh information linked to a coin. @@ -709,11 +713,11 @@ struct TALER_MINTDB_Plugin /** - * Lookup refresh session data under the given public key. + * Lookup refresh session data under the given @a session_hash. * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database handle to use - * @param refresh_session_pub public key to use for the lookup + * @param session_hash hash over the melt to use for the lookup * @param refresh_session[OUT] where to store the result * @return #GNUNET_YES on success, * #GNUNET_NO if not found, @@ -722,16 +726,16 @@ struct TALER_MINTDB_Plugin int (*get_refresh_session) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, struct RefreshSession *refresh_session); /** - * Store new refresh session data under the given public key. + * Store new refresh session data under the given @a session_hash. * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database handle to use - * @param refresh_session_pub public key to use to locate the session + * @param session_hash hash over the melt to use to locate the session * @param refresh_session session data to store * @return #GNUNET_YES on success, * #GNUNET_SYSERR on DB failure @@ -739,26 +743,24 @@ struct TALER_MINTDB_Plugin int (*create_refresh_session) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, const struct RefreshSession *refresh_session); - /** * Store the given /refresh/melt request in the database. * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection - * @param refresh_session session key of the melt operation * @param oldcoin_index index of the coin to store - * @param melt coin melt operation details to store + * @param melt coin melt operation details to store; includes + * the session hash of the melt * @return #GNUNET_OK on success * #GNUNET_SYSERR on internal error */ int (*insert_refresh_melt) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session, uint16_t oldcoin_index, const struct RefreshMelt *melt); @@ -768,7 +770,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection - * @param refresh_session session key of the melt operation + * @param session_hash hash to identify refresh session * @param oldcoin_index index of the coin to retrieve * @param melt melt data to fill in * @return #GNUNET_OK on success @@ -777,7 +779,7 @@ struct TALER_MINTDB_Plugin int (*get_refresh_melt) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session, + const struct GNUNET_HashCode *session_hash, uint16_t oldcoin_index, struct RefreshMelt *melt); @@ -788,7 +790,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection - * @param session_pub refresh session key + * @param session_hash hash to identify refresh session * @param num_newcoins number of coins to generate, size of the @a denom_pubs array * @param denom_pubs array denominations of the coins to create * @return #GNUNET_OK on success @@ -797,7 +799,7 @@ struct TALER_MINTDB_Plugin int (*insert_refresh_order) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, const struct TALER_DenominationPublicKey *denom_pubs); @@ -808,7 +810,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection - * @param session_pub refresh session key + * @param session_hash hash to identify refresh session * @param num_newcoins size of the @a denom_pubs array * @param denom_pubs[OUT] where to write @a num_newcoins denomination keys * @return #GNUNET_OK on success @@ -817,7 +819,7 @@ struct TALER_MINTDB_Plugin int (*get_refresh_order) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t num_newcoins, struct TALER_DenominationPublicKey *denom_pubs); @@ -828,7 +830,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use - * @param refresh_session_pub refresh session this commitment belongs to + * @param session_hash hash to identify refresh session * @param i set index (1st dimension), relating to kappa * @param num_newcoins coin index size of the @a commit_coins array * @param commit_coin array of coin commitments to store @@ -838,7 +840,7 @@ struct TALER_MINTDB_Plugin int (*insert_refresh_commit_coins) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_newcoins, const struct RefreshCommitCoin *commit_coins); @@ -850,7 +852,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use - * @param refresh_session_pub refresh session the commitment belongs to + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param num_coins size of the @a commit_coins array * @param commit_coin[OUT] array of coin commitments to return @@ -861,7 +863,7 @@ struct TALER_MINTDB_Plugin int (*get_refresh_commit_coins) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_coins, struct RefreshCommitCoin *commit_coins); @@ -873,8 +875,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with + * @param session_hash hash to identify refresh session * @param i set index (1st dimension), relating to kappa * @param num_links size of the @a commit_link array * @param commit_links array of link information to store @@ -883,7 +884,7 @@ struct TALER_MINTDB_Plugin int (*insert_refresh_commit_links) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_links, const struct RefreshCommitLink *commit_links); @@ -894,8 +895,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use - * @param refresh_session_pub public key of the refresh session this - * commitment belongs with + * @param session_hash hash to identify refresh session * @param i set index (1st dimension) * @param num_links size of the @links array to return * @param links[OUT] array link information to return @@ -906,7 +906,7 @@ struct TALER_MINTDB_Plugin int (*get_refresh_commit_links) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *refresh_session_pub, + const struct GNUNET_HashCode *session_hash, unsigned int i, unsigned int num_links, struct RefreshCommitLink *links); @@ -920,7 +920,7 @@ struct TALER_MINTDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection - * @param session_pub refresh session + * @param session_hash hash to identify refresh session * @param newcoin_index coin index * @param ev_sig coin signature * @return #GNUNET_OK on success @@ -928,7 +928,7 @@ struct TALER_MINTDB_Plugin int (*insert_refresh_collectable) (void *cls, struct TALER_MINTDB_Session *sesssion, - const struct TALER_SessionPublicKey *session_pub, + const struct GNUNET_HashCode *session_hash, uint16_t newcoin_index, const struct TALER_DenominationSignature *ev_sig); -- cgit v1.2.3 From f052af1e6bc9532c7a924ca3e8edba2e990b3b83 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 17:13:17 +0100 Subject: address #3731: no need for session public key or signature --- src/include/taler_crypto_lib.h | 39 --------------------- src/include/taler_signatures.h | 70 ++----------------------------------- src/mint/taler-mint-httpd_db.c | 9 ----- src/mint/taler-mint-httpd_db.h | 4 --- src/mint/taler-mint-httpd_refresh.c | 65 ++++------------------------------ src/mint/taler_mintdb_plugin.h | 15 -------- 6 files changed, 9 insertions(+), 193 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index a7e902777..3156e63ed 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -93,32 +93,6 @@ struct TALER_MerchantPrivateKey }; -/** - * Type of public keys used by clients to sign - * messages during a melting session. - */ -struct TALER_SessionPublicKey -{ - /** - * Taler uses EdDSA for melting session keys. - */ - struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; -}; - - -/** - * Type of public keys used by clients to sign - * messages during a melting session. - */ -struct TALER_SessionPrivateKey -{ - /** - * Taler uses EdDSA for melting session keys. - */ - struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; -}; - - /** * Type of transfer public keys used during refresh * operations. @@ -147,19 +121,6 @@ struct TALER_TransferPrivateKey }; -/** - * Type of signatures used by clients to sign - * messages during a melting session. - */ -struct TALER_SessionSignature -{ - /** - * Taler uses EdDSA for melting session keys. - */ - struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; -}; - - /** * Type of online public keys used by the mint to sign * messages. diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index fa713dc42..b8fe8a7b7 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -60,29 +60,17 @@ */ #define TALER_SIGNATURE_REFRESH_MELT_COIN 5 -/** - * Signature where the refresh session confirms - * the commits. - */ -#define TALER_SIGNATURE_REFRESH_MELT_SESSION 6 - /** * Signature where the mint (current signing key) * confirms the no-reveal index for cut-and-choose and * the validity of the melted coins. */ -#define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 7 - -/** - * Signature where coins confirm that they want - * to be melted into a certain session. - */ -#define TALER_SIGNATURE_REFRESH_MELT_CONFIRM 9 +#define TALER_SIGNATURE_REFRESH_MELT_RESPONSE 6 /** * Signature where the Mint confirms a deposit request. */ -#define TALER_SIGNATURE_MINT_DEPOSIT 10 +#define TALER_SIGNATURE_MINT_DEPOSIT 7 /***********************/ @@ -277,40 +265,6 @@ struct RefreshMeltCoinSignature }; -/** - * Message signed by a coin to indicate that the coin should - * be melted. - */ -struct RefreshMeltSessionSignature -{ - /** - * Purpose is #TALER_SIGNATURE_REFRESH_MELT_SESSION - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Which melting operation should the coin become a part of. - */ - struct GNUNET_HashCode melt_hash; - - /** - * Public key of the refresh session for which - * @e melt_client_signature must be a valid signature. - */ - struct TALER_SessionPublicKey session_key; - - /** - * What is the total value of the coins created during the - * refresh, including melting fee! - */ - struct TALER_AmountNBO amount_with_fee; - - /* FIXME: we should probably also include the value of - the melting fee here as well! */ - -}; - - /** * Format of the block signed by the Mint in response to a successful * "/refresh/melt" request. Hereby the mint affirms that all of the @@ -336,26 +290,6 @@ struct RefreshMeltResponseSignatureBody }; -/** - * Message signed by the client requesting the final - * result of the melting operation. - */ -struct RefreshMeltConfirmSignRequestBody -{ - /** - * Purpose is #TALER_SIGNATURE_REFRESH_MELT_CONFIRM. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - // FIXME: We probably need more info in here... - - /** - * Public key the client uses for this session. - */ - struct TALER_SessionPublicKey session_pub; -}; - - /** * Information about a signing key of the mint. Signing keys are used * to sign mint messages other than coins, i.e. to confirm that a diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 7592403da..c18936e1f 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -494,7 +494,6 @@ refresh_accept_melts (struct MHD_Connection *connection, struct TALER_MINTDB_Session *session, const struct MintKeyState *key_state, const struct GNUNET_HashCode *session_hash, - const struct TALER_SessionPublicKey *session_pub, const struct TALER_CoinPublicInfo *coin_public_info, const struct MeltDetails *coin_details, uint16_t oldcoin_index) @@ -587,9 +586,6 @@ refresh_accept_melts (struct MHD_Connection *connection, * * @param connection the MHD connection to handle * @param session_hash hash code of the session the coins are melted into - * @param refresh_session_pub public key of the refresh session - * @param client_signature signature of the client (matching @a refresh_session_pub) - * over the melting request * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @commit_coin array * @param denum_pubs public keys of the coins we want to withdraw in the end * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details, size of y-dimension of @commit_link array @@ -606,8 +602,6 @@ refresh_accept_melts (struct MHD_Connection *connection, int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_HashCode *session_hash, - const struct TALER_SessionPublicKey *refresh_session_pub, - const struct TALER_SessionSignature *client_signature, unsigned int num_new_denoms, const struct TALER_DenominationPublicKey *denom_pubs, unsigned int coin_count, @@ -665,7 +659,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, session, key_state, session_hash, - refresh_session_pub, &coin_public_infos[i], &coin_melt_details[i], i))) @@ -724,8 +717,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, /* store 'global' session data */ - refresh_session.melt_sig = *client_signature; - refresh_session.refresh_session_pub = *refresh_session_pub; refresh_session.num_oldcoins = coin_count; refresh_session.num_newcoins = num_new_denoms; refresh_session.kappa = KAPPA; // FIXME... (#3711) diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index edf8248c7..ed96bbd4b 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -108,8 +108,6 @@ struct MeltDetails * * @param connection the MHD connection to handle * @param session_hash hash code of the session the coins are melted into - * @param client_signature signature of the client (matching @a refresh_session_pub) - * over the melting request * @param num_new_denoms number of entries in @a denom_pubs, size of y-dimension of @commit_coin array * @param denum_pubs array of public denomination keys for the refresh (?) * @param coin_count number of entries in @a coin_public_infos and @ a coin_melt_details, size of y-dimension of @commit_link array @@ -126,8 +124,6 @@ struct MeltDetails int TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, const struct GNUNET_HashCode *session_hash, - const struct TALER_SessionPublicKey *refresh_session_pub, - const struct TALER_SessionSignature *client_signature, unsigned int num_new_denoms, const struct TALER_DenominationPublicKey *denom_pubs, unsigned int coin_count, diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c index 775ffd4ce..6575f02c9 100644 --- a/src/mint/taler-mint-httpd_refresh.c +++ b/src/mint/taler-mint-httpd_refresh.c @@ -40,13 +40,12 @@ * and then hand things of to execute the melt operation. * * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the melt operation * @param num_new_denoms number of coins to be created, size of y-dimension of @commit_link array * @param denom_pubs array of @a num_new_denoms keys * @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array * @param coin_public_infos array with @a coin_count entries about the coins * @param coin_melt_details array with @a coin_count entries with melting details - * @param commit_hash hash over the data that the client commits to + * @param session_hash hash over the data that the client commits to * @param commit_client_sig signature of the client over this commitment * @param kappa size of x-dimension of @commit_coin and @commit_link arrays * @param commit_coin 2d array of coin commitments (what the mint is to sign @@ -58,21 +57,18 @@ */ static int handle_refresh_melt_binary (struct MHD_Connection *connection, - const struct TALER_SessionPublicKey *refresh_session_pub, unsigned int num_new_denoms, const struct TALER_DenominationPublicKey *denom_pubs, unsigned int coin_count, struct TALER_CoinPublicInfo *coin_public_infos, const struct MeltDetails *coin_melt_details, - const struct GNUNET_HashCode *commit_hash, - const struct TALER_SessionSignature *commit_client_sig, + const struct GNUNET_HashCode *session_hash, unsigned int kappa, struct RefreshCommitCoin *const* commit_coin, struct RefreshCommitLink *const* commit_link) { unsigned int i; - struct RefreshMeltSessionSignature body; struct MintKeyState *key_state; struct TALER_MINT_DenomKeyIssue *dki; struct TALER_Amount cost; @@ -83,27 +79,6 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, struct TALER_Amount fee_melt; struct TALER_Amount total_melt; - /* check that signature from the session public key is ok */ - body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION); - body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature)); - body.melt_hash = *commit_hash; - TALER_amount_hton (&body.amount_with_fee, - &coin_melt_details->melt_amount_with_fee); - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION, - &body.purpose, - &commit_client_sig->eddsa_signature, - &refresh_session_pub->eddsa_pub)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "signature invalid (did not verify)\n"); - return TALER_MINT_reply_json_pack (connection, - MHD_HTTP_UNAUTHORIZED, - "{s:s}", - "error", - "invalid signature (verification)"); - } GNUNET_assert (GNUNET_OK == TALER_amount_get_zero (MINT_CURRENCY, &total_cost)); @@ -174,9 +149,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, "error", "value mismatch"); } return TALER_MINT_db_execute_refresh_melt (connection, - commit_hash, - refresh_session_pub, - commit_client_sig, + session_hash, num_new_denoms, denom_pubs, coin_count, @@ -382,7 +355,6 @@ free_commit_links (struct RefreshCommitLink **commit_link, * #handle_refresh_melt_binary(). * * @param connection the MHD connection to handle - * @param refresh_session_pub public key of the melt operation * @param new_denoms array of denomination keys * @param melt_coins array of coins to melt * @param melt_sig_json signature affirming the melt operation @@ -398,7 +370,6 @@ free_commit_links (struct RefreshCommitLink **commit_link, */ static int handle_refresh_melt_json (struct MHD_Connection *connection, - const struct TALER_SessionPublicKey *refresh_session_pub, const json_t *new_denoms, const json_t *melt_coins, const json_t *melt_sig_json, @@ -420,19 +391,14 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct TALER_CoinPublicInfo *coin_public_infos; struct MeltDetails *coin_melt_details; unsigned int coin_count; - struct GNUNET_HashCode commit_hash; + struct GNUNET_HashCode session_hash; struct GNUNET_HashContext *hash_context; struct RefreshCommitCoin *commit_coin[kappa]; struct RefreshCommitLink *commit_link[kappa]; - const struct TALER_SessionSignature commit_client_sig; /* For the signature check, we hash most of the inputs together (except for the signatures on the coins). */ hash_context = GNUNET_CRYPTO_hash_context_start (); - GNUNET_CRYPTO_hash_context_read (hash_context, - refresh_session_pub, - sizeof (struct TALER_SessionPublicKey)); - num_new_denoms = json_array_size (new_denoms); denom_pubs = GNUNET_malloc (num_new_denoms * sizeof (struct TALER_DenominationPublicKey)); @@ -625,25 +591,13 @@ handle_refresh_melt_json (struct MHD_Connection *connection, } GNUNET_CRYPTO_hash_context_finish (hash_context, - &commit_hash); - - res = GNUNET_MINT_parse_navigate_json (connection, - commit_signature, - JNAV_FIELD, - "sig", - JNAV_RET_DATA, - &commit_client_sig, - sizeof (struct TALER_SessionSignature)); - - if (GNUNET_OK != res) - return (GNUNET_NO == res) ? MHD_YES : MHD_NO; - + &session_hash); for (i=0;i Date: Tue, 24 Mar 2015 17:25:00 +0100 Subject: make kappa global fixed constant, not something to be negotiated, KISS --- src/include/taler_signatures.h | 11 ++++++ src/mint/plugin_mintdb_postgres.c | 4 +- src/mint/taler-mint-httpd.h | 6 --- src/mint/taler-mint-httpd_db.c | 26 ++++++------- src/mint/taler-mint-httpd_db.h | 8 +--- src/mint/taler-mint-httpd_refresh.c | 78 ++++++++++++++++++------------------- src/mint/taler_mintdb_plugin.h | 15 ++----- 7 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index b8fe8a7b7..3ad97a577 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -30,6 +30,17 @@ #include "taler_util.h" +/** + * Cut-and-choose size for refreshing. Client looses the gamble (of + * unaccountable transfers) with probability 1/KAPPA. Refresh cost + * increases linearly with KAPPA, and 3 is sufficient up to a + * income/sales tax of 66% of total transaction value. As there is + * no good reason to change this security parameter, we declare it + * fixed and part of the protocol. + */ +#define KAPPA 3 + + /** * Purpose for signing public keys signed * by the mint master key. diff --git a/src/mint/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c index 1c6851d86..5a1ff8c0c 100644 --- a/src/mint/plugin_mintdb_postgres.c +++ b/src/mint/plugin_mintdb_postgres.c @@ -247,7 +247,7 @@ postgres_create_tables (void *cls, // index of the old coin in the customer's request ",oldcoin_index INT2 NOT NULL" // index for cut and choose, - // ranges from 0 to kappa-1 + // ranges from 0 to #KAPPA-1 ",cnc_index INT2 NOT NULL" ")"); SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_coin" @@ -1486,7 +1486,6 @@ postgres_get_refresh_session (void *cls, struct TALER_DB_ResultSpec rs[] = { TALER_DB_RESULT_SPEC("num_oldcoins", &refresh_session->num_oldcoins), TALER_DB_RESULT_SPEC("num_newcoins", &refresh_session->num_newcoins), - TALER_DB_RESULT_SPEC("kappa", &refresh_session->kappa), TALER_DB_RESULT_SPEC("noreveal_index", &refresh_session->noreveal_index), TALER_DB_RESULT_SPEC_END }; @@ -1502,7 +1501,6 @@ postgres_get_refresh_session (void *cls, refresh_session->num_oldcoins = ntohs (refresh_session->num_oldcoins); refresh_session->num_newcoins = ntohs (refresh_session->num_newcoins); - refresh_session->kappa = ntohs (refresh_session->kappa); refresh_session->noreveal_index = ntohs (refresh_session->noreveal_index); PQclear (result); diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index 36d150bbc..50b745703 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -25,12 +25,6 @@ #include -/** - * Cut-and-choose size for refreshing. - * FIXME: maybe make it a config option? - */ -#define KAPPA 3 - /** * For now, we just do EUR. Should become configurable * in the future! diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index c18936e1f..17f44c9c9 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -591,12 +591,13 @@ refresh_accept_melts (struct MHD_Connection *connection, * @param coin_count number of entries in @a coin_public_infos and @a coin_melt_details, size of y-dimension of @commit_link array * @param coin_public_infos information about the coins to melt * @param coin_melt_details signatures and (residual) value of the respective coin should be melted - * @param kappa size of x-dimension of @commit_coin and @commit_link arrays * @param commit_coin 2d array of coin commitments (what the mint is to sign - * once the "/refres/reveal" of cut and choose is done) + * once the "/refres/reveal" of cut and choose is done), + * x-dimension must be #KAPPA * @param commit_link 2d array of coin link commitments (what the mint is * to return via "/refresh/link" to enable linkage in the * future) + * x-dimension must be #KAPPA * @return MHD result code */ int @@ -607,7 +608,6 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, unsigned int coin_count, const struct TALER_CoinPublicInfo *coin_public_infos, const struct MeltDetails *coin_melt_details, - unsigned int kappa, struct RefreshCommitCoin *const* commit_coin, struct RefreshCommitLink *const* commit_link) { @@ -684,7 +684,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } - for (i = 0; i < kappa; i++) + for (i = 0; i < KAPPA; i++) { if (GNUNET_OK != plugin->insert_refresh_commit_coins (plugin->cls, @@ -699,7 +699,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, return TALER_MINT_reply_internal_db_error (connection); } } - for (i = 0; i < kappa; i++) + for (i = 0; i < KAPPA; i++) { if (GNUNET_OK != plugin->insert_refresh_commit_links (plugin->cls, @@ -719,10 +719,9 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, /* store 'global' session data */ refresh_session.num_oldcoins = coin_count; refresh_session.num_newcoins = num_new_denoms; - refresh_session.kappa = KAPPA; // FIXME... (#3711) refresh_session.noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, - refresh_session.kappa); + KAPPA); if (GNUNET_OK != (res = plugin->create_refresh_session (plugin->cls, session, @@ -753,7 +752,7 @@ TALER_MINT_db_execute_refresh_melt (struct MHD_Connection *connection, * Check if the given @a transfer_privs correspond to an honest * commitment for the given session. * Checks that the transfer private keys match their commitments. - * Then derives the shared secret for each kappa, and check that they match. + * Then derives the shared secret for each #KAPPA, and check that they match. * * @param connection the MHD connection to handle * @param session database connection to use @@ -946,7 +945,7 @@ check_commitment (struct MHD_Connection *connection, buf_len)) ) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "blind envelope does not match for kappa=%u, old=%d\n", + "blind envelope does not match for k=%u, old=%d\n", off, (int) j); /* FIXME: return more specific error with original signature (#3712) */ @@ -1025,22 +1024,21 @@ refresh_mint_coin (struct MHD_Connection *connection, /** * Execute a "/refresh/reveal". The client is revealing to us the - * transfer keys for @a kappa-1 sets of coins. Verify that the + * transfer keys for @a #KAPPA-1 sets of coins. Verify that the * revealed transfer keys would allow linkage to the blinded coins, * and if so, return the signed coins for corresponding to the set of * coins that was not chosen. * * @param connection the MHD connection to handle * @param session_hash hash identifying the refresh session - * @param kappa size of x-dimension of @transfer_privs array plus one (!) * @param num_oldcoins size of y-dimension of @transfer_privs array - * @param transfer_pubs array with the revealed transfer keys + * @param transfer_pubs array with the revealed transfer keys, + * x-dimension must be #KAPPA - 1 * @return MHD result code */ int TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, const struct GNUNET_HashCode *session_hash, - unsigned int kappa, unsigned int num_oldcoins, struct TALER_TransferPrivateKey **transfer_privs) { @@ -1112,7 +1110,7 @@ TALER_MINT_db_execute_refresh_reveal (struct MHD_Connection *connection, off = 0; - for (i=0;irefresh_link @@ -543,7 +542,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, } } - for (i = 0; i < kappa; i++) + for (i = 0; i < KAPPA; i++) { commit_link[i] = GNUNET_malloc (num_oldcoins * sizeof (struct RefreshCommitLink)); @@ -563,8 +562,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection, { GNUNET_break (GNUNET_SYSERR != res); GNUNET_CRYPTO_hash_context_abort (hash_context); - free_commit_coins (commit_coin, kappa, num_newcoins); - free_commit_links (commit_link, kappa, num_oldcoins); + free_commit_coins (commit_coin, + KAPPA, + num_newcoins); + free_commit_links (commit_link, + KAPPA, + num_oldcoins); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } res = GNUNET_MINT_parse_navigate_json (connection, @@ -579,8 +582,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection, { GNUNET_break (GNUNET_SYSERR != res); GNUNET_CRYPTO_hash_context_abort (hash_context); - free_commit_coins (commit_coin, kappa, num_newcoins); - free_commit_links (commit_link, kappa, num_oldcoins); + free_commit_coins (commit_coin, + KAPPA, + num_newcoins); + free_commit_links (commit_link, + KAPPA, + num_oldcoins); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } @@ -615,12 +622,15 @@ handle_refresh_melt_json (struct MHD_Connection *connection, coin_public_infos, coin_melt_details, &session_hash, - kappa, commit_coin, commit_link); cleanup: - free_commit_coins (commit_coin, kappa, num_newcoins); - free_commit_links (commit_link, kappa, num_oldcoins); + free_commit_coins (commit_coin, + KAPPA, + num_newcoins); + free_commit_links (commit_link, + KAPPA, + num_oldcoins); for (j=0;j kappa) || (kappa > 32) ) + if (KAPPA != json_array_size (coin_evs)) { GNUNET_break_op (0); TALER_MINT_release_parsed_data (spec); return TALER_MINT_reply_arg_invalid (connection, "coin_evs"); } - if (json_array_size (transfer_pubs) != kappa) + if (KAPPA != json_array_size (transfer_pubs)) { GNUNET_break_op (0); TALER_MINT_release_parsed_data (spec); @@ -741,7 +749,6 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, melt_coins, melt_sig_json, commit_sig_json, - kappa, num_oldcoins, transfer_pubs, secret_encs, @@ -763,7 +770,6 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, * * @param connection the MHD connection to handle * @param session_hash hash identifying the melting session - * @param kappa length of the 1st dimension of @a transfer_privs array PLUS ONE * @param num_oldcoins length of the 2nd dimension of @a transfer_privs array * @param tp_json private transfer keys in JSON format * @return MHD result code @@ -771,20 +777,19 @@ TALER_MINT_handler_refresh_melt (struct RequestHandler *rh, static int handle_refresh_reveal_json (struct MHD_Connection *connection, const struct GNUNET_HashCode *session_hash, - unsigned int kappa, unsigned int num_oldcoins, const json_t *tp_json) { - struct TALER_TransferPrivateKey *transfer_privs[kappa - 1]; + struct TALER_TransferPrivateKey *transfer_privs[KAPPA - 1]; unsigned int i; unsigned int j; int res; - for (i = 0; i < kappa - 1; i++) + for (i = 0; i < KAPPA - 1; i++) transfer_privs[i] = GNUNET_malloc (num_oldcoins * sizeof (struct TALER_TransferPrivateKey)); res = GNUNET_OK; - for (i = 0; i < kappa - 1; i++) + for (i = 0; i < KAPPA - 1; i++) { if (GNUNET_OK != res) break; @@ -806,10 +811,9 @@ handle_refresh_reveal_json (struct MHD_Connection *connection, else res = TALER_MINT_db_execute_refresh_reveal (connection, session_hash, - kappa, num_oldcoins, transfer_privs); - for (i = 0; i < kappa - 1; i++) + for (i = 0; i < KAPPA - 1; i++) GNUNET_free (transfer_privs[i]); return res; } @@ -840,7 +844,6 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, { struct GNUNET_HashCode session_hash; int res; - unsigned int kappa; unsigned int num_oldcoins; json_t *reveal_detail; json_t *root; @@ -869,15 +872,13 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; /* Determine dimensionality of the request (kappa and #old coins) */ - kappa = json_array_size (transfer_privs) + 1; - if ( (2 > kappa) || (kappa > 31) ) + if (KAPPA != json_array_size (transfer_privs) + 1) { TALER_MINT_release_parsed_data (spec); return TALER_MINT_reply_arg_invalid (connection, "transfer_privs"); } /* Note we do +1 as 1 row (cut-and-choose!) is missing! */ - kappa++; res = GNUNET_MINT_parse_navigate_json (connection, transfer_privs, JNAV_INDEX, 0, @@ -892,7 +893,6 @@ TALER_MINT_handler_refresh_reveal (struct RequestHandler *rh, num_oldcoins = json_array_size (reveal_detail); res = handle_refresh_reveal_json (connection, &session_hash, - kappa, num_oldcoins, transfer_privs); TALER_MINT_release_parsed_data (spec); diff --git a/src/mint/taler_mintdb_plugin.h b/src/mint/taler_mintdb_plugin.h index d461413f1..08a73479d 100644 --- a/src/mint/taler_mintdb_plugin.h +++ b/src/mint/taler_mintdb_plugin.h @@ -247,14 +247,7 @@ struct RefreshSession uint16_t num_newcoins; /** - * Number of parallel operations we perform for the cut and choose. - * (must be greater or equal to three for security). 0 if not yet - * known. - */ - uint16_t kappa; - - /** - * Index (smaller @e kappa) which the mint has chosen to not + * Index (smaller #KAPPA) which the mint has chosen to not * have revealed during cut and choose. */ uint16_t noreveal_index; @@ -297,7 +290,7 @@ struct RefreshMelt /** * We have as many `struct RefreshCommitCoin` as there are new - * coins being created by the refresh (for each of the kappa + * coins being created by the refresh (for each of the #KAPPA * sets). These are the coins we ask the mint to sign if the * respective set is selected. */ @@ -816,7 +809,7 @@ struct TALER_MINTDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use * @param session_hash hash to identify refresh session - * @param i set index (1st dimension), relating to kappa + * @param i set index (1st dimension), relating to #KAPPA * @param num_newcoins coin index size of the @a commit_coins array * @param commit_coin array of coin commitments to store * @return #GNUNET_OK on success @@ -861,7 +854,7 @@ struct TALER_MINTDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @param sesssion database connection to use * @param session_hash hash to identify refresh session - * @param i set index (1st dimension), relating to kappa + * @param i set index (1st dimension), relating to #KAPPA * @param num_links size of the @a commit_link array * @param commit_links array of link information to store * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success -- cgit v1.2.3 From 324bf3f980542cb9f209ee7edc6f142c5c34e5a2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Tue, 24 Mar 2015 17:53:13 +0100 Subject: fix #3484: sign over full key set as well --- src/include/taler_signatures.h | 32 +++++++++++++++++++++++++++++++- src/mint/taler-mint-httpd_keystate.c | 21 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 3ad97a577..007a309f3 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -83,6 +83,11 @@ */ #define TALER_SIGNATURE_MINT_DEPOSIT 7 +/** + * Signature where the Mint confirms the full /keys response set. + */ +#define TALER_SIGNATURE_KEYS_SET 8 + /***********************/ /* Merchant signatures */ @@ -345,6 +350,31 @@ struct TALER_MINT_SignKeyIssue }; +/** + * Signature made by the mint over the full set of keys, used + * to detect cheating mints that give out different sets to + * different users. + */ +struct TALER_MINT_KeySetSignature +{ + + /** + * Purpose is #TALER_SIGNATURE_KEYS_SET + */ + struct GNUNET_CRYPTO_EccSignaturePurpose purpose; + + /** + * Time of the key set issue. + */ + struct GNUNET_TIME_AbsoluteNBO list_issue_date; + + /** + * Hash over the "inner" JSON with the key set. + */ + struct GNUNET_HashCode hc; +}; + + /** * Information about a denomination key. Denomination keys * are used to sign coins of a certain value into existence. @@ -358,7 +388,7 @@ struct TALER_MINT_DenomKeyIssue struct TALER_MasterSignature signature; /** - * Purpose ist #TALER_SIGNATURE_MASTER_DENOM. + * Purpose is #TALER_SIGNATURE_MASTER_DENOM. */ struct GNUNET_CRYPTO_EccSignaturePurpose purpose; diff --git a/src/mint/taler-mint-httpd_keystate.c b/src/mint/taler-mint-httpd_keystate.c index b795323ee..c29c5c516 100644 --- a/src/mint/taler-mint-httpd_keystate.c +++ b/src/mint/taler-mint-httpd_keystate.c @@ -378,6 +378,9 @@ TALER_MINT_key_state_acquire (void) struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get (); struct MintKeyState *key_state; json_t *keys; + char *inner; + struct TALER_MINT_KeySetSignature ks; + struct TALER_MintSignature sig; GNUNET_assert (0 == pthread_mutex_lock (&internal_key_state_mutex)); if (internal_key_state->next_reload.abs_value_us <= now.abs_value_us) @@ -413,8 +416,24 @@ TALER_MINT_key_state_acquire (void) "signkeys", key_state->sign_keys_array, "denoms", key_state->denom_keys_array, "list_issue_date", TALER_JSON_from_abs (key_state->reload_time)); + inner = json_dumps (keys, + JSON_INDENT(2)); + ks.purpose.size = htonl (sizeof (ks)); + ks.purpose.purpose = htonl (TALER_SIGNATURE_KEYS_SET); + ks.list_issue_date = GNUNET_TIME_absolute_hton (key_state->reload_time); + GNUNET_CRYPTO_hash (inner, + strlen (inner), + &ks.hc); + GNUNET_free (inner); + TALER_MINT_keys_sign (&ks.purpose, + &sig); + keys = json_pack ("{s:o, s:o}", + "keys", keys, + "eddsa-signature", TALER_JSON_from_eddsa_sig (&ks.purpose, + &sig.eddsa_signature)); key_state->keys_json = json_dumps (keys, - JSON_INDENT(2)); + JSON_INDENT (2)); + json_decref (keys); internal_key_state = key_state; } key_state = internal_key_state; -- cgit v1.2.3