diff options
Diffstat (limited to 'src/mint')
-rw-r--r-- | src/mint/Makefile.am | 128 | ||||
-rw-r--r-- | src/mint/key_io.c | 347 | ||||
-rw-r--r-- | src/mint/key_io.h | 187 | ||||
-rw-r--r-- | src/mint/plugin.c | 147 | ||||
-rw-r--r-- | src/mint/plugin.h | 50 | ||||
-rw-r--r-- | src/mint/plugin_mintdb_common.c | 118 | ||||
-rw-r--r-- | src/mint/plugin_mintdb_postgres.c | 2357 | ||||
-rw-r--r-- | src/mint/taler-mint-dbinit.c | 101 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.c | 12 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd.h | 5 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.c | 128 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_db.h | 1 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_deposit.c | 1 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_keystate.h | 2 | ||||
-rw-r--r-- | src/mint/taler-mint-httpd_mhd.c | 1 | ||||
-rw-r--r-- | src/mint/taler-mint-keycheck.c | 227 | ||||
-rw-r--r-- | src/mint/taler-mint-keyup.c | 954 | ||||
-rw-r--r-- | src/mint/taler-mint-reservemod.c | 305 | ||||
-rw-r--r-- | src/mint/test_mint_common.c | 86 | ||||
-rw-r--r-- | src/mint/test_mint_db.c | 393 | ||||
-rw-r--r-- | src/mint/test_mint_deposits.c | 142 |
21 files changed, 81 insertions, 5611 deletions
diff --git a/src/mint/Makefile.am b/src/mint/Makefile.am index f8e5696ff..538020e9e 100644 --- a/src/mint/Makefile.am +++ b/src/mint/Makefile.am @@ -1,82 +1,8 @@ # 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 - -EXTRA_DIST = plugin_mintdb_common.c - -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 - -libtalermint_common_la_SOURCES = \ - key_io.c key_io.h \ - plugin.c plugin.h - -libtalermint_common_la_LIBADD = \ - $(top_builddir)/src/util/libtalerutil.la \ - -lgnunetutil - -libtalermint_common_la_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) \ - -version-info 0:0:0 \ - -no-undefined - +AM_CPPFLAGS = -I$(top_srcdir)/src/include bin_PROGRAMS = \ - taler-mint-keyup \ - taler-mint-keycheck \ - taler-mint-reservemod \ - taler-mint-httpd \ - taler-mint-dbinit - -taler_mint_keyup_SOURCES = \ - taler-mint-keyup.c - -taler_mint_keyup_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/util/libtalerutil.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/mint/libtalermint_common.la \ - -lpq \ - -lgnunetutil -taler_mint_keyup_LDFLAGS = $(POSTGRESQL_LDFLAGS) - - -taler_mint_keycheck_SOURCES = \ - taler-mint-keycheck.c - -taler_mint_keycheck_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/util/libtalerutil.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/mint/libtalermint_common.la \ - -lgnunetutil \ - -lpq -taler_mint_keycheck_LDFLAGS = $(POSTGRESQL_LDFLAGS) - -taler_mint_reservemod_SOURCES = \ - taler-mint-reservemod.c -taler_mint_reservemod_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/util/libtalerutil.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/mint/libtalermint_common.la \ - -lpq \ - -lgnunetutil -taler_mint_reservemod_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) + taler-mint-httpd taler_mint_httpd_SOURCES = \ taler-mint-httpd.c \ @@ -92,56 +18,8 @@ taler_mint_httpd_LDADD = \ $(LIBGCRYPT_LIBS) \ $(top_builddir)/src/util/libtalerutil.la \ $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/mint/libtalermint_common.la \ - -lpq \ + $(top_builddir)/src/mintdb/libtalermintdb.la \ -lmicrohttpd \ -ljansson \ -lgnunetutil \ -lpthread -taler_mint_httpd_LDFLAGS = \ - $(POSTGRESQL_LDFLAGS) - - -taler_mint_dbinit_SOURCES = \ - taler-mint-dbinit.c -taler_mint_dbinit_LDADD = \ - $(LIBGCRYPT_LIBS) \ - $(top_builddir)/src/util/libtalerutil.la \ - $(top_builddir)/src/pq/libtalerpq.la \ - $(top_builddir)/src/mint/libtalermint_common.la \ - -lpq \ - -lgnunetutil -taler_mint_dbinit_LDFLAGS = $(POSTGRESQL_LDFLAGS) - -check_PROGRAMS = \ - test-mint-deposits \ - test-mint-common \ - test-mint-db-postgres - -test_mint_deposits_SOURCES = \ - test_mint_deposits.c -test_mint_deposits_LDADD = \ - libtalermint_common.la \ - $(top_srcdir)/src/util/libtalerutil.la \ - $(top_srcdir)/src/pq/libtalerpq.la \ - -lgnunetutil \ - -ljansson \ - -lpq - -test_mint_common_SOURCES = \ - test_mint_common.c -test_mint_common_LDADD = \ - libtalermint_common.la \ - $(top_srcdir)/src/util/libtalerutil.la \ - $(top_srcdir)/src/pq/libtalerpq.la \ - -lgnunetutil - -test_mint_db_postgres_SOURCES = \ - test_mint_db.c -test_mint_db_postgres_LDADD = \ - libtalermint_common.la \ - $(top_srcdir)/src/util/libtalerutil.la \ - $(top_srcdir)/src/pq/libtalerpq.la \ - -lgnunetutil -ljansson -EXTRA_test_mint_db_postgres_DEPENDENCIES = \ - libtaler_plugin_mintdb_postgres.la diff --git a/src/mint/key_io.c b/src/mint/key_io.c deleted file mode 100644 index 02d888d5d..000000000 --- a/src/mint/key_io.c +++ /dev/null @@ -1,347 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/key_io.c - * @brief I/O operations for the Mint's private keys - * @author Florian Dold - * @author Benedikt Mueller - * @author Sree Harsha Totakura - * @author Christian Grothoff - */ -#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 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, - const char *filename) -{ - struct SignkeysIterateContext *skc = cls; - ssize_t nread; - struct TALER_MintSigningKeyValidityPSPriv issue; - - nread = GNUNET_DISK_fn_read (filename, - &issue, - sizeof (struct TALER_MintSigningKeyValidityPSPriv)); - if (nread != sizeof (struct TALER_MintSigningKeyValidityPSPriv)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid signkey file `%s': wrong size\n", - filename); - return GNUNET_OK; - } - return skc->it (skc->it_cls, - filename, - &issue); -} - - -/** - * 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, - void *it_cls) -{ - char *signkey_dir; - struct SignkeysIterateContext skc; - int ret; - - GNUNET_asprintf (&signkey_dir, - "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, - mint_base_dir); - skc.it = it; - skc.it_cls = it_cls; - ret = GNUNET_DISK_directory_scan (signkey_dir, - &signkeys_iterate_dir_iter, - &skc); - GNUNET_free (signkey_dir); - return ret; -} - - -/** - * Import a denomination key from the given file. - * - * @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 - */ -int -TALER_MINT_read_denom_key (const char *filename, - struct TALER_DenominationKeyIssueInformation *dki) -{ - uint64_t size; - size_t offset; - void *data; - struct GNUNET_CRYPTO_rsa_PrivateKey *priv; - - if (GNUNET_OK != GNUNET_DISK_file_size (filename, - &size, - GNUNET_YES, - GNUNET_YES)) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Skipping inaccessable denomination key file `%s'\n", - filename); - return GNUNET_SYSERR; - } - offset = sizeof (struct TALER_DenominationKeyValidityPS); - if (size <= offset) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - data = GNUNET_malloc (size); - 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.rsa_private_key = priv; - dki->denom_pub.rsa_public_key - = 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. - * - * @param filename the file where to write the denomination key - * @param dki the denomination key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_MINT_write_denom_key (const char *filename, - const struct TALER_DenominationKeyIssueInformation *dki) -{ - char *priv_enc; - size_t priv_enc_size; - struct GNUNET_DISK_FileHandle *fh; - ssize_t wrote; - size_t wsize; - int ret; - - fh = NULL; - 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, - 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_DenominationKeyValidityPS); - 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))) - goto cleanup; - if (wrote != priv_enc_size) - goto cleanup; - ret = GNUNET_OK; - cleanup: - GNUNET_free_non_null (priv_enc); - if (NULL != fh) - (void) GNUNET_DISK_file_close (fh); - return ret; -} - - -/** - * 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 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, - const char *filename) -{ - struct DenomkeysIterateContext *dic = cls; - struct TALER_DenominationKeyIssueInformation issue; - - if (GNUNET_OK != - TALER_MINT_read_denom_key (filename, - &issue)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Invalid denomkey file: '%s'\n", - filename); - return GNUNET_OK; - } - return dic->it (dic->it_cls, - dic->alias, - &issue); -} - - -/** - * Function called on each subdirectory in the #DIR_DENOMKEYS. Will - * call the #denomkeys_iterate_keydir_iter() on each file in the - * subdirectory. - * - * @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, - const char *filename) -{ - struct DenomkeysIterateContext *dic = cls; - - dic->alias = GNUNET_STRINGS_get_short_name (filename); - if (0 > GNUNET_DISK_directory_scan (filename, - &denomkeys_iterate_keydir_iter, - dic)) - return GNUNET_SYSERR; - return GNUNET_OK; -} - - -/** - * 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, - void *it_cls) -{ - char *dir; - struct DenomkeysIterateContext dic; - int ret; - - GNUNET_asprintf (&dir, - "%s" DIR_SEPARATOR_STR DIR_DENOMKEYS, - mint_base_dir); - dic.it = it; - dic.it_cls = it_cls; - ret = GNUNET_DISK_directory_scan (dir, - &denomkeys_iterate_topdir_iter, - &dic); - GNUNET_free (dir); - return ret; -} - - -/* end of key_io.c */ diff --git a/src/mint/key_io.h b/src/mint/key_io.h deleted file mode 100644 index 0ff968976..000000000 --- a/src/mint/key_io.h +++ /dev/null @@ -1,187 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/key_io.h - * @brief IO operations for the mint's private keys - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#ifndef KEY_IO_H -#define KEY_IO_H - -#include <gnunet/gnunet_util_lib.h> -#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" - - -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. - * Includes the private key followed by the public information about - * the signing key. - */ -struct TALER_MintSigningKeyValidityPSPriv -{ - /** - * Private key part of the mint's signing key. - */ - struct TALER_MintPrivateKeyP signkey_priv; - - /** - * Public information about a mint signing key. - */ - struct TALER_MintSigningKeyValidityPS issue; -}; - - -GNUNET_NETWORK_STRUCT_END - - -/** - * All information about a denomination key (which is used to - * sign coins into existence). - */ -struct TALER_DenominationKeyIssueInformation -{ - /** - * 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 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 TALER_DenominationPublicKey denom_pub; - - /** - * Signed public information about a denomination key. - */ - struct TALER_DenominationKeyValidityPS issue; -}; - - -/** - * Iterator over signing keys. - * - * @param cls closure - * @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! - */ -typedef int -(*TALER_MINT_SignkeyIterator)(void *cls, - const char *filename, - const struct TALER_MintSigningKeyValidityPSPriv *ski); - - -/** - * Iterator over denomination keys. - * - * @param cls closure - * @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! - */ -typedef int -(*TALER_MINT_DenomkeyIterator)(void *cls, - const char *alias, - const struct TALER_DenominationKeyIssueInformation *dki); - - - -/** - * 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, - void *it_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, - void *it_cls); - - -/** - * Exports a denomination key to the given file. - * - * @param filename the file where to write the denomination key - * @param dki the denomination key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_MINT_write_denom_key (const char *filename, - const struct TALER_DenominationKeyIssueInformation *dki); - - -/** - * Import a denomination key from the given file. - * - * @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 - */ -int -TALER_MINT_read_denom_key (const char *filename, - struct TALER_DenominationKeyIssueInformation *dki); - - -#endif diff --git a/src/mint/plugin.c b/src/mint/plugin.c deleted file mode 100644 index 147d4c4c7..000000000 --- a/src/mint/plugin.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/plugin.c - * @brief Logic to load database plugin - * @author Christian Grothoff - */ -#include "platform.h" -#include "plugin.h" -#include <ltdl.h> - - -/** - * 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 (const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - char *plugin_name; - char *lib_name; - struct GNUNET_CONFIGURATION_Handle *cfg_dup; - - if (NULL != plugin) - return GNUNET_OK; - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint", - "db", - &plugin_name)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint", - "db"); - return GNUNET_SYSERR; - } - (void) GNUNET_asprintf (&lib_name, - "libtaler_plugin_mintdb_%s", - plugin_name); - GNUNET_free (plugin_name); - cfg_dup = GNUNET_CONFIGURATION_dup (cfg); - plugin = GNUNET_PLUGIN_load (lib_name, cfg_dup); - GNUNET_CONFIGURATION_destroy (cfg_dup); - GNUNET_free (lib_name); - if (NULL == plugin) - return GNUNET_SYSERR; - return GNUNET_OK; -} - - -/** - * Shutdown the plugin. - */ -void -TALER_MINT_plugin_unload () -{ - if (NULL == plugin) - return; - GNUNET_assert (NULL == GNUNET_PLUGIN_unload (plugin->library_name, - plugin)); -} - - -/** - * 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 (); -} - - -/* end of plugin.c */ diff --git a/src/mint/plugin.h b/src/mint/plugin.h deleted file mode 100644 index 0dfb866da..000000000 --- a/src/mint/plugin.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/plugin.h - * @brief Logic to load database plugins - * @author Christian Grothoff - */ -#ifndef PLUGIN_H -#define PLUGIN_H - -#include <gnunet/gnunet_util_lib.h> -#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 (const struct GNUNET_CONFIGURATION_Handle *cfg); - - -/** - * Shutdown the plugin. - */ -void -TALER_MINT_plugin_unload (void); - - -#endif diff --git a/src/mint/plugin_mintdb_common.c b/src/mint/plugin_mintdb_common.c deleted file mode 100644 index a95cf4be2..000000000 --- a/src/mint/plugin_mintdb_common.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - 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 <http://www.gnu.org/licenses/> -*/ -/** - * @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 (bt->wire); - GNUNET_free (bt); - break; - case TALER_MINT_DB_RO_WITHDRAW_COIN: - cbc = rh->details.withdraw; - GNUNET_CRYPTO_rsa_signature_free (cbc->sig.rsa_signature); - GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub.rsa_public_key); - GNUNET_free (cbc); - break; - } - 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) -{ - struct LinkDataList *next; - - while (NULL != ldl) - { - next = ldl->next; - GNUNET_free (ldl->link_data_enc); - GNUNET_free (ldl); - ldl = next; - } -} - - -/** - * 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) -{ - 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/plugin_mintdb_postgres.c b/src/mint/plugin_mintdb_postgres.c deleted file mode 100644 index 9846d1720..000000000 --- a/src/mint/plugin_mintdb_postgres.c +++ /dev/null @@ -1,2357 +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 <http://www.gnu.org/licenses/> -*/ - -/** - * @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 "taler_pq_lib.h" -#include "taler_signatures.h" -#include "taler_mintdb_plugin.h" -#include <pthread.h> -#include <libpq-fe.h> - -#include "plugin_mintdb_common.c" - -#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_PQ_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 *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 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 (void *cls, - int temporary) -{ - struct PostgresClosure *pc = cls; - PGresult *result; - PGconn *conn; - - result = NULL; - conn = PQconnectdb (pc->connection_cfg_str); - if (CONNECTION_OK != PQstatus (conn)) - { - TALER_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 INT8 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 INT8 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 INT8 NOT NULL" - ",expended_fraction INT4 NOT NULL" - ",expended_currency VARCHAR(4) NOT NULL" - ",refresh_session_hash BYTEA" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_sessions " - "(" - " session_hash BYTEA PRIMARY KEY CHECK (length(session_hash) = 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_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash)" - ",newcoin_index INT2 NOT NULL " - ",denom_pub BYTEA NOT NULL " - ",PRIMARY KEY (session_hash, newcoin_index)" - ") "); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link" - "(" - " 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 - ",oldcoin_index INT2 NOT NULL" - // index for cut and choose, - // ranges from 0 to #TALER_CNC_KAPPA-1 - ",cnc_index INT2 NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_coin" - "(" - " 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" - // index for cut and choose, - ",cnc_index INT2 NOT NULL" - ",coin_ev BYTEA NOT NULL" - ")"); - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_melt" - "(" - " 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_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) " - ",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 INT8 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_hash = $1)::INT2 as num_oldcoins " - ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_hash = $1 and cnc_index = 0)::INT2 as num_newcoins " - ",(SELECT count(*) FROM refresh_blind_session_keys " - " WHERE session_hash = $1 and newcoin_index = 0)::INT2 as kappa " - ",noreveal_index" - ",session_commit_sig " - ",reveal_ok " - "FROM refresh_sessions " - "WHERE session_hash = $1", - 1, NULL); -#endif - - PREPARE ("get_known_coin", - "SELECT " - " coin_pub, denom_pub, denom_sig " - ",expended_value, expended_fraction, expended_currency " - ",refresh_session_hash " - "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_hash = $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_hash" - ")" - "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_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_hash = $1 AND cnc_index = $2 AND newcoin_index = $3", - 3, NULL); - PREPARE ("insert_refresh_order", - "INSERT INTO refresh_order ( " - " newcoin_index " - ",session_hash " - ",denom_pub " - ") " - "VALUES ($1, $2, $3) ", - 3, NULL); - PREPARE ("insert_refresh_melt", - "INSERT INTO refresh_melt ( " - " session_hash " - ",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_hash = $1 AND newcoin_index = $2", - 2, NULL); - PREPARE ("get_refresh_collectable", - "SELECT ev_sig " - "FROM refresh_collectable " - "WHERE session_hash = $1 AND newcoin_index = $2", - 2, NULL); - PREPARE ("get_refresh_melt", - "SELECT coin_pub " - "FROM refresh_melt " - "WHERE session_hash = $1 AND oldcoin_index = $2", - 2, NULL); - PREPARE ("insert_refresh_session", - "INSERT INTO refresh_sessions ( " - " session_hash " - ",noreveal_index " - ") " - "VALUES ($1, $2) ", - 2, NULL); - PREPARE ("insert_refresh_commit_link", - "INSERT INTO refresh_commit_link ( " - " session_hash " - ",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_hash " - ",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_hash " - ",newcoin_index " - ",ev_sig " - ") " - "VALUES ($1, $2, $3) ", - 3, NULL); - PREPARE ("set_reveal_ok", - "UPDATE refresh_sessions " - "SET reveal_ok = TRUE " - "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_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_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_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_hash = rm.session_hash " - " ) ", - 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_session (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->connection_cfg_str); - if (CONNECTION_OK != - PQstatus (db_conn)) - { - TALER_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)) - { - TALER_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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(&reserve->pub), - TALER_PQ_QUERY_PARAM_END - }; - - result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC("expiration_date", &expiration_date_nbo), - TALER_PQ_RESULT_SPEC_END - }; - EXITIF (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)); - EXITIF (GNUNET_OK != - TALER_PQ_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) - return GNUNET_SYSERR; - ret = GNUNET_OK; - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (&reserve->pub), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_PQ_QUERY_PARAM_PTR (&expiry_nbo), - TALER_PQ_QUERY_PARAM_END - }; - TALER_amount_hton (&balance_nbo, - &reserve->balance); - expiry_nbo = GNUNET_TIME_absolute_hton (reserve->expiry); - result = TALER_PQ_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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (&reserve->pub), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_PQ_QUERY_PARAM_PTR_SIZED (balance_nbo.currency, - TALER_PQ_CURRENCY_LEN), - TALER_PQ_QUERY_PARAM_PTR (&expiry_nbo), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (&reserve->pub), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.value), - TALER_PQ_QUERY_PARAM_PTR (&balance_nbo.fraction), - TALER_PQ_QUERY_PARAM_PTR_SIZED (&balance_nbo.currency, - TALER_PQ_CURRENCY_LEN), - TALER_PQ_QUERY_PARAM_PTR (&expiry_nbo), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (h_blind), - TALER_PQ_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_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_VAR("denom_pub", &denom_pub_enc, &denom_pub_enc_size), - TALER_PQ_RESULT_SPEC_VAR("denom_sig", &denom_sig_enc, &denom_sig_enc_size), - TALER_PQ_RESULT_SPEC("reserve_sig", &collectable->reserve_sig), - TALER_PQ_RESULT_SPEC("reserve_pub", &collectable->reserve_pub), - TALER_PQ_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_PQ_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.rsa_public_key = denom_pub; - collectable->sig.rsa_signature = 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.rsa_public_key, - &denom_pub_enc); - denom_sig_enc_size = - GNUNET_CRYPTO_rsa_signature_encode (collectable->sig.rsa_signature, - &denom_sig_enc); - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (h_blind), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size - 1), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size - 1), /* DB doesn't like the trailing \0 */ - TALER_PQ_QUERY_PARAM_PTR (&collectable->reserve_pub), - TALER_PQ_QUERY_PARAM_PTR (&collectable->reserve_sig), - TALER_PQ_QUERY_PARAM_END - }; - if (GNUNET_OK != postgres_start (cls, - session)) - goto cleanup; - result = TALER_PQ_exec_prepared (session->conn, - "insert_collectable_blindcoin", - params); - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - QUERY_ERR (result); - goto rollback; - } - reserve.pub = 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 TALER_ReservePublicKeyP *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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (reserve_pub), - TALER_PQ_QUERY_PARAM_END - }; - - result = TALER_PQ_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_PQ_extract_amount (result, - --rows, - "balance_value", - "balance_fraction", - "balance_currency", - &bt->amount)) - { - GNUNET_free (bt); - GNUNET_break (0); - goto cleanup; - } - bt->reserve_pub = *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 TALER_ReserveSignatureP 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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (reserve_pub), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC ("blind_ev", &blind_ev), - TALER_PQ_RESULT_SPEC_VAR ("denom_pub", &denom_pub_enc, &denom_pub_enc_size), - TALER_PQ_RESULT_SPEC_VAR ("denom_sig", &denom_sig_enc, &denom_sig_enc_size), - TALER_PQ_RESULT_SPEC ("reserve_sig", &reserve_sig), - TALER_PQ_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_PQ_extract_result (result, rs, --rows)) - { - GNUNET_break (0); - goto cleanup; - } - cbc = GNUNET_new (struct CollectableBlindcoin); - 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.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.rsa_signature) || - (NULL == cbc->denom_pub.rsa_public_key) ) - { - 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; - } - (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) - { - common_free_reserve_history (cls, - 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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_PQ_QUERY_PARAM_PTR (&deposit->transaction_id), - TALER_PQ_QUERY_PARAM_PTR (&deposit->merchant_pub), - TALER_PQ_QUERY_PARAM_END - }; - PGresult *result; - int ret; - - ret = GNUNET_SYSERR; - result = TALER_PQ_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.rsa_public_key, - &denom_pub_enc); - denom_sig_enc_size = - 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, - &deposit->amount_with_fee); - struct TALER_PQ_QueryParam params[]= { - TALER_PQ_QUERY_PARAM_PTR (&deposit->coin.coin_pub), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_pub_enc, denom_pub_enc_size), - TALER_PQ_QUERY_PARAM_PTR_SIZED (denom_sig_enc, denom_sig_enc_size), - TALER_PQ_QUERY_PARAM_PTR (&deposit->transaction_id), - TALER_PQ_QUERY_PARAM_PTR (&amount_nbo.value), - TALER_PQ_QUERY_PARAM_PTR (&amount_nbo.fraction), - TALER_PQ_QUERY_PARAM_PTR_SIZED (amount_nbo.currency, - TALER_CURRENCY_LEN - 1), - TALER_PQ_QUERY_PARAM_PTR (&deposit->merchant_pub), - TALER_PQ_QUERY_PARAM_PTR (&deposit->h_contract), - TALER_PQ_QUERY_PARAM_PTR (&deposit->h_wire), - TALER_PQ_QUERY_PARAM_PTR (&deposit->csig), - TALER_PQ_QUERY_PARAM_PTR_SIZED (json_wire_enc, - strlen (json_wire_enc)), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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 @a session_hash. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param session database handle to use - * @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, - * #GNUNET_SYSERR on DB failure - */ -static int -postgres_get_refresh_session (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - struct RefreshSession *refresh_session) -{ - // FIXME: check logic! - int res; - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC("num_oldcoins", &refresh_session->num_oldcoins), - TALER_PQ_RESULT_SPEC("num_newcoins", &refresh_session->num_newcoins), - TALER_PQ_RESULT_SPEC("noreveal_index", &refresh_session->noreveal_index), - TALER_PQ_RESULT_SPEC_END - }; - - res = TALER_PQ_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->noreveal_index = ntohs (refresh_session->noreveal_index); - - PQclear (result); - return GNUNET_YES; -} - - -/** - * 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 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 - */ -static int -postgres_create_refresh_session (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - const struct RefreshSession *refresh_session) -{ - // FIXME: actually store session data! - uint16_t noreveal_index; - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&noreveal_index), - TALER_PQ_QUERY_PARAM_END - }; - - noreveal_index = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, 1<<15); - noreveal_index = htonl (noreveal_index); - - PGresult *result = TALER_PQ_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 oldcoin_index index of the coin to store - * @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, - 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.rsa_public_key, - &buf); - { - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(&melt->session_hash), - TALER_PQ_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&melt->coin.coin_pub), - TALER_PQ_QUERY_PARAM_PTR_SIZED(buf, buf_size), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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_HashCode *session_hash, - 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_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 - * #GNUNET_SYSERR on internal error - */ -static int -postgres_insert_refresh_order (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t num_newcoins, - const struct TALER_DenominationPublicKey *denom_pubs) -{ - // 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_pubs->rsa_public_key, - &buf); - - { - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR (&newcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR (session_hash), - TALER_PQ_QUERY_PARAM_PTR_SIZED (buf, buf_size), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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 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_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 - * #GNUNET_SYSERR on internal error - */ -static int -postgres_get_refresh_order (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t num_newcoins, - struct TALER_DenominationPublicKey *denom_pubs) -{ - // FIXME: check logic -- was written for just one coin! - char *buf; - size_t buf_size; - uint16_t newcoin_index_nbo = htons (num_newcoins); - - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_exec_prepared (session->conn, - "get_refresh_order", params); - - if (PGRES_TUPLES_OK != PQresultStatus (result)) - { - BREAK_DB_ERR (result); - PQclear (result); - return GNUNET_SYSERR; - } - - if (0 == PQntuples (result)) - { - PQclear (result); - /* FIXME: may want to distinguish between different error cases! */ - return GNUNET_SYSERR; - } - GNUNET_assert (1 == PQntuples (result)); - struct TALER_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_VAR ("denom_pub", &buf, &buf_size), - TALER_PQ_RESULT_SPEC_END - }; - if (GNUNET_OK != TALER_PQ_extract_result (result, rs, 0)) - { - PQclear (result); - GNUNET_break (0); - return GNUNET_SYSERR; - } - PQclear (result); - denom_pubs->rsa_public_key - = GNUNET_CRYPTO_rsa_public_key_decode (buf, - buf_size); - GNUNET_free (buf); - return GNUNET_OK; -} - - - -/** - * 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 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 - * @return #GNUNET_OK on success - * #GNUNET_SYSERR on error - */ -static int -postgres_insert_refresh_commit_coins (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - unsigned int i, - unsigned int num_newcoins, - const struct RefreshCommitCoin *commit_coins) -{ - // FIXME: check logic! -- was written for single commit_coin! - uint16_t cnc_index_nbo = htons (i); - uint16_t newcoin_index_nbo = htons (num_newcoins); - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR_SIZED(commit_coins->coin_ev, commit_coins->coin_ev_size), - TALER_PQ_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR_SIZED (commit_coins->refresh_link->coin_priv_enc, - commit_coins->refresh_link->blinding_key_enc_size + - sizeof (union TALER_CoinSpendPrivateKeyP)), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_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 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 - * @return #GNUNET_OK on success - * #GNUNET_NO if not found - * #GNUNET_SYSERR on error - */ -static int -postgres_get_refresh_commit_coins (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - 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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_PQ_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_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_VAR("coin_ev", &c_buf, &c_buf_size), - TALER_PQ_RESULT_SPEC_VAR("link_vector_enc", &rl_buf, &rl_buf_size), - TALER_PQ_RESULT_SPEC_END - }; - if (GNUNET_YES != TALER_PQ_extract_result (result, rs, 0)) - { - PQclear (result); - return GNUNET_SYSERR; - } - PQclear (result); - if (rl_buf_size < sizeof (union TALER_CoinSpendPrivateKeyP)) - { - 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 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 - * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success - */ -static int -postgres_insert_refresh_commit_links (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - 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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&commit_link->transfer_pub), - TALER_PQ_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&commit_link->shared_secret_enc), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_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 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 - * @return #GNUNET_SYSERR on internal error, - * #GNUNET_NO if commitment was not found - * #GNUNET_OK on success - */ -static int -postgres_get_refresh_commit_links (void *cls, - struct TALER_MINTDB_Session *session, - const struct GNUNET_HashCode *session_hash, - unsigned int i, - unsigned int num_links, - struct RefreshCommitLink *links) -{ - // 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_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&cnc_index_nbo), - TALER_PQ_QUERY_PARAM_PTR(&oldcoin_index_nbo), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC("transfer_pub", &links->transfer_pub), - TALER_PQ_RESULT_SPEC("link_secret_enc", &links->shared_secret_enc), - TALER_PQ_RESULT_SPEC_END - }; - - if (GNUNET_YES != TALER_PQ_extract_result (result, rs, 0)) - { - PQclear (result); - 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_hash hash to identify 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_HashCode *session_hash, - uint16_t newcoin_index, - const struct TALER_DenominationSignature *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->rsa_signature, - &buf); - { - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(session_hash), - TALER_PQ_QUERY_PARAM_PTR(&newcoin_index_nbo), - TALER_PQ_QUERY_PARAM_PTR_SIZED(buf, buf_size), - TALER_PQ_QUERY_PARAM_END - }; - result = TALER_PQ_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_data_list (void *cls, - struct TALER_MINTDB_Session *session, - const union TALER_CoinSpendPublicKeyP *coin_pub) -{ - // FIXME: check logic! - struct LinkDataList *ldl; - struct LinkDataList *pos; - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(coin_pub), - TALER_PQ_QUERY_PARAM_END - }; - PGresult *result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC_VAR("link_vector_enc", &ld_buf, &ld_buf_size), - TALER_PQ_RESULT_SPEC_VAR("denom_pub", &pk_buf, &pk_buf_size), - TALER_PQ_RESULT_SPEC_VAR("ev_sig", &sig_buf, &sig_buf_size), - TALER_PQ_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_PQ_extract_result (result, rs, i)) - { - PQclear (result); - GNUNET_break (0); - common_free_link_data_list (cls, - 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); - common_free_link_data_list (cls, - 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); - common_free_link_data_list (cls, - ldl); - return NULL; - } - pos = GNUNET_new (struct LinkDataList); - pos->next = ldl; - pos->link_data_enc = link_enc; - pos->denom_pub.rsa_public_key = denom_pub; - pos->ev_sig.rsa_signature = 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 - * #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 - * @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 union TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_TransferPublicKeyP *transfer_pub, - struct TALER_EncryptedLinkSecretP *shared_secret_enc) -{ - // FIXME: check logic! - struct TALER_PQ_QueryParam params[] = { - TALER_PQ_QUERY_PARAM_PTR(coin_pub), - TALER_PQ_QUERY_PARAM_END - }; - - PGresult *result = TALER_PQ_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_PQ_ResultSpec rs[] = { - TALER_PQ_RESULT_SPEC("transfer_pub", transfer_pub), - TALER_PQ_RESULT_SPEC("link_secret_enc", shared_secret_enc), - TALER_PQ_RESULT_SPEC_END - }; - - if (GNUNET_OK != TALER_PQ_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 union TALER_CoinSpendPublicKeyP *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)) - { - TALER_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_conn_str", - &pg->connection_cfg_str)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint", - "db_conn_str"); - return NULL; - } - plugin = GNUNET_new (struct TALER_MINTDB_Plugin); - plugin->cls = pg; - plugin->library_name = "libtaler_plugin_mintdb_postgres"; - 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->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; - 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_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; - 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; -} - - -/** - * 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->connection_cfg_str); - 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 deleted file mode 100644 index 8056b7df0..000000000 --- a/src/mint/taler-mint-dbinit.c +++ /dev/null @@ -1,101 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/taler-mint-dbinit.c - * @brief Create tables for the mint database. - * @author Florian Dold - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <libpq-fe.h> -#include "taler_util.h" -#include "taler_mintdb_plugin.h" -#include "plugin.h" - -/** - * Mint directory with the keys. - */ -static char *mint_base_dir; - -/** - * Our configuration. - */ -static struct GNUNET_CONFIGURATION_Handle *cfg; - - -/** - * 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) -{ - static const struct GNUNET_GETOPT_CommandLineOption 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 - }; - - 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)); - if (NULL == mint_base_dir) - { - fprintf (stderr, - "Mint base directory not given.\n"); - return 1; - } - cfg = TALER_config_load (mint_base_dir); - if (NULL == cfg) - { - fprintf (stderr, - "Failed to load mint configuration.\n"); - return 1; - } - if (GNUNET_OK != - TALER_MINT_plugin_load (cfg)) - { - fprintf (stderr, - "Failed to initialize database plugin.\n"); - return 1; - } - 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; -} - -/* end of taler-mint-dbinit.c */ diff --git a/src/mint/taler-mint-httpd.c b/src/mint/taler-mint-httpd.c index 13c77b033..a86735963 100644 --- a/src/mint/taler-mint-httpd.c +++ b/src/mint/taler-mint-httpd.c @@ -25,7 +25,6 @@ #include <gnunet/gnunet_util_lib.h> #include <jansson.h> #include <microhttpd.h> -#include <libpq-fe.h> #include <pthread.h> #include "taler_signatures.h" #include "taler_util.h" @@ -36,7 +35,6 @@ #include "taler-mint-httpd_refresh.h" #include "taler-mint-httpd_keystate.h" #include "taler_mintdb_plugin.h" -#include "plugin.h" /** @@ -61,6 +59,11 @@ struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key; char *TMH_expected_wire_format = "sepa"; /** + * Our DB plugin. + */ +struct TALER_MINTDB_Plugin *TMH_plugin; + +/** * The HTTP Daemon. */ static struct MHD_Daemon *mydaemon; @@ -260,8 +263,8 @@ mint_serve_process_config (const char *mint_directory) } GNUNET_free (TMH_master_public_key_str); - if (GNUNET_OK != - TALER_MINT_plugin_load (cfg)) + if (NULL == + (TMH_plugin = TALER_MINT_plugin_load (cfg))) { fprintf (stderr, "failed to initialize DB subsystem\n"); @@ -355,5 +358,6 @@ main (int argc, char *const *argv) ret = TMH_KS_loop (); MHD_stop_daemon (mydaemon); + TALER_MINT_plugin_unload (TMH_plugin); return (GNUNET_OK == ret) ? 0 : 1; } diff --git a/src/mint/taler-mint-httpd.h b/src/mint/taler-mint-httpd.h index 92ce54b84..11f2f3658 100644 --- a/src/mint/taler-mint-httpd.h +++ b/src/mint/taler-mint-httpd.h @@ -59,6 +59,11 @@ extern struct GNUNET_CRYPTO_EddsaPublicKey TMH_master_public_key; */ extern struct GNUNET_CRYPTO_EddsaPrivateKey TMH_mint_private_signing_key; +/** + * Our DB plugin. + */ +extern struct TALER_MINTDB_Plugin *TMH_plugin; + /** * Struct describing an URL and the handler for it. diff --git a/src/mint/taler-mint-httpd_db.c b/src/mint/taler-mint-httpd_db.c index 2fdd87188..13fde7240 100644 --- a/src/mint/taler-mint-httpd_db.c +++ b/src/mint/taler-mint-httpd_db.c @@ -26,7 +26,7 @@ #include "taler-mint-httpd_responses.h" #include "taler_util.h" #include "taler-mint-httpd_keystate.h" -#include "plugin.h" +#include "taler_mintdb_lib.h" /** @@ -109,14 +109,14 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection, struct TALER_DenominationKeyIssueInformation *dki; int ret; - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } if (GNUNET_YES == - plugin->have_deposit (plugin->cls, + TMH_plugin->have_deposit (TMH_plugin->cls, session, deposit)) { @@ -136,7 +136,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection, TMH_KS_release (mks); if (GNUNET_OK != - plugin->start (plugin->cls, + TMH_plugin->start (TMH_plugin->cls, session)) { GNUNET_break (0); @@ -145,7 +145,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection, /* fee for THIS transaction */ spent = deposit->amount_with_fee; /* add cost of all previous transactions */ - tl = plugin->get_coin_transactions (plugin->cls, + tl = TMH_plugin->get_coin_transactions (TMH_plugin->cls, session, &deposit->coin.coin_pub); if (GNUNET_OK != @@ -153,7 +153,7 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection, &spent, &spent)) { - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -162,30 +162,30 @@ TMH_DB_execute_deposit (struct MHD_Connection *connection, if (0 < TALER_amount_cmp (&spent, &value)) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); ret = TMH_RESPONSE_reply_deposit_insufficient_funds (connection, tl); - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); return ret; } - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); if (GNUNET_OK != - plugin->insert_deposit (plugin->cls, + TMH_plugin->insert_deposit (TMH_plugin->cls, session, deposit)) { TALER_LOG_WARNING ("Failed to store /deposit information in database\n"); - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } if (GNUNET_OK != - plugin->commit (plugin->cls, + TMH_plugin->commit (TMH_plugin->cls, session)) { TALER_LOG_WARNING ("/deposit transaction commit failed\n"); @@ -217,13 +217,13 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection, struct ReserveHistory *rh; int res; - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } - rh = plugin->get_reserve_history (plugin->cls, + rh = TMH_plugin->get_reserve_history (TMH_plugin->cls, session, reserve_pub); if (NULL == rh) @@ -233,7 +233,7 @@ TMH_DB_execute_withdraw_status (struct MHD_Connection *connection, "error", "Reserve not found"); res = TMH_RESPONSE_reply_withdraw_status_success (connection, rh); - plugin->free_reserve_history (plugin->cls, + TMH_plugin->free_reserve_history (TMH_plugin->cls, rh); return res; } @@ -282,13 +282,13 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, blinded_msg_len, &h_blind); - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } - res = plugin->get_collectable_blindcoin (plugin->cls, + res = TMH_plugin->get_collectable_blindcoin (TMH_plugin->cls, session, &h_blind, &collectable); @@ -323,7 +323,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, "Denomination not found"); } if (GNUNET_OK != - plugin->start (plugin->cls, + TMH_plugin->start (TMH_plugin->cls, session)) { GNUNET_break (0); @@ -331,12 +331,12 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, return TMH_RESPONSE_reply_internal_db_error (connection); } - rh = plugin->get_reserve_history (plugin->cls, + rh = TMH_plugin->get_reserve_history (TMH_plugin->cls, session, reserve); if (NULL == rh) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); TMH_KS_release (key_state); return TMH_RESPONSE_reply_json_pack (connection, @@ -357,7 +357,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, &value, &fee_withdraw)) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); TMH_KS_release (key_state); return TMH_RESPONSE_reply_internal_db_error (connection); @@ -378,7 +378,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, &deposit_total, &pos->details.bank->amount)) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); TMH_KS_release (key_state); return TMH_RESPONSE_reply_internal_db_error (connection); @@ -398,7 +398,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, &withdraw_total, &value)) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); TMH_KS_release (key_state); return TMH_RESPONSE_reply_internal_db_error (connection); @@ -416,15 +416,15 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, &balance)) { TMH_KS_release (key_state); - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); res = TMH_RESPONSE_reply_withdraw_sign_insufficient_funds (connection, rh); - plugin->free_reserve_history (plugin->cls, + TMH_plugin->free_reserve_history (TMH_plugin->cls, rh); return res; } - plugin->free_reserve_history (plugin->cls, + TMH_plugin->free_reserve_history (TMH_plugin->cls, rh); /* Balance is good, sign the coin! */ @@ -435,7 +435,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, if (NULL == sig) { GNUNET_break (0); - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_error (connection, "Internal error"); @@ -448,7 +448,7 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, &collectable.h_coin_envelope); collectable.reserve_sig = *signature; if (GNUNET_OK != - plugin->insert_collectable_blindcoin (plugin->cls, + TMH_plugin->insert_collectable_blindcoin (TMH_plugin->cls, session, &h_blind, amount_required, @@ -456,12 +456,12 @@ TMH_DB_execute_withdraw_sign (struct MHD_Connection *connection, { GNUNET_break (0); GNUNET_CRYPTO_rsa_signature_free (sig); - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } if (GNUNET_OK != - plugin->commit (plugin->cls, + TMH_plugin->commit (TMH_plugin->cls, session)) { TALER_LOG_WARNING ("/withdraw/sign transaction commit failed\n"); @@ -523,7 +523,7 @@ refresh_accept_melts (struct MHD_Connection *connection, /* fee for THIS transaction; the melt amount includes the fee! */ spent = coin_details->melt_amount_with_fee; /* add historic transaction costs of this coin */ - tl = plugin->get_coin_transactions (plugin->cls, + tl = TMH_plugin->get_coin_transactions (TMH_plugin->cls, session, &coin_public_info->coin_pub); if (GNUNET_OK != @@ -532,7 +532,7 @@ refresh_accept_melts (struct MHD_Connection *connection, &spent)) { GNUNET_break (0); - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -553,11 +553,11 @@ refresh_accept_melts (struct MHD_Connection *connection, coin_details->melt_amount_with_fee, coin_residual)) ? GNUNET_NO : GNUNET_SYSERR; - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); return res; } - plugin->free_coin_transaction_list (plugin->cls, + TMH_plugin->free_coin_transaction_list (TMH_plugin->cls, tl); melt.coin = *coin_public_info; @@ -565,7 +565,7 @@ refresh_accept_melts (struct MHD_Connection *connection, melt.session_hash = *session_hash; melt.amount_with_fee = coin_details->melt_amount_with_fee; if (GNUNET_OK != - plugin->insert_refresh_melt (plugin->cls, + TMH_plugin->insert_refresh_melt (TMH_plugin->cls, session, oldcoin_index, &melt)) @@ -617,26 +617,26 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, int res; unsigned int i; - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } if (GNUNET_OK != - plugin->start (plugin->cls, + TMH_plugin->start (TMH_plugin->cls, session)) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } - res = plugin->get_refresh_session (plugin->cls, + res = TMH_plugin->get_refresh_session (TMH_plugin->cls, session, session_hash, &refresh_session); if (GNUNET_YES == res) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); res = TMH_RESPONSE_reply_refresh_melt_success (connection, session_hash, @@ -645,7 +645,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, } if (GNUNET_SYSERR == res) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -664,7 +664,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, i))) { TMH_KS_release (key_state); - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; } @@ -673,13 +673,13 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, /* store requested new denominations */ if (GNUNET_OK != - plugin->insert_refresh_order (plugin->cls, + TMH_plugin->insert_refresh_order (TMH_plugin->cls, session, session_hash, num_new_denoms, denom_pubs)) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -687,14 +687,14 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, for (i = 0; i < TALER_CNC_KAPPA; i++) { if (GNUNET_OK != - plugin->insert_refresh_commit_coins (plugin->cls, + TMH_plugin->insert_refresh_commit_coins (TMH_plugin->cls, session, session_hash, i, num_new_denoms, commit_coin[i])) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -702,14 +702,14 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, for (i = 0; i < TALER_CNC_KAPPA; i++) { if (GNUNET_OK != - plugin->insert_refresh_commit_links (plugin->cls, + TMH_plugin->insert_refresh_commit_links (TMH_plugin->cls, session, session_hash, i, coin_count, commit_link[i])) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -723,12 +723,12 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, TALER_CNC_KAPPA); if (GNUNET_OK != - (res = plugin->create_refresh_session (plugin->cls, + (res = TMH_plugin->create_refresh_session (TMH_plugin->cls, session, session_hash, &refresh_session))) { - plugin->rollback (plugin->cls, + TMH_plugin->rollback (TMH_plugin->cls, session); return TMH_RESPONSE_reply_internal_db_error (connection); } @@ -736,7 +736,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, if (GNUNET_OK != - plugin->commit (plugin->cls, + TMH_plugin->commit (TMH_plugin->cls, session)) { TALER_LOG_WARNING ("/refresh/melt transaction commit failed\n"); @@ -789,7 +789,7 @@ check_commitment (struct MHD_Connection *connection, commit_links = GNUNET_malloc (num_oldcoins * sizeof (struct RefreshCommitLink)); if (GNUNET_OK != - plugin->get_refresh_commit_links (plugin->cls, + TMH_plugin->get_refresh_commit_links (TMH_plugin->cls, session, session_hash, off, @@ -888,7 +888,7 @@ check_commitment (struct MHD_Connection *connection, sizeof (struct RefreshCommitCoin)); if (GNUNET_OK != - plugin->get_refresh_commit_coins (plugin->cls, + TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls, session, session_hash, off, @@ -1008,7 +1008,7 @@ refresh_mint_coin (struct MHD_Connection *connection, return ev_sig; } if (GNUNET_OK != - plugin->insert_refresh_collectable (plugin->cls, + TMH_plugin->insert_refresh_collectable (TMH_plugin->cls, session, session_hash, coin_off, @@ -1054,14 +1054,14 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, unsigned int j; unsigned int off; - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } - res = plugin->get_refresh_session (plugin->cls, + res = TMH_plugin->get_refresh_session (TMH_plugin->cls, session, session_hash, &refresh_session); @@ -1081,7 +1081,7 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, for (j=0;j<refresh_session.num_oldcoins;j++) { if (GNUNET_OK != - plugin->get_refresh_melt (plugin->cls, + TMH_plugin->get_refresh_melt (TMH_plugin->cls, session, session_hash, j, @@ -1095,7 +1095,7 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, denom_pubs = GNUNET_malloc (refresh_session.num_newcoins * sizeof (struct TALER_DenominationPublicKey)); if (GNUNET_OK != - plugin->get_refresh_order (plugin->cls, + TMH_plugin->get_refresh_order (TMH_plugin->cls, session, session_hash, refresh_session.num_newcoins, @@ -1136,7 +1136,7 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, /* Client request OK, start transaction */ if (GNUNET_OK != - plugin->start (plugin->cls, + TMH_plugin->start (TMH_plugin->cls, session)) { GNUNET_break (0); @@ -1149,7 +1149,7 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, commit_coins = GNUNET_malloc (refresh_session.num_newcoins * sizeof (struct RefreshCommitCoin)); if (GNUNET_OK != - plugin->get_refresh_commit_coins (plugin->cls, + TMH_plugin->get_refresh_commit_coins (TMH_plugin->cls, session, session_hash, refresh_session.noreveal_index, @@ -1195,7 +1195,7 @@ TMH_DB_execute_refresh_reveal (struct MHD_Connection *connection, GNUNET_free (commit_coins); if (GNUNET_OK != - plugin->commit (plugin->cls, + TMH_plugin->commit (TMH_plugin->cls, session)) { TALER_LOG_WARNING ("/refresh/reveal transaction commit failed\n"); @@ -1234,13 +1234,13 @@ TMH_DB_execute_refresh_link (struct MHD_Connection *connection, struct TALER_EncryptedLinkSecretP shared_secret_enc; struct LinkDataList *ldl; - if (NULL == (session = plugin->get_session (plugin->cls, + if (NULL == (session = TMH_plugin->get_session (TMH_plugin->cls, GNUNET_NO))) { GNUNET_break (0); return TMH_RESPONSE_reply_internal_db_error (connection); } - res = plugin->get_transfer (plugin->cls, + res = TMH_plugin->get_transfer (TMH_plugin->cls, session, coin_pub, &transfer_pub, @@ -1260,7 +1260,7 @@ TMH_DB_execute_refresh_link (struct MHD_Connection *connection, } GNUNET_assert (GNUNET_OK == res); - ldl = plugin->get_link_data_list (plugin->cls, + ldl = TMH_plugin->get_link_data_list (TMH_plugin->cls, session, coin_pub); if (NULL == ldl) @@ -1275,7 +1275,7 @@ TMH_DB_execute_refresh_link (struct MHD_Connection *connection, &transfer_pub, &shared_secret_enc, ldl); - plugin->free_link_data_list (plugin->cls, + TMH_plugin->free_link_data_list (TMH_plugin->cls, ldl); return res; } diff --git a/src/mint/taler-mint-httpd_db.h b/src/mint/taler-mint-httpd_db.h index 44d11ffc9..3e8a7df7f 100644 --- a/src/mint/taler-mint-httpd_db.h +++ b/src/mint/taler-mint-httpd_db.h @@ -21,7 +21,6 @@ #ifndef TALER_MINT_HTTPD_DB_H #define TALER_MINT_HTTPD_DB_H -#include <libpq-fe.h> #include <microhttpd.h> #include <gnunet/gnunet_util_lib.h> #include "taler_util.h" diff --git a/src/mint/taler-mint-httpd_deposit.c b/src/mint/taler-mint-httpd_deposit.c index a1d64be45..ee2d24845 100644 --- a/src/mint/taler-mint-httpd_deposit.c +++ b/src/mint/taler-mint-httpd_deposit.c @@ -30,7 +30,6 @@ #include <gnunet/gnunet_util_lib.h> #include <jansson.h> #include <microhttpd.h> -#include <libpq-fe.h> #include <pthread.h> #include "taler_mintdb_plugin.h" #include "taler_signatures.h" diff --git a/src/mint/taler-mint-httpd_keystate.h b/src/mint/taler-mint-httpd_keystate.h index 4946ec1a3..26c9ccad6 100644 --- a/src/mint/taler-mint-httpd_keystate.h +++ b/src/mint/taler-mint-httpd_keystate.h @@ -26,7 +26,7 @@ #include <gnunet/gnunet_util_lib.h> #include <microhttpd.h> #include "taler-mint-httpd.h" -#include "key_io.h" +#include "taler_mintdb_lib.h" /** diff --git a/src/mint/taler-mint-httpd_mhd.c b/src/mint/taler-mint-httpd_mhd.c index 934a2f9d2..a12158731 100644 --- a/src/mint/taler-mint-httpd_mhd.c +++ b/src/mint/taler-mint-httpd_mhd.c @@ -27,7 +27,6 @@ #include <gnunet/gnunet_util_lib.h> #include <jansson.h> #include <microhttpd.h> -#include <libpq-fe.h> #include <pthread.h> #include "taler-mint-httpd_responses.h" #include "taler-mint-httpd.h" diff --git a/src/mint/taler-mint-keycheck.c b/src/mint/taler-mint-keycheck.c deleted file mode 100644 index 4e8885fd3..000000000 --- a/src/mint/taler-mint-keycheck.c +++ /dev/null @@ -1,227 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-mint-keycheck.c - * @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 <platform.h> -#include <gnunet/gnunet_util_lib.h> -#include "key_io.h" - -/** - * Mint directory with the keys. - */ -static char *mint_directory; - -/** - * 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, - const struct TALER_MintSigningKeyValidityPSPriv *ski) -{ - 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))); - - if (ntohl (ski->issue.purpose.size) != - (sizeof (struct TALER_MintSigningKeyValidityPS) - - offsetof (struct TALER_MintSigningKeyValidityPS, purpose))) - { - fprintf (stderr, - "Signing key `%s' has invalid purpose size\n", - filename); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_SIGNING_KEY_VALIDITY, - &ski->issue.purpose, - &ski->issue.signature.eddsa_signature, - &ski->issue.master_public_key.eddsa_pub)) - { - fprintf (stderr, - "Signing key `%s' has invalid signature\n", - filename); - return GNUNET_SYSERR; - } - 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 (mint_directory, - &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_DenominationKeyIssueInformation *dki) -{ - struct GNUNET_HashCode hc; - - if (ntohl (dki->issue.purpose.size) != - sizeof (struct TALER_DenominationKeyValidityPS)) - { - fprintf (stderr, - "Denomination key for `%s' has invalid purpose size\n", - alias); - return GNUNET_SYSERR; - } - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MINT_DENOMINATION_KEY_VALIDITY, - &dki->issue.purpose, - &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.rsa_public_key, - &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 (mint_directory, - &denomkeys_iter, - NULL)) - return GNUNET_NO; - return GNUNET_OK; -} - - -/** - * The main function of the keyup tool - * - * @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) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keycheck OPTIONS"), - {'d', "directory", "DIRECTORY", - "mint directory with keys to check", 1, - &GNUNET_GETOPT_set_filename, &mint_directory}, - GNUNET_GETOPT_OPTION_END - }; - - GNUNET_assert (GNUNET_OK == - GNUNET_log_setup ("taler-mint-keycheck", - "WARNING", - NULL)); - - if (GNUNET_GETOPT_run ("taler-mint-keycheck", - options, - argc, argv) < 0) - return 1; - if (NULL == mint_directory) - { - fprintf (stderr, - "Mint directory not given\n"); - return 1; - } - - kcfg = TALER_config_load (mint_directory); - if (NULL == kcfg) - { - fprintf (stderr, - "Failed to load mint configuration\n"); - return 1; - } - 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 */ diff --git a/src/mint/taler-mint-keyup.c b/src/mint/taler-mint-keyup.c deleted file mode 100644 index ab457426c..000000000 --- a/src/mint/taler-mint-keyup.c +++ /dev/null @@ -1,954 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-mint-keyup.c - * @brief Update the mint's keys for coins and signatures, - * using the mint's offline master key. - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff - */ -#include <platform.h> -#include <gnunet/gnunet_util_lib.h> -#include "taler_util.h" -#include "key_io.h" - -/** - * 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); - - -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 CoinTypeNBOP -{ - /** - * 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; - - /** - * 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; -}; - - -/** - * Filename of the master private key. - */ -static char *masterkeyfile; - -/** - * Director of the mint, containing the keys. - */ -static char *mint_directory; - -/** - * Time to pretend when the key update is executed. - */ -static char *pretend_time_str; - -/** - * Handle to the mint's configuration - */ -static struct GNUNET_CONFIGURATION_Handle *kcfg; - -/** - * Time when the key update is executed. Either the actual current time, or a - * pretended time. - */ -static struct GNUNET_TIME_Absolute now; - -/** - * Master private key of the mint. - */ -static struct TALER_MasterPrivateKeyP master_priv; - -/** - * Master public key of the mint. - */ -static struct TALER_MasterPublicKeyP master_public_key; - -/** - * Until what time do we provide keys? - */ -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. - * - * @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 const char * -get_signkey_file (struct GNUNET_TIME_Absolute start) -{ - static char dir[4096]; - - GNUNET_snprintf (dir, - sizeof (dir), - "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS DIR_SEPARATOR_STR "%llu", - mint_directory, - (unsigned long long) start.abs_value_us); - return dir; -} - - -/** - * 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 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, - struct GNUNET_HashCode *hash) -{ - struct CoinTypeNBOP p_nbo; - - memset (&p_nbo, - 0, - sizeof (struct CoinTypeNBOP)); - p_nbo.duration_spend = GNUNET_TIME_relative_hton (p->duration_spend); - p_nbo.duration_withdraw = GNUNET_TIME_relative_hton (p->duration_withdraw); - 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 CoinTypeNBOP), - hash); -} - - -/** - * 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 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) -{ - static char dir[4096]; - struct GNUNET_HashCode hash; - char *hash_str; - char *val_str; - size_t i; - - hash_coin_type (p, &hash); - hash_str = GNUNET_STRINGS_data_to_string_alloc (&hash, - sizeof (struct GNUNET_HashCode)); - 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]) ) - val_str[i] = '_'; - - GNUNET_snprintf (dir, - sizeof (dir), - "%s" DIR_SEPARATOR_STR DIR_DENOMKEYS DIR_SEPARATOR_STR "%s-%s", - mint_directory, - 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 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 (const struct CoinTypeParams *p, - struct GNUNET_TIME_Absolute start) -{ - static char filename[4096]; - const char *dir; - - dir = get_cointype_dir (p); - GNUNET_snprintf (filename, - sizeof (filename), - "%s" DIR_SEPARATOR_STR "%llu", - dir, - (unsigned long long) start.abs_value_us); - return filename; -} - - -/** - * 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. 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) - * that was found - * @param filename complete filename (absolute path) - * @return #GNUNET_OK (to continue to iterate) - */ -static int -get_anchor_iter (void *cls, - const char *filename) -{ - 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); - if ((NULL == end) || (0 != *end)) - { - fprintf(stderr, - "Ignoring unexpected file `%s'.\n", - filename); - return GNUNET_OK; - } - 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 (as we do not parse them, - * but just look at the filenames to "guess" at their contents). - * - * @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 - */ -static void -get_anchor (const char *dir, - struct GNUNET_TIME_Relative duration, - struct GNUNET_TIME_Relative overlap, - struct GNUNET_TIME_Absolute *anchor) -{ - 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)) - { - *anchor = now; - 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, - &get_anchor_iter, - 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... #3727*/ - if ((GNUNET_TIME_absolute_add (*anchor, - duration)).abs_value_us < now.abs_value_us) - { - 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) // Also odd... - { - /* 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 */ -} - - -/** - * 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 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, - struct GNUNET_TIME_Relative duration, - struct TALER_MintSigningKeyValidityPSPriv *pi) -{ - struct GNUNET_CRYPTO_EddsaPrivateKey *priv; - struct TALER_MintSigningKeyValidityPS *issue = &pi->issue; - - priv = GNUNET_CRYPTO_eddsa_key_create (); - pi->signkey_priv.eddsa_priv = *priv; - GNUNET_free (priv); - issue->master_public_key = master_public_key; - 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.eddsa_priv, - &issue->signkey_pub.eddsa_pub); - issue->purpose.purpose = htonl (TALER_SIGNATURE_MINT_SIGNING_KEY_VALIDITY); - issue->purpose.size = htonl (sizeof (struct TALER_MintSigningKeyValidityPS) - - offsetof (struct TALER_MintSigningKeyValidityPS, - purpose)); - - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, - &issue->purpose, - &issue->signature.eddsa_signature)); -} - - -/** - * Generate signing keys starting from the last key found to - * the lookahead time. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -mint_keys_update_signkeys () -{ - struct GNUNET_TIME_Relative signkey_duration; - struct GNUNET_TIME_Absolute anchor; - char *signkey_dir; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - "mint_keys", - "signkey_duration", - &signkey_duration)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint_keys", - "signkey_duration"); - return GNUNET_SYSERR; - } - ROUND_TO_SECS (signkey_duration, - rel_value_us); - GNUNET_asprintf (&signkey_dir, - "%s" DIR_SEPARATOR_STR DIR_SIGNKEYS, - mint_directory); - /* make sure the directory exists */ - if (GNUNET_OK != - GNUNET_DISK_directory_create (signkey_dir)) - { - fprintf (stderr, - "Failed to create signing key directory\n"); - return GNUNET_SYSERR; - } - - get_anchor (signkey_dir, - signkey_duration, - 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_MintSigningKeyValidityPSPriv signkey_issue; - ssize_t nwrite; - - skf = get_signkey_file (anchor); - 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_MintSigningKeyValidityPS), - GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_USER_READ); - if (nwrite != sizeof (struct TALER_MintSigningKeyValidityPS)) - { - fprintf (stderr, - "Failed to write to file `%s': %s\n", - skf, - STRERROR (errno)); - return GNUNET_SYSERR; - } - 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 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, - ct, - "duration_withdraw", - ¶ms->duration_withdraw)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "duration_withdraw"); - return GNUNET_SYSERR; - } - ROUND_TO_SECS (params->duration_withdraw, - rel_value_us); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - ct, - "duration_spend", - ¶ms->duration_spend)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "duration_spend"); - return GNUNET_SYSERR; - } - ROUND_TO_SECS (params->duration_spend, - rel_value_us); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_time (kcfg, - ct, - "duration_overlap", - ¶ms->duration_overlap)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "mint_denom_duration_overlap"); - return GNUNET_SYSERR; - } - ROUND_TO_SECS (params->duration_overlap, - rel_value_us); - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (kcfg, - ct, - "rsa_keysize", - &rsa_keysize)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "rsa_keysize"); - 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, - ct, - "value", - ¶ms->value)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "value"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_denom (kcfg, - ct, - "fee_withdraw", - ¶ms->fee_withdraw)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "fee_withdraw"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_denom (kcfg, - ct, - "fee_deposit", - ¶ms->fee_deposit)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "fee_deposit"); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_config_get_denom (kcfg, - ct, - "fee_refresh", - ¶ms->fee_refresh)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - ct, - "fee_refresh"); - return GNUNET_SYSERR; - } - - dir = get_cointype_dir (params); - 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 parameters used to initialize the @a dki - * @param dki[OUT] initialized according to @a params - */ -static void -create_denomkey_issue (const struct CoinTypeParams *params, - struct TALER_DenominationKeyIssueInformation *dki) -{ - 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_public_key; - dki->issue.start = GNUNET_TIME_absolute_hton (params->anchor); - dki->issue.expire_withdraw = - GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, - params->duration_withdraw)); - dki->issue.expire_spend = - GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_add (params->anchor, - params->duration_spend)); - 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_MINT_DENOMINATION_KEY_VALIDITY); - dki->issue.purpose.size = htonl (sizeof (struct TALER_DenominationKeyIssueInformation) - - offsetof (struct TALER_DenominationKeyIssueInformation, - issue.purpose)); - GNUNET_assert (GNUNET_OK == - GNUNET_CRYPTO_eddsa_sign (&master_priv.eddsa_priv, - &dki->issue.purpose, - &dki->issue.signature.eddsa_signature)); -} - - -/** - * 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 - */ -static void -mint_keys_update_cointype (void *cls, - const char *coin_alias) -{ - int *ret = cls; - struct CoinTypeParams p; - const char *dkf; - struct TALER_DenominationKeyIssueInformation denomkey_issue; - - 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) - { - 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)) - { - 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.rsa_private_key); - return; - } - 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, - p.duration_overlap); - } -} - - -/** - * Update all of the denomination keys of the mint. - * - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -static int -mint_keys_update_denomkeys () -{ - int ok; - - ok = GNUNET_OK; - GNUNET_CONFIGURATION_iterate_sections (kcfg, - &mint_keys_update_cointype, - &ok); - return ok; -} - - -/** - * 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 - * @return 0 ok, 1 on error - */ -int -main (int argc, - char *const *argv) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-keyup OPTIONS"), - {'m', "master-key", "FILE", - "master key file (private key)", 1, - &GNUNET_GETOPT_set_filename, &masterkeyfile}, - {'d', "mint-dir", "DIR", - "mint directory with keys to update", 1, - &GNUNET_GETOPT_set_filename, &mint_directory}, - {'t', "time", "TIMESTAMP", - "pretend it is a different time for the update", 0, - &GNUNET_GETOPT_set_string, &pretend_time_str}, - 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", - "WARNING", - NULL)); - - if (GNUNET_GETOPT_run ("taler-mint-keyup", - options, - argc, argv) < 0) - return 1; - if (NULL == mint_directory) - { - 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)) - { - fprintf (stderr, - "timestamp `%s' invalid\n", - pretend_time_str); - return 1; - } - } - else - { - now = GNUNET_TIME_absolute_get (); - } - ROUND_TO_SECS (now, abs_value_us); - - kcfg = TALER_config_load (mint_directory); - if (NULL == kcfg) - { - fprintf (stderr, - "Failed to load mint configuration\n"); - return 1; - } - if (NULL == masterkeyfile) - { - fprintf (stderr, - "Master key file not given\n"); - return 1; - } - 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_priv.eddsa_priv = *eddsa_priv; - GNUNET_free (eddsa_priv); - GNUNET_CRYPTO_eddsa_key_get_public (&master_priv.eddsa_priv, - &master_public_key.eddsa_pub); - - /* check if key from file matches the one from the configuration */ - { - struct GNUNET_CRYPTO_EddsaPublicKey master_public_key_from_cfg; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_data (kcfg, - "mint", - "master_public_key", - &master_public_key_from_cfg, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "mint", - "master_public_key"); - return 1; - } - if (0 != - memcmp (&master_public_key, - &master_public_key_from_cfg, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey))) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - "mint", - "master_public_key", - _("does not match with private key")); - return 1; - } - } - - 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; -} - -/* end of taler-mint-keyup.c */ diff --git a/src/mint/taler-mint-reservemod.c b/src/mint/taler-mint-reservemod.c deleted file mode 100644 index 125748704..000000000 --- a/src/mint/taler-mint-reservemod.c +++ /dev/null @@ -1,305 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file taler-mint-reservemod.c - * @brief Modify reserves. Allows manipulation of reserve balances. - * @author Florian Dold - * @author Benedikt Mueller - */ -#include "platform.h" -#include <gnunet/gnunet_util_lib.h> -#include <libpq-fe.h> -#include "taler_util.h" -#include "taler_signatures.h" -#include "taler_mintdb_plugin.h" -#include "taler_pq_lib.h" - - -/** - * Director of the mint, containing the keys. - */ -static char *mint_directory; - -/** - * Public key of the reserve to manipulate. - */ -static struct GNUNET_CRYPTO_EddsaPublicKey *reserve_pub; - -/** - * 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. - * - * @param denom denomination to add - * @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) -{ - PGresult *result; - 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)); - return GNUNET_SYSERR; - } - if (0 == PQntuples (result)) - { - struct GNUNET_TIME_AbsoluteNBO exnbo; - uint32_t value = htonl (denom.value); - uint32_t fraction = htonl (denom.fraction); - const void *param_values[] = { - reserve_pub, - &value, - &fraction, - denom.currency, - &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); - - if (PGRES_COMMAND_OK != PQresultStatus (result)) - { - fprintf (stderr, - "Insert failed: %s\n", - PQresultErrorMessage (result)); - return GNUNET_SYSERR; - } - } - else - { - 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_PQ_extract_amount (result, 0, - "balance_value", - "balance_fraction", - "balance_currency", - &old_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" - " 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)); - return GNUNET_SYSERR; - } - /* Yes, for historic reasons libpq returns a 'const char *'... */ - if (0 != strcmp ("1", - PQcmdTuples (result))) - { - fprintf (stderr, - "Update failed (updated `%s' tupes instead of '1')\n", - PQcmdTuples (result)); - return GNUNET_SYSERR; - } - } - return GNUNET_OK; -} - - -/** - * The main function of the reservemod tool - * - * @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) -{ - static char *reserve_pub_str; - static char *add_str; - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_HELP ("gnunet-mint-reservemod OPTIONS"), - {'d', "mint-dir", "DIR", - "mint directory with keys to update", 1, - &GNUNET_GETOPT_set_filename, &mint_directory}, - {'R', "reserve", "KEY", - "reserve (public key) to modify", 1, - &GNUNET_GETOPT_set_string, &reserve_pub_str}, - {'a', "add", "DENOM", - "value to add", 1, - &GNUNET_GETOPT_set_string, &add_str}, - GNUNET_GETOPT_OPTION_END - }; - char *connection_cfg_str; - - GNUNET_assert (GNUNET_OK == - GNUNET_log_setup ("taler-mint-reservemod", - "WARNING", - NULL)); - - if (GNUNET_GETOPT_run ("taler-mint-reservemod", - options, - argc, argv) < 0) - return 1; - if (NULL == mint_directory) - { - fprintf (stderr, - "Mint directory not given\n"); - return 1; - } - - reserve_pub = GNUNET_new (struct GNUNET_CRYPTO_EddsaPublicKey); - if ((NULL == reserve_pub_str) || - (GNUNET_OK != - GNUNET_STRINGS_string_to_data (reserve_pub_str, - strlen (reserve_pub_str), - reserve_pub, - sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))) - { - fprintf (stderr, - "Parsing reserve key invalid\n"); - return 1; - } - cfg = TALER_config_load (mint_directory); - if (NULL == cfg) - { - fprintf (stderr, - "Failed to load mint configuration\n"); - return 1; - } - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "mint", - "db", - &connection_cfg_str)) - { - fprintf (stderr, - "Database configuration string not found\n"); - return 1; - } - db_conn = PQconnectdb (connection_cfg_str); - if (CONNECTION_OK != PQstatus (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)) - { - fprintf (stderr, - "Failed to parse currency amount `%s'\n", - add_str); - return 1; - } - if (GNUNET_OK != - reservemod_add (add_value)) - { - fprintf (stderr, - "Failed to update reserve.\n"); - return 1; - } - } - return 0; -} - -/* end taler-mint-reservemod.c */ diff --git a/src/mint/test_mint_common.c b/src/mint/test_mint_common.c deleted file mode 100644 index 83df25046..000000000 --- a/src/mint/test_mint_common.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 GNUnet e. V. (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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/test_mint_common.c - * @brief test cases for some functions in mint/mint_common.c - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "platform.h" -#include "gnunet/gnunet_util_lib.h" -#include "taler_signatures.h" -#include "key_io.h" - -#define RSA_KEY_SIZE 1024 - - -#define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) - - -int -main (int argc, - const char *const argv[]) -{ - struct TALER_DenominationKeyIssueInformation dki; - char *enc; - size_t enc_size; - struct TALER_DenominationKeyIssueInformation dki_read; - char *enc_read; - size_t enc_read_size; - char *tmpfile; - int ret; - - ret = 1; - enc = NULL; - enc_read = NULL; - tmpfile = 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_DenominationKeyValidityPS, - signature)); - 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.rsa_private_key, - &enc_read); - EXITIF (enc_size != enc_read_size); - EXITIF (0 != memcmp (enc, - enc_read, - enc_size)); - ret = 0; - - EXITIF_exit: - GNUNET_free_non_null (enc); - if (NULL != tmpfile) - { - (void) unlink (tmpfile); - GNUNET_free (tmpfile); - } - GNUNET_free_non_null (enc_read); - 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 deleted file mode 100644 index a82094075..000000000 --- a/src/mint/test_mint_db.c +++ /dev/null @@ -1,393 +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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/test_mint_db.c - * @brief test cases for DB interaction functions - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "platform.h" -#include "plugin.h" - -static int result; - -#define FAILIF(cond) \ - do { \ - if (!(cond)){ break;} \ - GNUNET_break (0); \ - goto drop; \ - } while (0) - - -#define RND_BLK(ptr) \ - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, ptr, sizeof (*ptr)) - -#define ZR_BLK(ptr) \ - memset (ptr, 0, sizeof (*ptr)) - - -#define CURRENCY "EUR" - -/** - * Checks if the given reserve has the given amount of balance and expiry - * - * @param session the database connection - * @param pub the public key of the reserve - * @param value balance value - * @param fraction balance fraction - * @param currency currency of the reserve - * @param expiry expiration of the reserve - * @return #GNUNET_OK if the given reserve has the same balance and expiration - * as the given parameters; #GNUNET_SYSERR if not - */ -static int -check_reserve (struct TALER_MINTDB_Session *session, - const struct TALER_ReservePublicKeyP *pub, - uint64_t value, - uint32_t fraction, - const char *currency, - uint64_t expiry) -{ - struct Reserve reserve; - - reserve.pub = *pub; - - 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)); - FAILIF (expiry != reserve.expiry.abs_value_us); - - return GNUNET_OK; - drop: - return GNUNET_SYSERR; -} - - -struct DenomKeyPair -{ - struct TALER_DenominationPrivateKey priv; - struct TALER_DenominationPublicKey pub; -}; - - -static struct DenomKeyPair * -create_denom_key_pair (unsigned int size) -{ - struct DenomKeyPair *dkp; - - dkp = GNUNET_new (struct DenomKeyPair); - 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; -} - - -static void -destroy_denon_key_pair (struct DenomKeyPair *dkp) -{ - 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); -} - -/** - * 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 cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - struct TALER_MINTDB_Session *session; - struct TALER_ReservePublicKeyP reserve_pub; - struct Reserve reserve; - struct GNUNET_TIME_Absolute expiry; - struct TALER_Amount amount; - struct DenomKeyPair *dkp; - struct GNUNET_HashCode h_blind; - struct CollectableBlindcoin cbc; - struct CollectableBlindcoin cbc2; - struct ReserveHistory *rh; - 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; - - dkp = NULL; - rh = NULL; - wire = NULL; - session = NULL; - ZR_BLK (&cbc); - ZR_BLK (&cbc2); - if (GNUNET_OK != - TALER_MINT_plugin_load (cfg)) - { - result = 1; - return; - } - if (GNUNET_OK != - plugin->create_tables (plugin->cls, - GNUNET_YES)) - { - result = 2; - goto drop; - } - if (NULL == - (session = plugin->get_session (plugin->cls, - GNUNET_YES))) - { - result = 3; - goto drop; - } - RND_BLK (&reserve_pub); - reserve.pub = reserve_pub; - amount.value = 1; - amount.fraction = 1; - strcpy (amount.currency, CURRENCY); - expiry = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (), - GNUNET_TIME_UNIT_HOURS); - result = 4; - 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.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)); - amount.value--; - amount.fraction--; - 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.rsa_public_key); - 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.rsa_signature, - dkp->pub.rsa_public_key)); - 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 (1 != bt->amount.value); - FAILIF (1 != bt->amount.fraction); - FAILIF (0 != strcmp (CURRENCY, bt->amount.currency)); - FAILIF (NULL != bt->wire); /* FIXME: write wire details to db */ - break; - case TALER_MINT_DB_RO_WITHDRAW_COIN: - withdraw = rh_head->details.withdraw; - FAILIF (0 != memcmp (&withdraw->reserve_pub, - &reserve_pub, - sizeof (reserve_pub))); - FAILIF (0 != memcmp (&withdraw->h_coin_envelope, - &h_blind, sizeof (h_blind))); - break; - } - } - 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_with_fee = amount; - 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 != - 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 != - 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 != - plugin->have_deposit (plugin->cls, - session, - &deposit2)); - result = 0; - - drop: - if (NULL != wire) - json_decref (wire); - if (NULL != rh) - plugin->free_reserve_history (plugin->cls, - rh); - rh = NULL; - 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.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; - TALER_MINT_plugin_unload (); -} - - -int -main (int argc, - char *const argv[]) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - GNUNET_GETOPT_OPTION_END - }; - char *argv2[] = { - "test-mint-db-<plugin_name>", /* will be replaced later */ - "-c", "test-mint-db-<plugin_name>.conf", /* will be replaced later */ - NULL, - }; - const char *plugin_name; - char *config_filename; - char *testname; - - result = -1; - if (NULL == (plugin_name = strrchr (argv[0], (int) '-'))) - { - GNUNET_break (0); - return -1; - } - plugin_name++; - (void) GNUNET_asprintf (&testname, - "test-mint-db-%s", plugin_name); - (void) GNUNET_asprintf (&config_filename, - "%s.conf", testname); - argv2[0] = argv[0]; - argv2[2] = config_filename; - if (GNUNET_OK != - GNUNET_PROGRAM_run ((sizeof (argv2)/sizeof (char *)) - 1, argv2, - testname, - "Test cases for mint database helper functions.", - options, &run, NULL)) - { - GNUNET_free (config_filename); - GNUNET_free (testname); - return 3; - } - GNUNET_free (config_filename); - GNUNET_free (testname); - return result; -} diff --git a/src/mint/test_mint_deposits.c b/src/mint/test_mint_deposits.c deleted file mode 100644 index dbe12e88d..000000000 --- a/src/mint/test_mint_deposits.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014 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 <http://www.gnu.org/licenses/> -*/ -/** - * @file mint/test_mint_deposits.c - * @brief testcase for mint deposits - * @author Sree Harsha Totakura <sreeharsha@totakura.in> - */ -#include "platform.h" -#include <libpq-fe.h> -#include <gnunet/gnunet_util_lib.h> -#include "plugin.h" -#include "taler_pq_lib.h" -#include "taler-mint-httpd.h" - -#define DB_URI "postgres:///taler" - -#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) - - -/** - * Should we not interact with a temporary table? - */ -static int persistent; - -/** - * Testcase result - */ -static int result; - - -/** - * 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 cfg configuration - */ -static void -run (void *cls, - char *const *args, - const char *cfgfile, - const struct GNUNET_CONFIGURATION_Handle *cfg) -{ - static const char wire[] = "{" - "\"type\":\"SEPA\"," - "\"IBAN\":\"DE67830654080004822650\"," - "\"NAME\":\"GNUNET E.V\"," - "\"BIC\":\"GENODEF1SRL\"" - "}"; - struct Deposit *deposit; - uint64_t transaction_id; - struct TALER_MINTDB_Session *session; - - deposit = NULL; - 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, - deposit, - sizeof (struct Deposit)); - /* Makeup a random 64bit transaction ID */ - transaction_id = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, - UINT64_MAX); - deposit->transaction_id = GNUNET_htonll (transaction_id); - /* Random amount */ - deposit->amount_with_fee.value = - htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); - deposit->amount_with_fee.fraction = - htonl (GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, UINT32_MAX)); - GNUNET_assert (strlen (TMH_MINT_CURRENCY) < sizeof (deposit->amount_with_fee.currency)); - strcpy (deposit->amount_with_fee.currency, TMH_MINT_CURRENCY); - /* Copy wireformat */ - deposit->wire = json_loads (wire, 0, NULL); - 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); - return; -} - - -int -main (int argc, - char *const argv[]) -{ - static const struct GNUNET_GETOPT_CommandLineOption options[] = { - {'T', "persist", NULL, - gettext_noop ("Use a persistent database table instead of a temporary one"), - GNUNET_NO, &GNUNET_GETOPT_set_one, &persistent}, - GNUNET_GETOPT_OPTION_END - }; - - - persistent = GNUNET_NO; - result = GNUNET_SYSERR; - if (GNUNET_OK != - GNUNET_PROGRAM_run (argc, argv, - "test-mint-deposits", - "testcase for mint deposits", - options, &run, NULL)) - return 3; - return (GNUNET_OK == result) ? 0 : 1; -} |