diff options
Diffstat (limited to 'src/include')
26 files changed, 17944 insertions, 5489 deletions
diff --git a/src/include/.gitignore b/src/include/.gitignore new file mode 100644 index 000000000..beba883b6 --- /dev/null +++ b/src/include/.gitignore @@ -0,0 +1 @@ +taler_signatures.h diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 13b9a1444..45d74ab8e 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -5,6 +5,7 @@ talerinclude_HEADERS = \ platform.h gettext.h \ taler_auditor_service.h \ taler_amount_lib.h \ + taler_attributes.h \ taler_auditordb_lib.h \ taler_auditordb_plugin.h \ taler_bank_service.h \ @@ -16,7 +17,10 @@ talerinclude_HEADERS = \ taler_exchangedb_lib.h \ taler_exchangedb_plugin.h \ taler_extensions.h \ + taler_extensions_policy.h \ taler_fakebank_lib.h \ + taler_kyclogic_lib.h \ + taler_kyclogic_plugin.h \ taler_json_lib.h \ taler_testing_lib.h \ taler_util.h \ @@ -24,6 +28,7 @@ talerinclude_HEADERS = \ taler_pq_lib.h \ taler_signatures.h \ taler_sq_lib.h \ + taler_templating_lib.h \ taler_twister_testing_lib.h EXTRA_DIST = \ diff --git a/src/include/platform.h b/src/include/platform.h index b2c286b74..db04cb972 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -15,22 +15,22 @@ */ /** - * @file exchange/src/include/platform.h + * @file include/platform.h * @brief This file contains the includes and definitions which are used by the * rest of the modules * @author Sree Harsha Totakura <sreeharsha@totakura.in> */ - #ifndef PLATFORM_H_ #define PLATFORM_H_ /* Include our configuration header */ #ifndef HAVE_USED_CONFIG_H -# define HAVE_USED_CONFIG_H -# ifdef HAVE_CONFIG_H -# include "taler_config.h" -# endif +#define HAVE_USED_CONFIG_H +#ifdef HAVE_CONFIG_H +#include "taler_config.h" +#endif #endif + /* For the exchange build, we do NOT want gettext, even if it is available! */ #undef ENABLE_NLS @@ -45,9 +45,6 @@ /* Include the features available for GNU source */ #define _GNU_SOURCE -/* Include GNUnet's platform file */ -#include <gnunet/platform.h> - /* Do not use shortcuts for gcrypt mpi */ #define GCRYPT_NO_MPI_MACROS 1 @@ -67,24 +64,209 @@ #define ENABLE_SANITY_CHECKS 1 +#include <netdb.h> +#include <sys/socket.h> +#include <sys/un.h> +#if HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#if HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#if HAVE_NETINET_IP_H +#include <netinet/ip.h> /* superset of previous */ +#endif +#include <arpa/inet.h> +#include <netinet/tcp.h> +#include <pwd.h> +#include <sys/ioctl.h> +#include <sys/wait.h> +#include <grp.h> + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdarg.h> +#include <stdbool.h> +#include <errno.h> +#include <signal.h> +#include <libgen.h> +#ifdef HAVE_MALLOC_H +#include <malloc.h> /* for mallinfo on GNU */ +#endif +#include <unistd.h> /* KLB_FIX */ +#include <sys/stat.h> +#include <sys/types.h> +#include <dirent.h> /* KLB_FIX */ +#include <fcntl.h> +#include <math.h> +#if HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif +#if HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#include <time.h> +#ifdef BSD +#include <net/if.h> +#endif +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#include <semaphore.h> +#endif +#ifdef DARWIN +#include <dlfcn.h> +#include <semaphore.h> +#include <net/if.h> +#endif +#if defined(__linux__) || defined(GNU) +#include <net/if.h> +#endif +#ifdef SOLARIS +#include <sys/sockio.h> +#include <sys/filio.h> +#include <sys/loadavg.h> +#include <semaphore.h> +#endif +#if HAVE_UCRED_H +#include <ucred.h> +#endif +#if HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif +#if HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif +#include <errno.h> +#include <limits.h> + +#if HAVE_VFORK_H +#include <vfork.h> +#endif + +#include <ctype.h> +#if HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#if HAVE_ENDIAN_H +#include <endian.h> +#endif +#if HAVE_SYS_ENDIAN_H +#include <sys/endian.h> +#endif + +#define DIR_SEPARATOR '/' +#define DIR_SEPARATOR_STR "/" +#define PATH_SEPARATOR ':' +#define PATH_SEPARATOR_STR ":" +#define NEWLINE "\n" + + +#include <locale.h> +#include "gettext.h" +/** + * GNU gettext support macro. + */ +#define _(String) dgettext (PACKAGE, String) + + +#include <sys/mman.h> + +/* FreeBSD_kernel is not defined on the now discontinued kFreeBSD */ +#if defined(BSD) && defined(__FreeBSD__) && defined(__FreeBSD_kernel__) +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#endif + +#ifdef DARWIN +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +/* not available on darwin, override configure */ +#undef HAVE_STAT64 +#undef HAVE_MREMAP +#endif + +#if ! HAVE_ATOLL +long long +atoll (const char *nptr); + +#endif + +#if ENABLE_NLS +#include "langinfo.h" +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX ((size_t) (-1)) +#endif + +#ifndef O_LARGEFILE +#define O_LARGEFILE 0 +#endif + + +#if defined(__sparc__) +#define MAKE_UNALIGNED(val) ({ __typeof__((val)) __tmp; memmove (&__tmp, &(val), \ + sizeof((val))); \ + __tmp; }) +#else +#define MAKE_UNALIGNED(val) val +#endif + + +#ifndef PATH_MAX +/** + * Assumed maximum path length. + */ +#define PATH_MAX 4096 +#endif + +#if HAVE_THREAD_LOCAL_GCC +#define TALER_THREAD_LOCAL __thread +#else +#define TALER_THREAD_LOCAL +#endif + + /* LSB-style exit status codes */ #ifndef EXIT_INVALIDARGUMENT +/** + * Command-line arguments are invalid. + * Restarting useless. + */ #define EXIT_INVALIDARGUMENT 2 #endif #ifndef EXIT_NOTIMPLEMENTED +/** + * The requested operation is not implemented. + * Restarting useless. + */ #define EXIT_NOTIMPLEMENTED 3 #endif #ifndef EXIT_NOPERMISSION +/** + * Permissions needed to run are not available. + * Restarting useless. + */ #define EXIT_NOPERMISSION 4 #endif #ifndef EXIT_NOTINSTALLED +/** + * Key resources are not installed. + * Restarting useless. + */ #define EXIT_NOTINSTALLED 5 #endif #ifndef EXIT_NOTCONFIGURED +/** + * Key configuration settings are missing or invalid. + * Restarting useless. + */ #define EXIT_NOTCONFIGURED 6 #endif @@ -93,6 +275,25 @@ #endif +#ifndef EXIT_NO_RESTART +/** + * Exit code from 'main' if we do not want to be restarted, + * except by manual intervention (hard failure). + */ +#define EXIT_NO_RESTART 9 +#endif + + +/** + * clang et al do not have such an attribute + */ +#if __has_attribute (__nonstring__) +# define __nonstring __attribute__((__nonstring__)) +#else +# define __nonstring +#endif + + #endif /* PLATFORM_H_ */ /* end of platform.h */ diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h index c6d2f474e..937238d15 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -18,6 +18,10 @@ * @brief amount-representation utility functions * @author Sree Harsha Totakura <sreeharsha@totakura.in> */ +#if ! defined (__TALER_UTIL_LIB_H_INSIDE__) +#error "Only <taler_util.h> can be included directly." +#endif + #ifndef TALER_AMOUNT_LIB_H #define TALER_AMOUNT_LIB_H @@ -124,6 +128,16 @@ struct TALER_Amount /** + * Check that the currency code in @a str is well-formed. + * + * @param str currency code name to validate + * @return #GNUNET_OK if @a str is a valid currency code + */ +enum GNUNET_GenericReturnValue +TALER_check_currency (const char *str); + + +/** * Parse monetary amount, in the format "T:V.F". * * @param str amount string @@ -185,6 +199,18 @@ TALER_amount_is_valid (const struct TALER_Amount *amount); /** + * Test if the given amount is in the given currency + * + * @param amount amount to check + * @param currency currency to check for + * @return #GNUNET_OK if @a amount is in @a currency + */ +enum GNUNET_GenericReturnValue +TALER_amount_is_currency (const struct TALER_Amount *amount, + const char *currency); + + +/** * Convert amount from host to network representation. * * @param[out] res where to store amount in network representation @@ -386,7 +412,7 @@ TALER_amount_multiply (struct TALER_Amount *result, * #GNUNET_NO if value was already normalized * #GNUNET_SYSERR if value was invalid or could not be normalized */ -int +enum GNUNET_GenericReturnValue TALER_amount_normalize (struct TALER_Amount *amount); diff --git a/src/include/taler_attributes.h b/src/include/taler_attributes.h new file mode 100644 index 000000000..862a26928 --- /dev/null +++ b/src/include/taler_attributes.h @@ -0,0 +1,129 @@ +/* + This file is part of GNU Taler + Copyright (C) 2023 Taler Systems SA + + GNU Taler is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNU 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + SPDX-License-Identifier: LGPL3.0-or-later + + Note: the LGPL does not apply to all components of GNU Taler, + but it does apply to this file. + */ +/** + * @file src/include/taler_attributes.h + * @brief GNU Taler database event types, TO BE generated via https://gana.gnunet.org/ + */ +#ifndef GNU_TALER_ATTRIBUTES_H +#define GNU_TALER_ATTRIBUTES_H + +#ifdef __cplusplus +extern "C" { +#if 0 /* keep Emacsens' auto-indent happy */ +} +#endif +#endif + +/** + * Legal name of the business/company. + */ +#define TALER_ATTRIBUTE_COMPANY_NAME "company_name" + +/** + * Legal country of registration of the business/company, + * 2-letter country code using ISO 3166-2. + */ +#define TALER_ATTRIBUTE_REGISTRATION_COUNTRY "registration_country" + +/** + * Full name, when known/possible using "Lastname, Firstname(s)" format, + * but "Firstname(s) Lastname" or "Firstname M. Lastname" should also be + * tolerated (as is "Name", especially if the person only has one name). + * If the person has no name, an empty string must be given. + * NULL for not collected. + */ +#define TALER_ATTRIBUTE_FULL_NAME "full_name" + +/** + * True/false indicator if the individual is a politically + * exposed person. + */ +#define TALER_ATTRIBUTE_PEP "pep" + +/** + * Street-level address. Usually includes the street and the house number. May + * consist of multiple lines (separated by '\n'). Identifies a house in a city. The city is not + * part of the street. + */ +#define TALER_ATTRIBUTE_ADDRESS_STREET "street" + +/** + * City including postal code. If available, a 2-letter country-code prefixes + * the postal code, which is before the city (e.g. "DE-42289 Wuppertal"). If + * the country code is unknown, the "CC-" prefix is missing. If the ZIP code + * is unknown, the hyphen is followed by a space ("DE- Wuppertal"). If only + * the city name is known, it is prefixed by a space (" "). + * If the city name is unknown, a space is at the end of the value. + */ +#define TALER_ATTRIBUTE_ADDRESS_CITY "city" + +/** + * Phone number (of business or individual). Should come with the "+CC" + * prefix including the country code. + */ +#define TALER_ATTRIBUTE_PHONE "phone" + +/** + * Email address (of business or individual). Should be + * in the format "user@hostname". + */ +#define TALER_ATTRIBUTE_EMAIL "email" + +/** + * Birthdate of the person, as far as known. YYYY-MM-DD, a value + * of 0 (for DD, MM or even YYYY) is to be used for 'unknown' + * according to official records. + * Thus, 1950-00-00 stands for a birthdate in 1950 with unknown + * day and month. If official documents record January 1st or + * some other date instead, that day may also be specified. + * NULL for not collected. + */ +#define TALER_ATTRIBUTE_BIRTHDATE "birthdate" + +/** + * Citizenship(s) of the person using 2-letter country codes ("US", "DE", + * "FR", "IT", etc.) separated by commas if multiple citizenships are + * confirmed ("EN,US,DE"). Note that in the latter case it is not guaranteed + * that all nationalities were necessarily recorded. Empty string for + * stateless persons. NULL for not collected. + */ +#define TALER_ATTRIBUTE_NATIONALITIES "nationalities" + +/** + * Residence countries(s) of the person using 2-letter country codes ("US", + * "DE", "FR", "IT", etc.) separated by commas if multiple residences are + * confirmed ("EN,US,DE"). Note that in the latter case it is not guaranteed + * that all residences were necessarily recorded. Empty string for + * international nomads. NULL for not collected. + */ +#define TALER_ATTRIBUTE_RESIDENCES "residences" + + +#if 0 /* keep Emacsens' auto-indent happy */ +{ +#endif +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/include/taler_auditor_service.h b/src/include/taler_auditor_service.h index bc990a143..36ea781b1 100644 --- a/src/include/taler_auditor_service.h +++ b/src/include/taler_auditor_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -16,6 +16,8 @@ /** * @file include/taler_auditor_service.h * @brief C interface of libtalerauditor, a C library to use auditor's HTTP API + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff */ @@ -28,12 +30,12 @@ #include <gnunet/gnunet_curl_lib.h> -/* ********************* /version *********************** */ +/* ********************* /config *********************** */ /** - * @brief Information we get from the auditor about auditors. + * @brief Information we get from the auditor about itself. */ -struct TALER_AUDITOR_VersionInformation +struct TALER_AUDITOR_ConfigInformation { /** * Public key of the auditing institution. Wallets and merchants @@ -44,6 +46,11 @@ struct TALER_AUDITOR_VersionInformation struct TALER_AuditorPublicKeyP auditor_pub; /** + * Master public key of the audited exchange. + */ + struct TALER_MasterPublicKeyP exchange_master_public_key; + + /** * Supported Taler protocol version by the auditor. * String in the format current:revision:age using the * semantics of GNU libtool. See @@ -147,56 +154,90 @@ struct TALER_AUDITOR_HttpResponse /** + * Response to /config request. + */ +struct TALER_AUDITOR_ConfigResponse +{ + /** + * HTTP response. + */ + struct TALER_AUDITOR_HttpResponse hr; + + /** + * Details depending on HTTP status. + */ + union + { + + /** + * Details for #MHD_HTTP_OK. + */ + struct + { + + /** + * Protocol compatibility evaluation. + */ + enum TALER_AUDITOR_VersionCompatibility compat; + + /** + * Config data returned by /config. + */ + struct TALER_AUDITOR_ConfigInformation vi; + + } ok; + + } details; + +}; + + +/** * Function called with information about the auditor. * * @param cls closure - * @param hr HTTP response data - * @param vi basic information about the auditor - * @param compat protocol compatibility information + * @param vr response data */ typedef void -(*TALER_AUDITOR_VersionCallback) ( +(*TALER_AUDITOR_ConfigCallback) ( void *cls, - const struct TALER_AUDITOR_HttpResponse *hr, - const struct TALER_AUDITOR_VersionInformation *vi, - enum TALER_AUDITOR_VersionCompatibility compat); + const struct TALER_AUDITOR_ConfigResponse *vr); /** * @brief Handle to the auditor. This is where we interact with * a particular auditor and keep the per-auditor information. */ -struct TALER_AUDITOR_Handle; +struct TALER_AUDITOR_GetConfigHandle; /** - * Initialise a connection to the auditor. Will connect to the + * Obtain meta data about an auditor. Will connect to the * auditor and obtain information about the auditor's master public * key and the auditor's auditor. The respective information will - * be passed to the @a version_cb once available, and all future - * interactions with the auditor will be checked to be signed - * (where appropriate) by the respective master key. + * be passed to the @a config_cb once available. * - * @param ctx the context + * @param ctx the context for CURL requests * @param url HTTP base URL for the auditor - * @param version_cb function to call with the auditor's version information - * @param version_cb_cls closure for @a version_cb + * @param config_cb function to call with the auditor's config information + * @param config_cb_cls closure for @a config_cb * @return the auditor handle; NULL upon error */ -struct TALER_AUDITOR_Handle * -TALER_AUDITOR_connect (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_AUDITOR_VersionCallback version_cb, - void *version_cb_cls); +struct TALER_AUDITOR_GetConfigHandle * +TALER_AUDITOR_get_config (struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_AUDITOR_ConfigCallback config_cb, + void *config_cb_cls); /** - * Disconnect from the auditor. + * Cancel auditor config request. * - * @param auditor the auditor handle + * @param[in] auditor the auditor handle */ void -TALER_AUDITOR_disconnect (struct TALER_AUDITOR_Handle *auditor); +TALER_AUDITOR_get_config_cancel ( + struct TALER_AUDITOR_GetConfigHandle *auditor); /** @@ -206,16 +247,28 @@ struct TALER_AUDITOR_DepositConfirmationHandle; /** + * Response to /deposit-confirmation request. + */ +struct TALER_AUDITOR_DepositConfirmationResponse +{ + /** + * HTTP response. + */ + struct TALER_AUDITOR_HttpResponse hr; +}; + + +/** * Signature of functions called with the result from our call to the * auditor's /deposit-confirmation handler. * * @param cls closure - * @param hr HTTP response data + * @param dcr response data */ typedef void (*TALER_AUDITOR_DepositConfirmationResultCallback)( void *cls, - const struct TALER_AUDITOR_HttpResponse *hr); + const struct TALER_AUDITOR_DepositConfirmationResponse *dcr); /** @@ -225,21 +278,23 @@ typedef void * that the response is well-formed. If the auditor's reply is not * well-formed, we return an HTTP status code of zero to @a cb. * - * We also verify that the @a exchange_sig is valid for this deposit-confirmation - * request, and that the @a master_sig is a valid signature for @a - * exchange_pub. Also, the @a auditor must be ready to operate (i.e. have - * finished processing the /version reply). If either check fails, we do - * NOT initiate the transaction with the auditor and instead return NULL. + * We also verify that the @a exchange_sig is valid for this + * deposit-confirmation request, and that the @a master_sig is a valid + * signature for @a exchange_pub. If the check fails, we do NOT initiate the + * transaction with the auditor and instead return NULL. * - * @param auditor the auditor handle; the auditor must be ready to operate + * @param ctx the context for CURL requests + * @param url HTTP base URL for the auditor * @param h_wire hash of merchant wire details - * @param h_extensions hash over the extensions, if any + * @param h_policy hash over the policy, if any * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor) * @param exchange_timestamp timestamp when the contract was finalized, must not be too far in the future * @param wire_deadline date until which the exchange should wire the funds * @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant - * @param coin_pub coin’s public key + * @param total_without_fee the amount confirmed to be wired by the exchange to the merchant + * @param num_coins number of coins involved in the batch deposit + * @param coin_pubs array of the coin’s public keys + * @param coin_sigs array of the original deposit signatures of the coins in the batch * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) * @param exchange_sig the signature made with purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT * @param exchange_pub the public key of the exchange that matches @a exchange_sig @@ -255,22 +310,25 @@ typedef void */ struct TALER_AUDITOR_DepositConfirmationHandle * TALER_AUDITOR_deposit_confirmation ( - struct TALER_AUDITOR_Handle *auditor, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_ExtensionContractHash *h_extensions, - const struct TALER_PrivateContractHash *h_contract_terms, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute wire_deadline, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_Amount *amount_without_fee, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendPublicKeyP *coin_pubs[static num_coins], + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute ep_start, - struct GNUNET_TIME_Absolute ep_expire, - struct GNUNET_TIME_Absolute ep_end, + struct GNUNET_TIME_Timestamp ep_start, + struct GNUNET_TIME_Timestamp ep_expire, + struct GNUNET_TIME_Timestamp ep_end, const struct TALER_MasterSignatureP *master_sig, TALER_AUDITOR_DepositConfirmationResultCallback cb, void *cb_cls); @@ -287,72 +345,4 @@ TALER_AUDITOR_deposit_confirmation_cancel ( struct TALER_AUDITOR_DepositConfirmationHandle *deposit_confirmation); -/** - * Handle for /exchanges API returned by - * #TALER_AUDITOR_list_exchanges() so that the operation can be - * cancelled with #TALER_AUDITOR_list_exchanges_cancel() - */ -struct TALER_AUDITOR_ListExchangesHandle; - - -/** - * Information about an exchange kept by the auditor. - */ -struct TALER_AUDITOR_ExchangeInfo -{ - /** - * Master public key of the exchange. - */ - struct TALER_MasterPublicKeyP master_pub; - - /** - * Base URL of the exchange's API. - */ - const char *exchange_url; -}; - - -/** - * Function called with the result from /exchanges. - * - * @param cls closure - * @param hr HTTP response data - * @param num_exchanges length of array at @a ei - * @param ei information about exchanges returned by the auditor - */ -typedef void -(*TALER_AUDITOR_ListExchangesResultCallback)( - void *cls, - const struct TALER_AUDITOR_HttpResponse *hr, - unsigned int num_exchanges, - const struct TALER_AUDITOR_ExchangeInfo *ei); - -/** - * Submit an /exchanges request to the auditor and get the - * auditor's response. If the auditor's reply is not - * well-formed, we return an HTTP status code of zero to @a cb. - * - * @param auditor the auditor handle; the auditor must be ready to operate - * @param cb the callback to call when a reply for this request is available - * @param cb_cls closure for the above callback - * @return a handle for this request; NULL if the inputs are invalid (i.e. - * signatures fail to verify). In this case, the callback is not called. - */ -struct TALER_AUDITOR_ListExchangesHandle * -TALER_AUDITOR_list_exchanges (struct TALER_AUDITOR_Handle *auditor, - TALER_AUDITOR_ListExchangesResultCallback cb, - void *cb_cls); - - -/** - * Cancel a list exchanges request. This function cannot be used - * on a request handle if a response is already served for it. - * - * @param leh the list exchanges request handle - */ -void -TALER_AUDITOR_list_exchanges_cancel ( - struct TALER_AUDITOR_ListExchangesHandle *leh); - - #endif /* _TALER_AUDITOR_SERVICE_H */ diff --git a/src/include/taler_auditordb_plugin.h b/src/include/taler_auditordb_plugin.h index 7756db2bc..c0a771343 100644 --- a/src/include/taler_auditordb_plugin.h +++ b/src/include/taler_auditordb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,26 +25,12 @@ #include <jansson.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_db_lib.h> +#include "taler_util.h" #include "taler_auditordb_lib.h" #include "taler_signatures.h" /** - * Function called with information about exchanges this - * auditor is monitoring. - * - * @param cls closure - * @param master_pub master public key of the exchange - * @param exchange_url base URL of the exchange's API - */ -typedef void -(*TALER_AUDITORDB_ExchangeCallback)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *exchange_url); - - -/** * Function called with the results of select_historic_denom_revenue() * * @param cls closure @@ -62,8 +48,8 @@ typedef void typedef enum GNUNET_GenericReturnValue (*TALER_AUDITORDB_HistoricDenominationRevenueDataCallback)( void *cls, - const struct TALER_DenominationHash *denom_pub_hash, - struct GNUNET_TIME_Absolute revenue_timestamp, + const struct TALER_DenominationHashP *denom_pub_hash, + struct GNUNET_TIME_Timestamp revenue_timestamp, const struct TALER_Amount *revenue_balance, const struct TALER_Amount *loss_balance); @@ -84,268 +70,207 @@ typedef enum GNUNET_GenericReturnValue typedef enum GNUNET_GenericReturnValue (*TALER_AUDITORDB_HistoricReserveRevenueDataCallback)( void *cls, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, const struct TALER_Amount *reserve_profits); /** - * Structure for remembering the wire auditor's progress over the - * various tables and (auditor) transactions. + * Information about a signing key of an exchange. */ -struct TALER_AUDITORDB_WireProgressPoint +struct TALER_AUDITORDB_ExchangeSigningKey { /** - * Time until which we have confirmed that all wire transactions - * that the exchange should do, have indeed been done. - */ - struct GNUNET_TIME_Absolute last_timestamp; - - /** - * reserves_close uuid until which we have checked - * reserve closures. - */ - uint64_t last_reserve_close_uuid; -}; - - -/** - * Structure for remembering the wire auditor's progress over the - * various tables and (auditor) transactions per wire account. - */ -struct TALER_AUDITORDB_WireAccountProgressPoint -{ - /** - * serial ID of the last reserve_in transfer the wire auditor processed + * When does @e exchange_pub start to be used? */ - uint64_t last_reserve_in_serial_id; + struct GNUNET_TIME_Timestamp ep_start; /** - * serial ID of the last wire_out the wire auditor processed - */ - uint64_t last_wire_out_serial_id; - -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing reserves. - */ -struct TALER_AUDITORDB_ProgressPointReserve -{ - /** - * serial ID of the last reserve_in transfer the auditor processed + * When will the exchange stop signing with @e exchange_pub? */ - uint64_t last_reserve_in_serial_id; + struct GNUNET_TIME_Timestamp ep_expire; /** - * serial ID of the last reserve_out the auditor processed + * When does the signing key expire (for legal disputes)? */ - uint64_t last_reserve_out_serial_id; + struct GNUNET_TIME_Timestamp ep_end; /** - * serial ID of the last recoup entry the auditor processed when - * considering reserves. + * What is the public offline signing key this is all about? */ - uint64_t last_reserve_recoup_serial_id; + struct TALER_ExchangePublicKeyP exchange_pub; /** - * serial ID of the last reserve_close - * entry the auditor processed. + * Signature by the offline master key affirming the above. */ - uint64_t last_reserve_close_serial_id; - + struct TALER_MasterSignatureP master_sig; }; /** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing reserves. + * Information about a deposit confirmation we received from + * a merchant. */ -struct TALER_AUDITORDB_ProgressPointDepositConfirmation +struct TALER_AUDITORDB_DepositConfirmation { + /** - * serial ID of the last deposit_confirmation the auditor processed + * Hash over the contract for which this deposit is made. */ - uint64_t last_deposit_confirmation_serial_id; - -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing aggregations. - */ -struct TALER_AUDITORDB_ProgressPointAggregation -{ + struct TALER_PrivateContractHashP h_contract_terms; /** - * serial ID of the last prewire transfer the auditor processed + * Hash over the policy extension for the deposit. */ - uint64_t last_wire_out_serial_id; -}; + struct TALER_ExtensionPolicyHashP h_policy; - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing coins. - */ -struct TALER_AUDITORDB_ProgressPointCoin -{ /** - * serial ID of the last withdraw the auditor processed + * Hash over the wiring information of the merchant. */ - uint64_t last_withdraw_serial_id; + struct TALER_MerchantWireHashP h_wire; /** - * serial ID of the last deposit the auditor processed + * Time when this deposit confirmation was generated by the exchange. */ - uint64_t last_deposit_serial_id; + struct GNUNET_TIME_Timestamp exchange_timestamp; /** - * serial ID of the last refresh the auditor processed + * How much time does the @e merchant have to issue a refund + * request? Zero if refunds are not allowed. After this time, the + * coin cannot be refunded. Note that the wire transfer will not be + * performed by the exchange until the refund deadline. This value + * is taken from the original deposit request. */ - uint64_t last_melt_serial_id; + struct GNUNET_TIME_Timestamp refund_deadline; /** - * serial ID of the last refund the auditor processed + * How much time does the @e exchange have to wire the funds? */ - uint64_t last_refund_serial_id; + struct GNUNET_TIME_Timestamp wire_deadline; /** - * Serial ID of the last recoup operation the auditor processed. + * Amount to be deposited, excluding fee. Calculated from the + * amount with fee and the fee from the deposit request. */ - uint64_t last_recoup_serial_id; + struct TALER_Amount total_without_fee; /** - * Serial ID of the last recoup-of-refresh operation the auditor processed. + * Length of the @e coin_pubs and @e coin_sigs arrays. */ - uint64_t last_recoup_refresh_serial_id; - -}; - + unsigned int num_coins; -/** - * Information about a signing key of an exchange. - */ -struct TALER_AUDITORDB_ExchangeSigningKey -{ /** - * Public master key of the exchange that certified @e master_sig. + * Array of the coin public keys involved in the + * batch deposit operation. */ - struct TALER_MasterPublicKeyP master_public_key; + const struct TALER_CoinSpendPublicKeyP *coin_pubs; /** - * When does @e exchange_pub start to be used? + * Array of coin deposit signatures from the deposit operation. */ - struct GNUNET_TIME_Absolute ep_start; + const struct TALER_CoinSpendSignatureP *coin_sigs; /** - * When will the exchange stop signing with @e exchange_pub? + * The Merchant's public key. Allows the merchant to later refund + * the transaction or to inquire about the wire transfer identifier. */ - struct GNUNET_TIME_Absolute ep_expire; + struct TALER_MerchantPublicKeyP merchant; /** - * When does the signing key expire (for legal disputes)? + * Signature from the exchange of type + * #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. */ - struct GNUNET_TIME_Absolute ep_end; + struct TALER_ExchangeSignatureP exchange_sig; /** - * What is the public offline signing key this is all about? + * Public signing key from the exchange matching @e exchange_sig. */ struct TALER_ExchangePublicKeyP exchange_pub; /** - * Signature by the offline master key affirming the above. + * Exchange master signature over @e exchange_sig. */ struct TALER_MasterSignatureP master_sig; + }; /** - * Information about a deposit confirmation we received from - * a merchant. + * Balance values for a reserve (or all reserves). */ -struct TALER_AUDITORDB_DepositConfirmation +struct TALER_AUDITORDB_ReserveFeeBalance { - /** - * Hash over the contract for which this deposit is made. + * Remaining funds. */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_Amount reserve_balance; /** - * Hash over the extensions for the deposit. + * Losses from operations that should not have + * happened (e.g. negative balance). */ - struct TALER_ExtensionContractHash h_extensions; + struct TALER_Amount reserve_loss; /** - * Hash over the wiring information of the merchant. + * Fees charged for withdraw. */ - struct TALER_MerchantWireHash h_wire; + struct TALER_Amount withdraw_fee_balance; /** - * Time when this deposit confirmation was generated by the exchange. + * Fees charged for closing. */ - struct GNUNET_TIME_Absolute exchange_timestamp; + struct TALER_Amount close_fee_balance; /** - * How much time does the @e merchant have to issue a refund - * request? Zero if refunds are not allowed. After this time, the - * coin cannot be refunded. Note that the wire transfer will not be - * performed by the exchange until the refund deadline. This value - * is taken from the original deposit request. + * Fees charged for purse creation. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct TALER_Amount purse_fee_balance; /** - * How much time does the @e exchange have to wire the funds? + * Opening fees charged. */ - struct GNUNET_TIME_Absolute wire_deadline; + struct TALER_Amount open_fee_balance; /** - * Amount to be deposited, excluding fee. Calculated from the - * amount with fee and the fee from the deposit request. + * History fees charged. */ - struct TALER_Amount amount_without_fee; + struct TALER_Amount history_fee_balance; +}; - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_CoinSpendPublicKeyP coin_pub; +/** + * Balance data for denominations in circulation. + */ +struct TALER_AUDITORDB_DenominationCirculationData +{ /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. + * Amount of outstanding coins in circulation. */ - struct TALER_MerchantPublicKeyP merchant; + struct TALER_Amount denom_balance; /** - * Signature from the exchange of type - * #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. + * Amount lost due coins illicitly accepted (effectively, a + * negative @a denom_balance). */ - struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_Amount denom_loss; /** - * Public signing key from the exchange matching @e exchange_sig. + * Total amount that could still be theoretically lost in the future due to + * recoup operations. (Total put into circulation minus @e recoup_loss). */ - struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_Amount denom_risk; /** - * Exchange master signature over @e exchange_sig. + * Amount lost due to recoups. */ - struct TALER_MasterSignatureP master_sig; + struct TALER_Amount recoup_loss; /** - * Master public key of the exchange corresponding to @e master_sig. - * Identifies the exchange this is about. + * Number of coins of this denomination that the exchange signed into + * existence. */ - struct TALER_MasterPublicKeyP master_public_key; - + uint64_t num_issued; }; @@ -366,6 +291,42 @@ typedef enum GNUNET_GenericReturnValue /** + * Function called on deposits that are past their due date + * and have not yet seen a wire transfer. + * + * @param cls closure + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline + */ +typedef void +(*TALER_AUDITORDB_WireMissingCallback)( + void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline); + + +/** + * Function called on expired purses. + * + * @param cls closure + * @param purse_pub public key of the purse + * @param balance amount of money in the purse + * @param expiration_date when did the purse expire? + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_AUDITORDB_ExpiredPurseCallback)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp expiration_date); + + +/** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. * @@ -400,6 +361,48 @@ struct TALER_AUDITORDB_Plugin /** + * Register callback to be invoked on events of type @a es. + * + * @param cls database context to use + * @param es specification of the event to listen for + * @param timeout how long to wait for the event + * @param cb function to call when the event happens, possibly + * mulrewardle times (until cancel is invoked) + * @param cb_cls closure for @a cb + * @return handle useful to cancel the listener + */ + struct GNUNET_DB_EventHandler * + (*event_listen)(void *cls, + const struct GNUNET_DB_EventHeaderP *es, + struct GNUNET_TIME_Relative timeout, + GNUNET_DB_EventCallback cb, + void *cb_cls); + + /** + * Stop notifications. + * + * @param eh handle to unregister. + */ + void + (*event_listen_cancel)(struct GNUNET_DB_EventHandler *eh); + + + /** + * Notify all that listen on @a es of an event. + * + * @param cls database context to use + * @param es specification of the event to generate + * @param extra additional event data provided + * @param extra_size number of bytes in @a extra + */ + void + (*event_notify)(void *cls, + const struct GNUNET_DB_EventHeaderP *es, + const void *extra, + size_t extra_size); + + + /** * Drop all auditor tables OR deletes recoverable auditor state. * This should only be used by testcases or when restarting the * auditor from scratch. @@ -412,17 +415,21 @@ struct TALER_AUDITORDB_Plugin */ enum GNUNET_GenericReturnValue (*drop_tables)(void *cls, - int drop_exchangelist); + bool drop_exchangelist); /** * Create the necessary tables if they are not present * * @param cls the @e cls of this struct with the plugin-specific state + * @param support_partitions true to support partitioning + * @param num_partitions number of partitions to use * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*create_tables)(void *cls); + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); /** @@ -467,197 +474,21 @@ struct TALER_AUDITORDB_Plugin /** - * Insert information about an exchange this auditor will be auditing. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param exchange_url public (base) URL of the API of the exchange - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_exchange)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *exchange_url); - - - /** - * Delete an exchange from the list of exchanges this auditor is auditing. - * Warning: this will cascade and delete all knowledge of this auditor related - * to this exchange! - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*delete_exchange)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub); - - - /** - * Obtain information about exchanges this auditor is auditing. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param cb function to call with the results - * @param cb_cls closure for @a cb - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*list_exchanges)(void *cls, - TALER_AUDITORDB_ExchangeCallback cb, - void *cb_cls); - - /** - * Insert information about a signing key of the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param sk signing key information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_exchange_signkey)( - void *cls, - const struct TALER_AUDITORDB_ExchangeSigningKey *sk); - - - /** - * Insert information about a deposit confirmation into the database. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param dc deposit confirmation information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_deposit_confirmation)( - void *cls, - const struct TALER_AUDITORDB_DepositConfirmation *dc); - - - /** - * Get information about deposit confirmations from the database. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_public_key for which exchange do we want to get deposit confirmations - * @param start_id row/serial ID where to start the iteration (0 from - * the start, exclusive, i.e. serial_ids must start from 1) - * @param cb function to call with results - * @param cb_cls closure for @a cb - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*get_deposit_confirmations)( - void *cls, - const struct TALER_MasterPublicKeyP *master_public_key, - uint64_t start_id, - TALER_AUDITORDB_DepositConfirmationCallback cb, - void *cb_cls); - - - /** - * Insert information about the auditor's progress with an exchange's - * data. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppc where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_coin)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); - - - /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppc where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_coin)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); - - - /** - * Get information about the progress of the auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] ppc set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_auditor_progress_coin)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointCoin *ppc); - - /** - * Insert information about the auditor's progress with an exchange's - * data. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppr where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_reserve)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointReserve *ppr); - - - /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppr where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_reserve)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointReserve *ppr); - - - /** - * Get information about the progress of the auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] ppr set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_auditor_progress_reserve)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointReserve *ppr); - - /** * Insert information about the auditor's progress with an exchange's * data. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppdc where is the auditor in processing + * @param progress_key name of the progress indicator + * @param progress_offset offset until which we have made progress + * @param ... NULL terminated list of additional key-value pairs to insert * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_deposit_confirmation)( + (*insert_auditor_progress)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + const char *progress_key, + uint64_t progress_offset, + ...); /** @@ -665,191 +496,142 @@ struct TALER_AUDITORDB_Plugin * must be an existing record for the exchange. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppdc where is the auditor in processing + * @param progress_key name of the progress indicator + * @param progress_offset offset until which we have made progress + * @param ... NULL terminated list of additional key-value pairs to update * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_auditor_progress_deposit_confirmation)( + (*update_auditor_progress)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + const char *progress_key, + uint64_t progress_offset, + ...); /** * Get information about the progress of the auditor. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] ppdc set to where the auditor is in processing + * @param progress_key name of the progress indicator + * @param[out] progress_offset set to offset until which we have made progress, set to 0 if key was not found + * @param ... NULL terminated list of additional key-value pairs to fetch * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_auditor_progress_deposit_confirmation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + (*get_auditor_progress)(void *cls, + const char *progress_key, + uint64_t *progress_offset, + ...); /** - * Insert information about the auditor's progress with an exchange's - * data. + * Insert information about a balance tracked by the auditor. There must not be an + * existing record. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppa where is the auditor in processing + * @param balance_key key of the balance to store + * @param balance_value value to store + * @param ... NULL terminated list of additional key-value pairs to insert * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_aggregation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointAggregation *ppa); + (*insert_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_value, + ...); /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param ppa where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_aggregation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointAggregation *ppa); - - - /** - * Get information about the progress of the auditor. + * Insert information about a balance tracked by the auditor. Destructively updates an + * existing record, which must already exist. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] ppa set to where the auditor is in processing + * @param balance_key key of the balance to store + * @param balance_amount value to store + * @param ... NULL terminated list of additional key-value pairs to update * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_auditor_progress_aggregation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointAggregation *ppa); + (*update_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_amount, + ...); /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * Get summary information about balance tracked by the auditor. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @param in_wire_off how far are we in the incoming wire transaction history - * @param out_wire_off how far are we in the outgoing wire transaction history + * @param balance_key key of the balance to store + * @param[out] balance_value set to amount stored under @a balance_key, set to invalid amount (all zero) if key was not found + * @param ... NULL terminated list of additional key-value pairs to fetch * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_auditor_account_progress)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t in_wire_off, - uint64_t out_wire_off); + (*get_balance)(void *cls, + const char *balance_key, + struct TALER_Amount *balance_value, + ...); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * Insert information about a signing key of the exchange. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @param in_wire_off how far are we in the incoming wire transaction history - * @param out_wire_off how far are we in the outgoing wire transaction history - * @return transaction status code + * @param sk signing key information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*update_wire_auditor_account_progress)( + (*insert_exchange_signkey)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t in_wire_off, - uint64_t out_wire_off); + const struct TALER_AUDITORDB_ExchangeSigningKey *sk); /** - * Get information about the progress of the wire auditor. + * Insert information about a deposit confirmation into the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param[out] pp where is the auditor in processing - * @param[out] in_wire_off how far are we in the incoming wire transaction history - * @param[out] out_wire_off how far are we in the outgoing wire transaction history - * @return transaction status code + * @param dc deposit confirmation information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*get_wire_auditor_account_progress)( + (*insert_deposit_confirmation)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t *in_wire_off, - uint64_t *out_wire_off); + const struct TALER_AUDITORDB_DepositConfirmation *dc); /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * Get information about deposit confirmations from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @return transaction status code + * @param start_id row/serial ID where to start the iteration (0 from + * the start, exclusive, i.e. serial_ids must start from 1) + * @param return_suppressed should suppressed rows be returned anyway? + * @param cb function to call with results + * @param cb_cls closure for @a cb + * @return query result status */ enum GNUNET_DB_QueryStatus - (*insert_wire_auditor_progress)( + (*get_deposit_confirmations)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_WireProgressPoint *pp); + uint64_t start_id, + bool return_suppressed, + TALER_AUDITORDB_DepositConfirmationCallback cb, + void *cb_cls); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * Delete information about a deposit confirmation from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @return transaction status code + * @param row_id row to delete + * @return query result status */ enum GNUNET_DB_QueryStatus - (*update_wire_auditor_progress)( + (*delete_deposit_confirmation)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_WireProgressPoint *pp); - - - /** - * Get information about the progress of the wire auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param[out] pp set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_wire_auditor_progress)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_WireProgressPoint *pp); + uint64_t row_id); /** @@ -858,22 +640,18 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param rfb balance amounts for the reserve * @param expiration_date expiration date of the reserve * @param origin_account where did the money in the reserve originally come from * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_reserve_info)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute expiration_date, - const char *origin_account); + (*insert_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp expiration_date, + const char *origin_account); /** @@ -882,20 +660,16 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param rfb balance amounts for the reserve * @param expiration_date expiration date of the reserve * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_reserve_info)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute expiration_date); + (*update_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp expiration_date); /** @@ -903,24 +677,20 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange * @param[out] rowid which row did we get the information from - * @param[out] reserve_balance amount stored in the reserve - * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param[out] rfb set to balances associated with the reserve * @param[out] expiration_date expiration date of the reserve * @param[out] sender_account from where did the money in the reserve originally come from * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_info)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - uint64_t *rowid, - struct TALER_Amount *reserve_balance, - struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute *expiration_date, - char **sender_account); + (*get_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *rowid, + struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp *expiration_date, + char **sender_account); /** @@ -928,277 +698,202 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange * @return transaction status code */ enum GNUNET_DB_QueryStatus (*del_reserve_info)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub); + const struct TALER_ReservePublicKeyP *reserve_pub); /** - * Insert information about all reserves. There must not be an - * existing record for the @a master_pub. + * Insert new row into the pending deposits table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the requested wire transfer deadline * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_reserve_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance); + (*insert_pending_deposit)( + void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_PaytoHashP *wire_target_h_payto, + const struct TALER_Amount *total_amount, + struct GNUNET_TIME_Timestamp deadline); /** - * Update information about all reserves. Destructively updates an - * existing record, which must already exist. + * Delete a row from the pending deposit table. + * Usually done when the respective wire transfer + * was finally detected. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param batch_deposit_serial_id which entry to delete * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_reserve_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance); + (*delete_pending_deposit)( + void *cls, + uint64_t batch_deposit_serial_id); /** - * Get summary information about all reserves. + * Return (batch) deposits for which we have not yet + * seen the required wire transfer. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param[out] reserve_balance amount stored in the reserve - * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param deadline only return up to this deadline + * @param cb function to call on each entry + * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *reserve_balance, - struct TALER_Amount *withdraw_fee_balance); + (*select_pending_deposits)( + void *cls, + struct GNUNET_TIME_Absolute deadline, + TALER_AUDITORDB_WireMissingCallback cb, + void *cb_cls); /** - * Insert information about exchange's wire fee balance. There must not be an - * existing record for the same @a master_pub. + * Insert information about a purse. There must not be an + * existing record for the purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param wire_fee_balance amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param balance balance of the purse + * @param expiration_date expiration date of the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_fee_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *wire_fee_balance); + (*insert_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp expiration_date); /** - * Insert information about exchange's wire fee balance. Destructively updates an + * Update information about a purse. Destructively updates an * existing record, which must already exist. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param wire_fee_balance amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param balance new balance for the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_wire_fee_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *wire_fee_balance); + (*update_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); /** - * Get summary information about an exchanges wire fee balance. + * Get information about a purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param[out] wire_fee_balance set amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param[out] rowid which row did we get the information from + * @param[out] balance set to balance of the purse + * @param[out] expiration_date expiration date of the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_wire_fee_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *wire_fee_balance); + (*get_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + uint64_t *rowid, + struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp *expiration_date); /** - * Insert information about a denomination key's balances. There - * must not be an existing record for the denomination key. + * Delete information about a purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param denom_pub_hash hash of the denomination public key - * @param denom_balance value of coins outstanding with this denomination key - * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param denom_risk value of coins issued with this denomination key - * @param denom_recoup value of coins paid back if this denomination key was revoked - * @param num_issued how many coins of this denomination did the exchange blind-sign + * @param purse_pub public key of the reserve * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_denomination_balance)(void *cls, - const struct - TALER_DenominationHash *denom_pub_hash, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *denom_loss, - const struct TALER_Amount *denom_risk, - const struct TALER_Amount *recoup_loss, - uint64_t num_issued); + (*delete_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub); /** - * Update information about a denomination key's balances. There - * must be an existing record for the denomination key. + * Get information about expired purses. * * @param cls the @e cls of this struct with the plugin-specific state - * @param denom_pub_hash hash of the denomination public key - * @param denom_balance value of coins outstanding with this denomination key - * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param denom_risk value of coins issued with this denomination key - * @param denom_recoup value of coins paid back if this denomination key was revoked - * @param num_issued how many coins of this denomination did the exchange blind-sign + * @param cb function to call on expired purses + * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_denomination_balance)(void *cls, - const struct - TALER_DenominationHash *denom_pub_hash, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *denom_loss, - const struct TALER_Amount *denom_risk, - const struct TALER_Amount *recoup_loss, - uint64_t num_issued); + (*select_purse_expired)( + void *cls, + TALER_AUDITORDB_ExpiredPurseCallback cb, + void *cb_cls); /** - * Get information about a denomination key's balances. + * Insert information about a denomination key's balances. There + * must not be an existing record for the denomination key. * * @param cls the @e cls of this struct with the plugin-specific state * @param denom_pub_hash hash of the denomination public key - * @param[out] denom_balance value of coins outstanding with this denomination key - * @param[out] denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param[out] denom_risk value of coins issued with this denomination key - * @param[out] denom_recoup value of coins paid back if this denomination key was revoked - * @param[out] num_issued how many coins of this denomination did the exchange blind-sign + * @param dcd denomination circulation data to store * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_denomination_balance)(void *cls, - const struct - TALER_DenominationHash *denom_pub_hash, - struct TALER_Amount *denom_balance, - struct TALER_Amount *denom_loss, - struct TALER_Amount *denom_risk, - struct TALER_Amount *recoup_loss, - uint64_t *num_issued); + (*insert_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** - * Delete information about a denomination key's balances. + * Update information about a denomination key's balances. There + * must be an existing record for the denomination key. * * @param cls the @e cls of this struct with the plugin-specific state * @param denom_pub_hash hash of the denomination public key + * @param dcd denomination circulation data to store * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*del_denomination_balance)(void *cls, - const struct - TALER_DenominationHash *denom_pub_hash); - - - /** - * Insert information about an exchange's denomination balances. There - * must not be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param denom_balance value of coins outstanding with this denomination key - * @param deposit_fee_balance total deposit fees collected for this DK - * @param melt_fee_balance total melt fees collected for this DK - * @param refund_fee_balance total refund fees collected for this DK - * @param risk maximum risk exposure of the exchange - * @param recoup_loss actual losses from recoup (actualized @a risk) - * @param irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_balance_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *deposit_fee_balance, - const struct TALER_Amount *melt_fee_balance, - const struct TALER_Amount *refund_fee_balance, - const struct TALER_Amount *risk, - const struct TALER_Amount *recoup_loss, - const struct TALER_Amount *irregular_recoups); - + (*update_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** - * Update information about an exchange's denomination balances. There - * must be an existing record for the exchange. + * Delete information about a denomination key's balances. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param denom_balance value of coins outstanding with this denomination key - * @param deposit_fee_balance total deposit fees collected for this DK - * @param melt_fee_balance total melt fees collected for this DK - * @param refund_fee_balance total refund fees collected for this DK - * @param risk maximum risk exposure of the exchange - * @param recoup_loss actual losses from recoup (actualized @a risk) - * @param irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) + * @param denom_pub_hash hash of the denomination public key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_balance_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *deposit_fee_balance, - const struct TALER_Amount *melt_fee_balance, - const struct TALER_Amount *refund_fee_balance, - const struct TALER_Amount *risk, - const struct TALER_Amount *recoup_loss, - const struct TALER_Amount *irregular_recoups); + (*del_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash); /** - * Get information about an exchange's denomination balances. + * Get information about a denomination key's balances. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] denom_balance value of coins outstanding with this denomination key - * @param[out] deposit_fee_balance total deposit fees collected for this DK - * @param[out] melt_fee_balance total melt fees collected for this DK - * @param[out] refund_fee_balance total refund fees collected for this DK - * @param[out] risk maximum risk exposure of the exchange - * @param[out] recoup_loss actual losses from recoup (actualized @a risk) - * @param[out] irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) + * @param denom_pub_hash hash of the denomination public key + * @param[out] dcd denomination circulation data to initialize * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_balance_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *denom_balance, - struct TALER_Amount *deposit_fee_balance, - struct TALER_Amount *melt_fee_balance, - struct TALER_Amount *refund_fee_balance, - struct TALER_Amount *risk, - struct TALER_Amount *recoup_loss, - struct TALER_Amount *irregular_recoup); + (*get_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** @@ -1206,7 +901,6 @@ struct TALER_AUDITORDB_Plugin * revenue about a denomination key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange * @param denom_pub_hash hash of the denomination key * @param revenue_timestamp when did this profit get realized * @param revenue_balance what was the total profit made from @@ -1218,19 +912,16 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_denom_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_DenominationHash *denom_pub_hash, - struct GNUNET_TIME_Absolute revenue_timestamp, + const struct TALER_DenominationHashP *denom_pub_hash, + struct GNUNET_TIME_Timestamp revenue_timestamp, const struct TALER_Amount *revenue_balance, const struct TALER_Amount *recoup_loss_balance); /** - * Obtain all of the historic denomination key revenue - * of the given @a master_pub. + * Obtain all of the historic denomination key revenue. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange * @param cb function to call with the results * @param cb_cls closure for @a cb * @return transaction status code @@ -1238,7 +929,6 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*select_historic_denom_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb, void *cb_cls); @@ -1247,7 +937,6 @@ struct TALER_AUDITORDB_Plugin * Insert information about an exchange's historic revenue from reserves. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange * @param start_time beginning of aggregated time interval * @param end_time end of aggregated time interval * @param reserve_profits total profits made @@ -1256,9 +945,8 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_reserve_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, const struct TALER_Amount *reserve_profits); @@ -1266,7 +954,6 @@ struct TALER_AUDITORDB_Plugin * Return information about an exchange's historic revenue from reserves. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange * @param cb function to call with results * @param cb_cls closure for @a cb * @return transaction status code @@ -1274,55 +961,9 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*select_historic_reserve_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, TALER_AUDITORDB_HistoricReserveRevenueDataCallback cb, void *cb_cls); - - /** - * Insert information about the predicted exchange's bank - * account balance. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param balance what the bank account balance of the exchange should show - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_predicted_result)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance); - - - /** - * Update information about an exchange's predicted balance. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param balance what the bank account balance of the exchange should show - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_predicted_result)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance); - - - /** - * Get an exchange's predicted balance. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] balance expected bank account balance of the exchange - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_predicted_balance)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *balance); - - }; diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h index db78ca6a8..e8e32947b 100644 --- a/src/include/taler_bank_service.h +++ b/src/include/taler_bank_service.h @@ -100,24 +100,64 @@ struct TALER_BANK_AdminAddIncomingHandle; /** + * Response details for a history request. + */ +struct TALER_BANK_AdminAddIncomingResponse +{ + + /** + * HTTP status. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + /** + * unique ID of the wire transfer in the bank's records + */ + uint64_t serial_id; + + /** + * time when the transaction was made. + */ + struct GNUNET_TIME_Timestamp timestamp; + + } ok; + + } details; + +}; + +/** * Callbacks of this type are used to return the result of submitting * a request to transfer funds to the exchange. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol) - * @param ec detailed error code - * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error - * @param timestamp time when the transaction was made. - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON + * @param air response details */ typedef void -(*TALER_BANK_AdminAddIncomingCallback) (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - struct GNUNET_TIME_Absolute timestamp, - const json_t *json); +(*TALER_BANK_AdminAddIncomingCallback) ( + void *cls, + const struct TALER_BANK_AdminAddIncomingResponse *air); /** @@ -190,20 +230,64 @@ struct TALER_BANK_TransferHandle; /** + * Response details for a history request. + */ +struct TALER_BANK_TransferResponse +{ + + /** + * HTTP status. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + + /** + * unique ID of the wire transfer in the bank's records + */ + uint64_t row_id; + + /** + * when did the transaction go into effect + */ + struct GNUNET_TIME_Timestamp timestamp; + + } ok; + } details; +}; + + +/** * Function called with the result from the execute step. * * @param cls closure - * @param response_code HTTP status code - * @param ec taler error code - * @param row_id unique ID of the wire transfer in the bank's records - * @param timestamp when did the transaction go into effect + * @param tr response details */ typedef void -(*TALER_BANK_TransferCallback)(void *cls, - unsigned int response_code, - enum TALER_ErrorCode ec, - uint64_t row_id, - struct GNUNET_TIME_Absolute timestamp); +(*TALER_BANK_TransferCallback)( + void *cls, + const struct TALER_BANK_TransferResponse *tr); /** @@ -259,6 +343,11 @@ struct TALER_BANK_CreditHistoryHandle; struct TALER_BANK_CreditDetails { /** + * Serial ID of the wire transfer. + */ + uint64_t serial_id; + + /** * Amount that was transferred */ struct TALER_Amount amount; @@ -266,25 +355,75 @@ struct TALER_BANK_CreditDetails /** * Time of the the transfer */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** - * Reserve public key encoded in the wire - * transfer subject. + * Reserve public key encoded in the wire transfer subject. */ struct TALER_ReservePublicKeyP reserve_pub; /** - * payto://-URL of the source account that - * send the funds. + * payto://-URL of the source account that send the funds. */ const char *debit_account_uri; +}; + + +/** + * Response details for a history request. + */ +struct TALER_BANK_CreditHistoryResponse +{ + /** - * payto://-URL of the target account that - * received the funds. + * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both + * successful replies, but @e details will only contain @e success information + * if this is set to #MHD_HTTP_OK. */ - const char *credit_account_uri; + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + /** + * payto://-URL of the target account that received the funds. + */ + const char *credit_account_uri; + + /** + * Array of transactions received. + */ + const struct TALER_BANK_CreditDetails *details; + + /** + * Length of the @e details array. + */ + unsigned int details_length; + + } ok; + + } details; + }; @@ -293,25 +432,12 @@ struct TALER_BANK_CreditDetails * the bank for the credit transaction history. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol), - * #MHD_HTTP_NO_CONTENT if there are no more results; on success the - * last callback is always of this status (even if `abs(num_results)` were - * already returned). - * @param ec detailed error code - * @param serial_id monotonically increasing counter corresponding to the transaction - * @param details details about the wire transfer - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration + * @param reply details about the response */ -typedef enum GNUNET_GenericReturnValue +typedef void (*TALER_BANK_CreditHistoryCallback)( void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - const struct TALER_BANK_CreditDetails *details, - const json_t *json); + const struct TALER_BANK_CreditHistoryResponse *reply); /** @@ -332,13 +458,14 @@ typedef enum GNUNET_GenericReturnValue * In this case, the callback is not called. */ struct TALER_BANK_CreditHistoryHandle * -TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx, - const struct TALER_BANK_AuthenticationData *auth, - uint64_t start_row, - int64_t num_results, - struct GNUNET_TIME_Relative timeout, - TALER_BANK_CreditHistoryCallback hres_cb, - void *hres_cb_cls); +TALER_BANK_credit_history ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + uint64_t start_row, + int64_t num_results, + struct GNUNET_TIME_Relative timeout, + TALER_BANK_CreditHistoryCallback hres_cb, + void *hres_cb_cls); /** @@ -367,6 +494,11 @@ struct TALER_BANK_DebitHistoryHandle; struct TALER_BANK_DebitDetails { /** + * Serial ID of the wire transfer. + */ + uint64_t serial_id; + + /** * Amount that was transferred */ struct TALER_Amount amount; @@ -374,7 +506,7 @@ struct TALER_BANK_DebitDetails /** * Time of the the transfer */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Wire transfer identifier used by the exchange. @@ -387,16 +519,66 @@ struct TALER_BANK_DebitDetails const char *exchange_base_url; /** - * payto://-URI of the source account that - * send the funds. + * payto://-URI of the target account that received the funds. */ - const char *debit_account_uri; + const char *credit_account_uri; + +}; + + +/** + * Response details for a history request. + */ +struct TALER_BANK_DebitHistoryResponse +{ /** - * payto://-URI of the target account that - * received the funds. + * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both + * successful replies, but @e details will only contain @e success information + * if this is set to #MHD_HTTP_OK. */ - const char *credit_account_uri; + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + /** + * payto://-URI of the source account that send the funds. + */ + const char *debit_account_uri; + + /** + * Array of transactions initiated. + */ + const struct TALER_BANK_DebitDetails *details; + + /** + * Length of the @e details array. + */ + unsigned int details_length; + + } ok; + + } details; }; @@ -406,25 +588,12 @@ struct TALER_BANK_DebitDetails * the bank for the debit transaction history. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol), - * #MHD_HTTP_NO_CONTENT if there are no more results; on success the - * last callback is always of this status (even if `abs(num_results)` were - * already returned). - * @param ec detailed error code - * @param serial_id monotonically increasing counter corresponding to the transaction - * @param details details about the wire transfer - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration + * @param reply details about the response */ -typedef enum GNUNET_GenericReturnValue +typedef void (*TALER_BANK_DebitHistoryCallback)( void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - const struct TALER_BANK_DebitDetails *details, - const json_t *json); + const struct TALER_BANK_DebitHistoryResponse *reply); /** @@ -477,7 +646,7 @@ TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh); * @param[out] auth set to the configuration data found * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, struct TALER_BANK_AuthenticationData *auth); diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index ea53efb66..b941316b5 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,13 +18,88 @@ * @brief taler-specific crypto functions * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff <christian@grothoff.org> + * @author Özgür Kesim <oec-taler@kesim.org> */ +#if ! defined (__TALER_UTIL_LIB_H_INSIDE__) +#error "Only <taler_util.h> can be included directly." +#endif + #ifndef TALER_CRYPTO_LIB_H #define TALER_CRYPTO_LIB_H #include <gnunet/gnunet_util_lib.h> #include "taler_error_codes.h" #include <gcrypt.h> +#include <jansson.h> + + +/** + * Maximum number of coins we allow per operation. + */ +#define TALER_MAX_FRESH_COINS 256 + +/** + * Cut-and-choose size for refreshing. Client looses the gamble (of + * unaccountable transfers) with probability 1/TALER_CNC_KAPPA. Refresh cost + * increases linearly with TALER_CNC_KAPPA, and 3 is sufficient up to a + * income/sales tax of 66% of total transaction value. As there is + * no good reason to change this security parameter, we declare it + * fixed and part of the protocol. + */ +#define TALER_CNC_KAPPA 3 +#define TALER_CNC_KAPPA_MINUS_ONE_STR "2" + + +/** + * Possible AML decision states. + */ +enum TALER_AmlDecisionState +{ + + /** + * All AML requirements are currently satisfied. + */ + TALER_AML_NORMAL = 0, + + /** + * An AML investigation is pending. + */ + TALER_AML_PENDING = 1, + + /** + * An AML decision has concluded that the funds must be frozen. + */ + TALER_AML_FROZEN = 2, + + /** + * Maximum allowed numeric value for AML status. + */ + TALER_AML_MAX = 2 +}; + + +/** + * Possible algorithms for confirmation code generation. + */ +enum TALER_MerchantConfirmationAlgorithm +{ + + /** + * No purchase confirmation. + */ + TALER_MCA_NONE = 0, + + /** + * Purchase confirmation without payment + */ + TALER_MCA_WITHOUT_PRICE = 1, + + /** + * Purchase confirmation with payment + */ + TALER_MCA_WITH_PRICE = 2 + +}; /* ****************** Coin crypto primitives ************* */ @@ -44,6 +119,26 @@ struct TALER_SecurityModulePublicKeyP struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; }; +/** + * @brief Set of the public keys of the security modules + */ +struct TALER_SecurityModulePublicKeySetP +{ + /** + * Public key of the RSA security module + */ + struct TALER_SecurityModulePublicKeyP rsa; + + /** + * Public key of the CS security module + */ + struct TALER_SecurityModulePublicKeyP cs; + + /** + * Public key of the eddsa security module + */ + struct TALER_SecurityModulePublicKeyP eddsa; +}; /** * @brief Type of private keys for Taler security modules (software or hardware). @@ -106,6 +201,18 @@ struct TALER_ReserveSignatureP /** + * (Symmetric) key used to encrypt KYC attribute data in the database. + */ +struct TALER_AttributeKeyP +{ + /** + * Actual key material. + */ + struct GNUNET_HashCode key; +}; + + +/** * @brief Type of public keys to for merchant authorizations. * Merchants can issue refunds using the corresponding * private key. @@ -159,7 +266,7 @@ struct TALER_TransferPublicKeyP /** - * @brief Type of transfer public keys used during refresh + * @brief Type of transfer private keys used during refresh * operations. */ struct TALER_TransferPrivateKeyP @@ -172,6 +279,32 @@ struct TALER_TransferPrivateKeyP /** + * @brief Type of public keys used for contract + * encryption. + */ +struct TALER_ContractDiffiePublicP +{ + /** + * Taler uses ECDHE for contract encryption. + */ + struct GNUNET_CRYPTO_EcdhePublicKey ecdhe_pub; +}; + + +/** + * @brief Type of private keys used for contract + * encryption. + */ +struct TALER_ContractDiffiePrivateP +{ + /** + * Taler uses ECDHE for contract encryption. + */ + struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_priv; +}; + + +/** * @brief Type of online public keys used by the exchange to sign * messages. */ @@ -222,6 +355,30 @@ struct TALER_MasterPublicKeyP /** + * @brief Type of the offline master public keys used by the exchange. + */ +struct TALER_MasterPrivateKeyP +{ + /** + * Taler uses EdDSA for the long-term offline master key. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures by the offline master public key used by the exchange. + */ +struct TALER_MasterSignatureP +{ + /** + * Taler uses EdDSA for the long-term offline master key. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** * @brief Type of the private key used by the auditor. */ struct TALER_AuditorPrivateKeyP @@ -258,108 +415,201 @@ struct TALER_AuditorSignatureP /** - * @brief Type of the offline master public keys used by the exchange. + * @brief Type of public keys for Taler coins. The same key material is used + * for EdDSA and ECDHE operations. */ -struct TALER_MasterPrivateKeyP +struct TALER_CoinSpendPublicKeyP { /** - * Taler uses EdDSA for the long-term offline master key. + * Taler uses EdDSA for coins when signing deposit requests. */ - struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; + }; /** - * @brief Type of signatures by the offline master public key used by the exchange. + * @brief Type of private keys for Taler coins. The same key material is used + * for EdDSA and ECDHE operations. */ -struct TALER_MasterSignatureP +struct TALER_CoinSpendPrivateKeyP { /** - * Taler uses EdDSA for the long-term offline master key. + * Taler uses EdDSA for coins when signing deposit requests. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + +/** + * @brief Type of signatures made with Taler coins. + */ +struct TALER_CoinSpendSignatureP +{ + /** + * Taler uses EdDSA for coins. */ struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; }; -/* - * @brief Type of a list of age groups, represented as bit mask. - * - * The bits set in the mask mark the edges at the beginning of a next age - * group. F.e. for the age groups - * 0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-* - * the following bits are set: - * - * 31 24 16 8 0 - * | | | | | - * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 - * - * A value of 0 means that the exchange does not support the extension for - * age-restriction. + +/** + * @brief Type of private keys for age commitment in coins. */ -struct TALER_AgeMask +struct TALER_AgeCommitmentPrivateKeyP { - uint32_t mask; +#ifdef AGE_RESTRICTION_WITH_ECDSA + /** + * Taler uses EcDSA for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey priv; +#else + /** + * Taler uses Edx25519 for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_Edx25519PrivateKey priv; +#endif }; + /** - * @brief Age restriction commitment of a coin. + * @brief Type of public keys for age commitment in coins. */ -struct TALER_AgeHash +struct TALER_AgeCommitmentPublicKeyP { +#ifdef AGE_RESTRICTION_WITH_ECDSA /** - * The commitment is a SHA-256 hash code. + * Taler uses EcDSA for coins when signing age verification attestation. */ - struct GNUNET_ShortHashCode shash; + struct GNUNET_CRYPTO_EcdsaPublicKey pub; +#else + /** + * Taler uses Edx25519 for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_Edx25519PublicKey pub; +#endif +}; + + +/* + * @brief Hash to represent the commitment to n*kappa blinded keys during a + * age-withdrawal. It is the running SHA512 hash over the hashes of the blinded + * envelopes of n*kappa coins. + */ +struct TALER_AgeWithdrawCommitmentHashP +{ + struct GNUNET_HashCode hash; }; /** - * @brief Type of public keys for Taler coins. The same key material is used - * for EdDSA and ECDHE operations. + * @brief Type of online public keys used by the wallet to establish a purse and the associated contract meta data. */ -struct TALER_CoinSpendPublicKeyP +struct TALER_PurseContractPublicKeyP { /** - * Taler uses EdDSA for coins when signing deposit requests. + * Taler uses EdDSA for purse message signing. */ struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + +/** + * @brief Type of online private keys used by the wallet to + * bind a purse to a particular contract (and other meta data). + */ +struct TALER_PurseContractPrivateKeyP +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; }; /** - * @brief Type of private keys for Taler coins. The same key material is used - * for EdDSA and ECDHE operations. + * @brief Type of signatures used by the wallet to sign purse creation messages online. */ -struct TALER_CoinSpendPrivateKeyP +struct TALER_PurseContractSignatureP { /** - * Taler uses EdDSA for coins when signing deposit requests. + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * @brief Type of online public keys used by the wallet to + * sign a merge of a purse into an account. + */ +struct TALER_PurseMergePublicKeyP +{ + /** + * Taler uses EdDSA for purse message signing. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of online private keys used by the wallet to + * sign a merge of a purse into an account. + */ +struct TALER_PurseMergePrivateKeyP +{ + /** + * Taler uses EdDSA for online signatures sessions. */ struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; }; /** - * @brief Type of signatures made with Taler coins. + * @brief Type of signatures used by the wallet to sign purse merge requests online. */ -struct TALER_CoinSpendSignatureP +struct TALER_PurseMergeSignatureP { /** - * Taler uses EdDSA for coins. + * Taler uses EdDSA for online signatures sessions. */ struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; }; /** - * @brief Type of blinding keys for Taler. + * @brief Type of online public keys used by AML officers. */ -union TALER_DenominationBlindingKeyP +struct TALER_AmlOfficerPublicKeyP { /** - * Taler uses RSA for blind signatures. + * Taler uses EdDSA for AML decision signing. */ - struct GNUNET_CRYPTO_RsaBlindingKeySecret rsa_bks; + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of online private keys used to identify + * AML officers. + */ +struct TALER_AmlOfficerPrivateKeyP +{ + /** + * Taler uses EdDSA for AML decision signing. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures used by AML officers. + */ +struct TALER_AmlOfficerSignatureP +{ + /** + * Taler uses EdDSA for AML decision signing. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; }; @@ -377,6 +627,19 @@ struct TALER_RefreshCommitmentP /** + * Symmetric key we use to encrypt KYC attributes + * in our database. + */ +struct TALER_AttributeEncryptionKeyP +{ + /** + * The key is a hash code. + */ + struct GNUNET_HashCode hash; +}; + + +/** * Token used for access control to the merchant's unclaimed * orders. */ @@ -393,7 +656,7 @@ struct TALER_ClaimTokenP * Salt used to hash a merchant's payto:// URI to * compute the "h_wire" (say for deposit requests). */ -struct TALER_WireSalt +struct TALER_WireSaltP { /** * Actual 128-bit salt value. @@ -403,6 +666,20 @@ struct TALER_WireSalt /** + * Hash used to represent an CS public key. Does not include age + * restrictions and is ONLY for CS. Used ONLY for interactions with the CS + * security module. + */ +struct TALER_CsPubHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** * Hash used to represent an RSA public key. Does not include age * restrictions and is ONLY for RSA. Used ONLY for interactions with the RSA * security module. @@ -417,21 +694,41 @@ struct TALER_RsaPubHashP /** - * Hash @a rsa. - * - * @param rsa key to hash - * @param[out] h_rsa where to write the result + * Master key material for the deriviation of + * private coins and blinding factors during + * withdraw or refresh. */ -void -TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, - struct TALER_RsaPubHashP *h_rsa); +struct TALER_PlanchetMasterSecretP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; + + +/** + * Master key material for the deriviation of + * private coins and blinding factors. + */ +struct TALER_RefreshMasterSecretP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; /** * Hash used to represent a denomination public key * and associated age restrictions (if any). */ -struct TALER_DenominationHash +struct TALER_DenominationHashP { /** * Actual hash value. @@ -444,7 +741,7 @@ struct TALER_DenominationHash * Hash used to represent the private part * of a contract between merchant and consumer. */ -struct TALER_PrivateContractHash +struct TALER_PrivateContractHashP { /** * Actual hash value. @@ -454,10 +751,9 @@ struct TALER_PrivateContractHash /** - * Hash used to represent the "public" extensions to - * a contract that is shared with the exchange. + * Hash used to represent the policy extension to a deposit */ -struct TALER_ExtensionContractHash +struct TALER_ExtensionPolicyHashP { /** * Actual hash value. @@ -470,7 +766,7 @@ struct TALER_ExtensionContractHash * Hash used to represent the salted hash of a * merchant's bank account. */ -struct TALER_MerchantWireHash +struct TALER_MerchantWireHashP { /** * Actual hash value. @@ -483,12 +779,12 @@ struct TALER_MerchantWireHash * Hash used to represent the unsalted hash of a * payto:// URI representing a bank account. */ -struct TALER_PaytoHash +struct TALER_PaytoHashP { /** * Actual hash value. */ - struct GNUNET_HashCode hash; + struct GNUNET_ShortHashCode hash; }; @@ -496,7 +792,7 @@ struct TALER_PaytoHash * Hash used to represent a commitment to a blinded * coin, i.e. the hash of the envelope. */ -struct TALER_BlindedCoinHash +struct TALER_BlindedCoinHashP { /** * Actual hash value. @@ -509,7 +805,7 @@ struct TALER_BlindedCoinHash * Hash used to represent the hash of the public * key of a coin (without blinding). */ -struct TALER_CoinPubHash +struct TALER_CoinPubHashP { /** * Actual hash value. @@ -518,141 +814,471 @@ struct TALER_CoinPubHash }; -GNUNET_NETWORK_STRUCT_END +/** + * @brief Value that uniquely identifies a reward. + */ +struct TALER_RewardIdentifierP +{ + /** + * The tip identifier is a SHA-512 hash code. + */ + struct GNUNET_HashCode hash; +}; /** - * Types of public keys used for denominations in Taler. + * @brief Value that uniquely identifies a tip pick up operation. */ -enum TALER_DenominationCipher +struct TALER_PickupIdentifierP { + /** + * The pickup identifier is a SHA-512 hash code. + */ + struct GNUNET_HashCode hash; +}; + +/** + * @brief Salted hash over the JSON object representing the manifests of + * extensions. + */ +struct TALER_ExtensionManifestsHashP +{ /** - * Invalid type of signature. + * Actual hash value. */ - TALER_DENOMINATION_INVALID = 0, + struct GNUNET_HashCode hash; +}; + + +/** + * Set of the fees applying to a denomination. + */ +struct TALER_DenomFeeSetNBOP +{ /** - * RSA blind signature. + * The fee the exchange charges when a coin of this type is withdrawn. + * (can be zero). */ - TALER_DENOMINATION_RSA = 1, + struct TALER_AmountNBO withdraw; /** - * Clause-Schnorr blind signature. + * The fee the exchange charges when a coin of this type is deposited. + * (can be zero). */ - // TALER_DENOMINATION_CS = 2 + struct TALER_AmountNBO deposit; + + /** + * The fee the exchange charges when a coin of this type is refreshed. + * (can be zero). + */ + struct TALER_AmountNBO refresh; + + /** + * The fee the exchange charges when a coin of this type is refunded. + * (can be zero). Note that refund fees are charged to the customer; + * if a refund is given, the deposit fee is also refunded. + */ + struct TALER_AmountNBO refund; + }; /** - * @brief Type of (unblinded) coin signatures for Taler. + * Set of the fees applying for a given + * time-range and wire method. */ -struct TALER_DenominationSignature +struct TALER_WireFeeSetNBOP { /** - * Type of the signature. + * The fee the exchange charges for wiring funds + * to a merchant. */ - enum TALER_DenominationCipher cipher; + struct TALER_AmountNBO wire; /** - * Details, depending on @e cipher. + * The fee the exchange charges for closing a reserve + * and wiring the funds back to the origin account. */ - union - { + struct TALER_AmountNBO closing; + +}; + + +/** + * Set of the fees applying globally for a given + * time-range. + */ +struct TALER_GlobalFeeSetNBOP +{ - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaSignature *rsa_signature; + /** + * The fee the exchange charges for returning the history of a reserve or + * account. + */ + struct TALER_AmountNBO history; - } details; + /** + * The fee the exchange charges for keeping an account or reserve open for a + * year. + */ + struct TALER_AmountNBO account; + /** + * The fee the exchange charges if a purse is abandoned and this was not + * covered by the account limit. + */ + struct TALER_AmountNBO purse; }; +GNUNET_NETWORK_STRUCT_END + + /** - * @brief Type for *blinded* denomination signatures for Taler. - * Must be unblinded before it becomes valid. + * Compute RFC 3548 base32 decoding of @a val and write + * result to @a udata. + * + * @param val value to decode + * @param val_size number of bytes in @a val + * @param key is the val in bits + * @param key_len is the size of @a key */ -struct TALER_BlindedDenominationSignature +int +TALER_rfc3548_base32decode (const char *val, + size_t val_size, + void *key, + size_t key_len); + + +/** + * @brief Builds POS confirmation token to verify payment. + * + * @param pos_key encoded key for verification payment + * @param pos_alg algorithm to compute the payment verification + * @param total of the order paid + * @param ts is the time given + * @return POS token on success, NULL otherwise + */ +char * +TALER_build_pos_confirmation (const char *pos_key, + enum TALER_MerchantConfirmationAlgorithm pos_alg, + const struct TALER_Amount *total, + struct GNUNET_TIME_Timestamp ts); + + +/** + * Set of the fees applying to a denomination. + */ +struct TALER_DenomFeeSet { /** - * Type of the signature. + * The fee the exchange charges when a coin of this type is withdrawn. + * (can be zero). */ - enum TALER_DenominationCipher cipher; + struct TALER_Amount withdraw; /** - * Details, depending on @e cipher. + * The fee the exchange charges when a coin of this type is deposited. + * (can be zero). */ - union - { + struct TALER_Amount deposit; - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature; + /** + * The fee the exchange charges when a coin of this type is refreshed. + * (can be zero). + */ + struct TALER_Amount refresh; - } details; + /** + * The fee the exchange charges when a coin of this type is refunded. + * (can be zero). Note that refund fees are charged to the customer; + * if a refund is given, the deposit fee is also refunded. + */ + struct TALER_Amount refund; }; /** - * @brief Type of public signing keys for verifying blindly signed coins. + * Set of the fees applying for a given time-range and wire method. */ -struct TALER_DenominationPublicKey +struct TALER_WireFeeSet { /** - * Type of the public key. + * The fee the exchange charges for wiring funds to a merchant. */ - enum TALER_DenominationCipher cipher; + struct TALER_Amount wire; /** - * Age restriction mask used for the key. + * The fee the exchange charges for closing a reserve + * and wiring the funds back to the origin account. */ - struct TALER_AgeMask age_mask; + struct TALER_Amount closing; + +}; + + +/** + * Set of the fees applying globally for a given + * time-range. + */ +struct TALER_GlobalFeeSet +{ /** - * Details, depending on @e cipher. + * The fee the exchange charges for returning the + * history of a reserve or account. */ - union - { + struct TALER_Amount history; - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key; + /** + * The fee the exchange charges for keeping + * an account or reserve open for a year. + */ + struct TALER_Amount account; - } details; + /** + * The fee the exchange charges if a purse + * is abandoned and this was not covered by + * the account limit. + */ + struct TALER_Amount purse; }; /** - * @brief Type of private signing keys for blind signing of coins. + * Convert fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert */ -struct TALER_DenominationPrivateKey +void +TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo, + const struct TALER_DenomFeeSet *fees); + + +/** + * Convert fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees, + const struct TALER_DenomFeeSetNBOP *nbo); + + +/** + * Convert global fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert + */ +void +TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo, + const struct TALER_GlobalFeeSet *fees); + + +/** + * Convert global fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees, + const struct TALER_GlobalFeeSetNBOP *nbo); + + +/** + * Compare global fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1, + const struct TALER_GlobalFeeSet *f2); + + +/** + * Convert wire fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert + */ +void +TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo, + const struct TALER_WireFeeSet *fees); + + +/** + * Convert wire fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees, + const struct TALER_WireFeeSetNBOP *nbo); + + +/** + * Compare wire fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1, + const struct TALER_WireFeeSet *f2); + + +/** + * Hash @a rsa. + * + * @param rsa key to hash + * @param[out] h_rsa where to write the result + */ +void +TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, + struct TALER_RsaPubHashP *h_rsa); + + +/** + * Hash @a cs. + * + * @param cs key to hash + * @param[out] h_cs where to write the result + */ +void +TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs, + struct TALER_CsPubHashP *h_cs); + + +/** + * @brief Type of (unblinded) coin signatures for Taler. + */ +struct TALER_DenominationSignature { + /** + * Denominations use blind signatures. + */ + struct GNUNET_CRYPTO_UnblindedSignature *unblinded_sig; +}; + +/** + * @brief Type for *blinded* denomination signatures for Taler. + * Must be unblinded before it becomes valid. + */ +struct TALER_BlindedDenominationSignature +{ /** - * Type of the public key. + * Denominations use blind signatures. */ - enum TALER_DenominationCipher cipher; + struct GNUNET_CRYPTO_BlindedSignature *blinded_sig; +}; + +/* *************** Age Restriction *********************************** */ + +/* + * @brief Type of a list of age groups, represented as bit mask. + * + * The bits set in the mask mark the edges at the beginning of a next age + * group. F.e. for the age groups + * 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-21, 21-* + * the following bits are set: + * + * 31 24 16 8 0 + * | | | | | + * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + * + * A value of 0 means that the exchange does not support the extension for + * age-restriction. + * + * For a non-0 age mask, the 0th bit always must be set, otherwise the age + * mask is considered invalid. + */ +struct TALER_AgeMask +{ + uint32_t bits; +}; + +/** + * @brief Age commitment of a coin. + */ +struct TALER_AgeCommitmentHash +{ /** - * Details, depending on @e cipher. + * The commitment is a SHA-256 hash code. */ - union - { + struct GNUNET_ShortHashCode shash; +}; + +/** + * @brief Signature of an age with the private key for the corresponding age group of an age commitment. + */ +struct TALER_AgeAttestation +{ +#ifdef AGE_RESTRICTION_WITH_ECDSA + struct GNUNET_CRYPTO_EcdsaSignature signature; +#else + struct GNUNET_CRYPTO_Edx25519Signature signature; +#endif +}; - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key; +#define TALER_AgeCommitmentHash_isNullOrZero(ph) ((NULL == ph) || \ + GNUNET_is_zero (ph)) + +/** + * @brief Type of public signing keys for verifying blindly signed coins. + */ +struct TALER_DenominationPublicKey +{ + + /** + * Age restriction mask used for the key. + */ + struct TALER_AgeMask age_mask; + + /** + * Type of the public key. + */ + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub_key; + +}; + + +/** + * @brief Type of private signing keys for blind signing of coins. + */ +struct TALER_DenominationPrivateKey +{ + + struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv_key; + +}; + + +/** + * @brief Blinded planchet send to exchange for blind signing. + */ +struct TALER_BlindedPlanchet +{ + /** + * A blinded message. + */ + struct GNUNET_CRYPTO_BlindedMessage *blinded_message; - } details; }; @@ -672,12 +1298,18 @@ struct TALER_CoinPublicInfo * Hash of the public key representing the denomination of the coin that is * being deposited. */ - struct TALER_DenominationHash denom_pub_hash; + struct TALER_DenominationHashP denom_pub_hash; + + /** + * Hash of the age commitment. If no age commitment was provided, it must be + * set to all zeroes. + */ + struct TALER_AgeCommitmentHash h_age_commitment; /** - * Hash of the age commitment. + * True, if age commitment is not applicable. */ - struct TALER_AgeHash age_commitment_hash; + bool no_age_commitment; /** * (Unblinded) signature over @e coin_pub with @e denom_pub, @@ -696,7 +1328,7 @@ struct TALER_TrackTransferDetails /** * Hash of the proposal data. */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Which coin was deposited? @@ -704,57 +1336,139 @@ struct TALER_TrackTransferDetails struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Value of the deposit (including fee). + * Value of the deposit (including fee), after refunds. */ struct TALER_Amount coin_value; /** - * Fee charged by the exchange for the deposit. + * Fee charged by the exchange for the deposit, + * possibly reduced (or waived) due to refunds. */ struct TALER_Amount coin_fee; + /** + * Total amount of refunds applied to this coin. + */ + struct TALER_Amount refund_total; + }; /** - * Free internals of @a denom_pub, but not @a denom_pub itself. + * @brief Inputs needed from the exchange for blind signing. + */ +struct TALER_ExchangeWithdrawValues +{ + + /** + * Input values. + */ + struct GNUNET_CRYPTO_BlindingInputValues *blinding_inputs; +}; + + +/** + * Return the alg value singleton for creation of + * blinding secrets for RSA. * - * @param[in] denom_pub key to free + * @return singleton to use for RSA blinding + */ +const struct TALER_ExchangeWithdrawValues * +TALER_denom_ewv_rsa_singleton (void); + + +/** + * Make a (deep) copy of the given @a bi_src to + * @a bi_dst. + * + * @param[out] bi_dst target to copy to + * @param bi_src blinding input values to copy */ void -TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub); +TALER_denom_ewv_copy ( + struct TALER_ExchangeWithdrawValues *bi_dst, + const struct TALER_ExchangeWithdrawValues *bi_src); /** - * Create a blinding secret @a bs for @a cipher. + * Create private key for a Taler coin. + * @param ps planchet secret to derive coin priv key + * @param alg_values includes algorithm specific values + * @param[out] coin_priv private key to initialize + */ +void +TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinSpendPrivateKeyP *coin_priv); + + +/** + * @brief Method to derive withdraw /csr nonce * - * @param[out] bs blinding secret to initialize + * @param ps planchet secrets of the coin + * @param[out] nonce withdraw nonce included in the request to generate R_0 and R_1 */ void -TALER_blinding_secret_create (union TALER_DenominationBlindingKeyP *bs); +TALER_cs_withdraw_nonce_derive ( + const struct TALER_PlanchetMasterSecretP *ps, + struct GNUNET_CRYPTO_CsSessionNonce *nonce); + + +/** + * @brief Method to derive /csr nonce + * to be used during refresh/melt operation. + * + * @param rms secret input for the refresh operation + * @param idx index of the fresh coin + * @param[out] nonce set to nonce included in the request to generate R_0 and R_1 + */ +void +TALER_cs_refresh_nonce_derive ( + const struct TALER_RefreshMasterSecretP *rms, + uint32_t idx, + struct GNUNET_CRYPTO_CsSessionNonce *nonce); /** * Initialize denomination public-private key pair. * - * For #TALER_DENOMINATION_RSA, an additional "unsigned int" + * For #GNUNET_CRYPTO_BSA_RSA, an additional "unsigned int" * argument with the number of bits for 'n' (e.g. 2048) must * be passed. * * @param[out] denom_priv where to write the private key - * @param[out] deonm_pub where to write the public key + * @param[out] denom_pub where to write the public key * @param cipher which type of cipher to use - * @param ... cipher-specific parameters + * @param ... RSA key size (eg. 2048/3072/4096) * @return #GNUNET_OK on success, #GNUNET_NO if parameters were invalid */ enum GNUNET_GenericReturnValue TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv, struct TALER_DenominationPublicKey *denom_pub, - enum TALER_DenominationCipher cipher, + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, ...); /** + * Free internals of @a denom_pub, but not @a denom_pub itself. + * + * @param[in] denom_pub key to free + */ +void +TALER_denom_pub_free (struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Free internals of @a ewv, but not @a ewv itself. + * + * @param[in] ewv input values to free + */ +void +TALER_denom_ewv_free (struct TALER_ExchangeWithdrawValues *ewv); + + +/** * Free internals of @a denom_priv, but not @a denom_priv itself. * * @param[in] denom_priv key to free @@ -775,23 +1489,30 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); /** * Blind coin for blind signing with @a dk using blinding secret @a coin_bks. * + * NOTE: As a particular oddity, the @a blinded_planchet is only partially + * initialized by this function in the case of CS-denominations. Here, the + * 'nonce' must be initialized separately! + * * @param dk denomination public key to blind for * @param coin_bks blinding secret to use + * @param nonce nonce used to derive session values, + * could be NULL for ciphers that do not use it * @param age_commitment_hash hash of the age commitment to be used for the coin. NULL if no commitment is made. * @param coin_pub public key of the coin to blind + * @param alg_values algorithm specific values to blind the planchet * @param[out] c_hash resulting hashed coin - * @param[out] coin_ev blinded coin to submit - * @param[out] coin_ev_size number of bytes in @a coin_ev + * @param[out] blinded_planchet planchet data to initialize * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue TALER_denom_blind (const struct TALER_DenominationPublicKey *dk, - const union TALER_DenominationBlindingKeyP *coin_bks, - const struct TALER_AgeHash *age_commitment_hash, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_AgeCommitmentHash *age_commitment_hash, const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_CoinPubHash *c_hash, - void **coin_ev, - size_t *coin_ev_size); + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinPubHashP *c_hash, + struct TALER_BlindedPlanchet *blinded_planchet); /** @@ -799,15 +1520,15 @@ TALER_denom_blind (const struct TALER_DenominationPublicKey *dk, * * @param[out] denom_sig where to write the signature * @param denom_priv private key to use for signing - * @param blinded_msg message to sign - * @param blinded_msg_size number of bytes in @a blinded_msg + * @param for_melt true to use the HKDF for melt + * @param blinded_planchet the planchet already blinded * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, const struct TALER_DenominationPrivateKey *denom_priv, - void *blinded_msg, - size_t blinded_msg_size); + bool for_melt, + const struct TALER_BlindedPlanchet *blinded_planchet); /** @@ -816,6 +1537,8 @@ TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, * @param[out] denom_sig where to write the unblinded signature * @param bdenom_sig the blinded signature * @param bks blinding secret to use + * @param c_hash hash of the coin's public key for verification of the signature + * @param alg_values algorithm specific values * @param denom_pub public key used for signing * @return #GNUNET_OK on success */ @@ -823,7 +1546,9 @@ enum GNUNET_GenericReturnValue TALER_denom_sig_unblind ( struct TALER_DenominationSignature *denom_sig, const struct TALER_BlindedDenominationSignature *bdenom_sig, - const union TALER_DenominationBlindingKeyP *bks, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, const struct TALER_DenominationPublicKey *denom_pub); @@ -845,7 +1570,7 @@ TALER_blinded_denom_sig_free ( */ void TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, - struct TALER_DenominationHash *denom_hash); + struct TALER_DenominationHashP *denom_hash); /** @@ -853,11 +1578,11 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, * @a denom_dst. * * @param[out] denom_dst target to copy to - * @param denom_str public key to copy + * @param denom_src public key to copy */ void -TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst, - const struct TALER_DenominationPublicKey *denom_src); +TALER_denom_pub_copy (struct TALER_DenominationPublicKey *denom_dst, + const struct TALER_DenominationPublicKey *denom_src); /** @@ -865,11 +1590,11 @@ TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst, * @a denom_dst. * * @param[out] denom_dst target to copy to - * @param denom_str public key to copy + * @param denom_src public key to copy */ void -TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, - const struct TALER_DenominationSignature *denom_src); +TALER_denom_sig_copy (struct TALER_DenominationSignature *denom_dst, + const struct TALER_DenominationSignature *denom_src); /** @@ -877,10 +1602,10 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, * @a denom_dst. * * @param[out] denom_dst target to copy to - * @param denom_str public key to copy + * @param denom_src public key to copy */ void -TALER_blinded_denom_sig_deep_copy ( +TALER_blinded_denom_sig_copy ( struct TALER_BlindedDenominationSignature *denom_dst, const struct TALER_BlindedDenominationSignature *denom_src); @@ -923,16 +1648,16 @@ TALER_blinded_denom_sig_cmp ( /** - * Obtain denomination public key from a denomination private key. + * Compare two blinded planchets. * - * @param denom_priv private key to convert - * @param age_mask age mask to be applied - * @param[out] denom_pub where to return the public key + * @param bp1 first blinded planchet + * @param bp2 second blinded planchet + * @return 0 if the keys are equal, otherwise -1 or 1 */ -void -TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv, - const struct TALER_AgeMask age_mask, - struct TALER_DenominationPublicKey *denom_pub); +int +TALER_blinded_planchet_cmp ( + const struct TALER_BlindedPlanchet *bp1, + const struct TALER_BlindedPlanchet *bp2); /** @@ -947,7 +1672,52 @@ TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv, enum GNUNET_GenericReturnValue TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_DenominationSignature *denom_sig, - const struct TALER_CoinPubHash *c_hash); + const struct TALER_CoinPubHashP *c_hash); + + +/** + * Encrypts KYC attributes for storage in the database. + * + * @param key encryption key to use + * @param attr set of attributes to encrypt + * @param[out] enc_attr encrypted attribute data + * @param[out] enc_attr_size number of bytes in @a enc_attr + */ +void +TALER_CRYPTO_kyc_attributes_encrypt ( + const struct TALER_AttributeEncryptionKeyP *key, + const json_t *attr, + void **enc_attr, + size_t *enc_attr_size); + + +/** + * Encrypts KYC attributes for storage in the database. + * + * @param key encryption key to use + * @param enc_attr encrypted attribute data + * @param enc_attr_size number of bytes in @a enc_attr + * @return set of decrypted attributes, NULL on failure + */ +json_t * +TALER_CRYPTO_kyc_attributes_decrypt ( + const struct TALER_AttributeEncryptionKeyP *key, + const void *enc_attr, + size_t enc_attr_size); + + +/** + * Takes a set of KYC attributes and extracts key + * data that we use to detect similar / duplicate + * entries in the database. + * + * @param attr set of KYC attributes + * @param[out] kyc_prox set to the proximity hash + */ +void +TALER_CRYPTO_attributes_to_kyc_prox ( + const json_t *attr, + struct GNUNET_ShortHashCode *kyc_prox); /** @@ -968,14 +1738,14 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, /** * Compute the hash of a blinded coin. * - * @param coin_ev blinded coin - * @param coin_ev_size number of bytes in @a coin_ev + * @param blinded_planchet blinded planchet + * @param denom_hash hash of the denomination public key * @param[out] bch where to write the hash */ void -TALER_coin_ev_hash (const void *coin_ev, - size_t coin_ev_size, - struct TALER_BlindedCoinHash *bch); +TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, + const struct TALER_DenominationHashP *denom_hash, + struct TALER_BlindedCoinHashP *bch); /** @@ -987,8 +1757,8 @@ TALER_coin_ev_hash (const void *coin_ev, */ void TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_AgeHash *age_commitment_hash, - struct TALER_CoinPubHash *coin_h); + const struct TALER_AgeCommitmentHash *age_commitment_hash, + struct TALER_CoinPubHashP *coin_h); /** @@ -999,34 +1769,7 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, */ void TALER_payto_hash (const char *payto, - struct TALER_PaytoHash *h_payto); - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * Header for serializations of coin-specific information about the - * fresh coins we generate. These are the secrets that arise during - * planchet generation, which is the first stage of creating a new - * coin. - */ -struct TALER_PlanchetSecretsP -{ - - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * The blinding key. - */ - union TALER_DenominationBlindingKeyP blinding_key; - -}; - - -GNUNET_NETWORK_STRUCT_END + struct TALER_PaytoHashP *h_payto); /** @@ -1040,17 +1783,12 @@ struct TALER_PlanchetDetail /** * Hash of the denomination public key. */ - struct TALER_DenominationHash denom_pub_hash; - - /** - * Blinded coin (see GNUNET_CRYPTO_rsa_blind()). Note: is malloc()'ed! - */ - void *coin_ev; + struct TALER_DenominationHashP denom_pub_hash; /** - * Number of bytes in @a coin_ev. + * The blinded planchet */ - size_t coin_ev_size; + struct TALER_BlindedPlanchet blinded_planchet; }; @@ -1073,8 +1811,9 @@ struct TALER_FreshCoin struct TALER_CoinSpendPrivateKeyP coin_priv; /** - * FIXME-Oec: Age-verification vector, as pointer: Dyn alloc! + * Optional hash of an age commitment bound to this coin, maybe NULL. */ + const struct TALER_AgeCommitmentHash *h_age_commitment; }; @@ -1167,44 +1906,121 @@ GNUNET_NETWORK_STRUCT_END /** - * Setup information for a fresh coin, deriving the coin private key - * and the blinding factor from the @a secret_seed with a KDF salted - * by the @a coin_num_salt. + * Setup information for a fresh coin, deriving the coin planchet secrets from + * which we will later derive the private key and the blinding factor. The + * planchet secrets derivation is based on the @a secret_seed with a KDF + * salted by the @a coin_num_salt. * * @param secret_seed seed to use for KDF to derive coin keys * @param coin_num_salt number of the coin to include in KDF * @param[out] ps value to initialize */ void -TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, - uint32_t coin_num_salt, - struct TALER_PlanchetSecretsP *ps); +TALER_transfer_secret_to_planchet_secret ( + const struct TALER_TransferSecretP *secret_seed, + uint32_t coin_num_salt, + struct TALER_PlanchetMasterSecretP *ps); /** - * Setup information for a fresh coin. + * Derive the @a coin_num transfer private key @a tpriv from a refresh from + * the @a rms seed and the @a old_coin_pub of the refresh operation. The + * transfer private key derivation is based on the @a ps with a KDF salted by + * the @a coin_num. + * + * @param rms seed to use for KDF to derive transfer keys + * @param old_coin_priv private key of the old coin + * @param cnc_num cut and choose number to include in KDF + * @param[out] tpriv value to initialize + */ +void +TALER_planchet_secret_to_transfer_priv ( + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, + uint32_t cnc_num, + struct TALER_TransferPrivateKeyP *tpriv); + + +/** + * Setup secret seed information for fresh coins to be + * withdrawn. * * @param[out] ps value to initialize */ void -TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps); +TALER_planchet_master_setup_random ( + struct TALER_PlanchetMasterSecretP *ps); + + +/** + * Setup secret seed for fresh coins to be refreshed. + * + * @param[out] rms value to initialize + */ +void +TALER_refresh_master_setup_random ( + struct TALER_RefreshMasterSecretP *rms); + + +/** + * Create a blinding secret @a bks given the client's @a ps and the alg_values + * from the exchange. + * + * @param ps secret to derive blindings from + * @param alg_values withdraw values containing cipher and additional CS values + * @param[out] bks blinding secrets + */ +void +TALER_planchet_blinding_secret_create ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + union GNUNET_CRYPTO_BlindingSecretP *bks); /** - * Prepare a planchet for tipping. Creates and blinds a coin. + * Prepare a planchet for withdrawal. Creates and blinds a coin. * * @param dk denomination key for the coin to be created - * @param ps secret planchet internals (for #TALER_planchet_to_coin) + * @param alg_values algorithm specific values + * @param bks blinding secrets + * @param nonce session nonce used to get @a alg_values + * @param coin_priv coin private key + * @param ach hash of age commitment to bind to this coin, maybe NULL * @param[out] c_hash set to the hash of the public key of the coin (needed later) * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and - * other withdraw operations + * other withdraw operations, `pd->blinded_planchet.cipher` will be set + * to cipher from @a dk * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct TALER_PlanchetSecretsP *ps, - struct TALER_CoinPubHash *c_hash, - struct TALER_PlanchetDetail *pd); +TALER_planchet_prepare ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_ExchangeWithdrawValues *alg_values, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + struct TALER_CoinPubHashP *c_hash, + struct TALER_PlanchetDetail *pd); + + +/** + * Frees blinded message inside blinded planchet depending on `blinded_planchet->cipher`. + * Does not free the @a blinded_planchet itself! + * + * @param[in] blinded_planchet blinded planchet + */ +void +TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * Frees blinded message inside planchet detail @a pd. + * + * @param[in] pd planchet detail to free + */ +void +TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd); /** @@ -1213,8 +2029,11 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, * * @param dk denomination key, must match what was given to #TALER_planchet_prepare() * @param blind_sig blind signature from the exchange - * @param ps secrets from #TALER_planchet_prepare() + * @param bks blinding key secret + * @param coin_priv private key of the coin + * @param ach hash of age commitment that is bound to this coin, maybe NULL * @param c_hash hash of the coin's public key for verification of the signature + * @param alg_values values obtained from the exchange for the withdrawal * @param[out] coin set to the details of the fresh coin * @return #GNUNET_OK on success */ @@ -1222,12 +2041,24 @@ enum GNUNET_GenericReturnValue TALER_planchet_to_coin ( const struct TALER_DenominationPublicKey *dk, const struct TALER_BlindedDenominationSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct TALER_CoinPubHash *c_hash, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, struct TALER_FreshCoin *coin); -/* ****************** Refresh crypto primitives ************* */ +/** + * Add the hash of the @a bp (in some canonicalized form) + * to the @a hash_context. + * + * @param bp blinded planchet to hash + * @param[in,out] hash_context hash context to use + */ +void +TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp, + struct GNUNET_HashContext *hash_context); /** @@ -1290,14 +2121,9 @@ struct TALER_RefreshCoinData const struct TALER_DenominationPublicKey *dk; /** - * The envelope with the blinded coin. - */ - void *coin_ev; - - /** - * Number of bytes in @a coin_ev + * The blinded planchet (details depend on cipher). */ - size_t coin_ev_size; + struct TALER_BlindedPlanchet blinded_planchet; }; @@ -1325,6 +2151,7 @@ struct TALER_RefreshCommitmentEntry * * @param[out] rc set to the value the wallet must commit to * @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA) + * @param rms refresh master secret to include, can be NULL! * @param num_new_coins number of new coins to be created * @param rcs array of @a kappa commitments * @param coin_pub public key of the coin to be melted @@ -1333,11 +2160,171 @@ struct TALER_RefreshCommitmentEntry void TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, uint32_t kappa, + const struct TALER_RefreshMasterSecretP *rms, uint32_t num_new_coins, const struct TALER_RefreshCommitmentEntry *rcs, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *amount_with_fee); + +/** + * Encrypt contract for transmission to a party that will + * merge it into a reserve. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param merge_priv merge capability to include + * @param contract_terms contract terms to encrypt + * @param[out] econtract set to encrypted contract + * @param[out] econtract_size set to number of bytes in @a econtract + */ +void +TALER_CRYPTO_contract_encrypt_for_merge ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const json_t *contract_terms, + void **econtract, + size_t *econtract_size); + + +/** + * Decrypt contract for the party that will + * merge it into a reserve. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param[out] merge_priv set to merge capability + * @return decrypted contract terms, or NULL on failure + */ +json_t * +TALER_CRYPTO_contract_decrypt_for_merge ( + const struct TALER_ContractDiffiePrivateP *contract_priv, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const void *econtract, + size_t econtract_size, + struct TALER_PurseMergePrivateKeyP *merge_priv); + + +/** + * Encrypt contract for transmission to a party that will + * pay for it. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param contract_terms contract terms to encrypt + * @param[out] econtract set to encrypted contract + * @param[out] econtract_size set to number of bytes in @a econtract + */ +void +TALER_CRYPTO_contract_encrypt_for_deposit ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + void **econtract, + size_t *econtract_size); + + +/** + * Decrypt contract for the party that will pay for it. + * + * @param contract_priv private key of the contract + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @return decrypted contract terms, or NULL on failure + */ +json_t * +TALER_CRYPTO_contract_decrypt_for_deposit ( + const struct TALER_ContractDiffiePrivateP *contract_priv, + const void *econtract, + size_t econtract_size); + + +/* **************** AML officer signatures **************** */ + +/** + * Sign AML query. Simple authentication, doesn't actually + * sign anything. + * + * @param officer_priv private key of AML officer + * @param[out] officer_sig where to write the signature + */ +void +TALER_officer_aml_query_sign ( + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Verify AML query authorization. + * + * @param officer_pub public key of AML officer + * @param officer_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_officer_aml_query_verify ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Sign AML decision. + * + * @param justification human-readable justification + * @param decision_time when was the decision made + * @param new_threshold at what monthly amount threshold + * should a revision be triggered + * @param h_payto payto URI hash of the account the + * decision is about + * @param new_state updated AML state + * @param kyc_requirements additional KYC requirements to + * impose, can be NULL + * @param officer_priv private key of AML officer + * @param[out] officer_sig where to write the signature + */ +void +TALER_officer_aml_decision_sign ( + const char *justification, + struct GNUNET_TIME_Timestamp decision_time, + const struct TALER_Amount *new_threshold, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState new_state, + const json_t *kyc_requirements, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Verify AML decision. + * + * @param justification human-readable justification + * @param decision_time when was the decision made + * @param new_threshold at what monthly amount threshold + * should a revision be triggered + * @param h_payto payto URI hash of the account the + * decision is about + * @param new_state updated AML state + * @param kyc_requirements additional KYC requirements to + * impose, can be NULL + * @param officer_pub public key of AML officer + * @param officer_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_officer_aml_decision_verify ( + const char *justification, + struct GNUNET_TIME_Timestamp decision_time, + const struct TALER_Amount *new_threshold, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState new_state, + const json_t *kyc_requirements, + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const struct TALER_AmlOfficerSignatureP *officer_sig); + + /* **************** Helper-based RSA operations **************** */ /** @@ -1358,7 +2345,7 @@ struct TALER_CRYPTO_RsaDenominationHelper; * @param validity_duration how long does the key remain available for signing; * zero if the key has been revoked or purged * @param h_rsa hash of the RSA @a denom_pub that is available (or was purged) - * @param denom_pub the public key itself, NULL if the key was revoked or purged + * @param bs_pub the public key itself, NULL if the key was revoked or purged * @param sm_pub public key of the security module, NULL if the key was revoked or purged * @param sm_sig signature from the security module, NULL if the key was revoked or purged * The signature was already verified against @a sm_pub. @@ -1367,10 +2354,10 @@ typedef void (*TALER_CRYPTO_RsaDenominationKeyStatusCallback)( void *cls, const char *section_name, - struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Relative validity_duration, const struct TALER_RsaPubHashP *h_rsa, - const struct TALER_DenominationPublicKey *denom_pub, + struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub, const struct TALER_SecurityModulePublicKeyP *sm_pub, const struct TALER_SecurityModuleSignatureP *sm_sig); @@ -1379,6 +2366,7 @@ typedef void * Initiate connection to an denomination key helper. * * @param cfg configuration to use + * @param section configuration section prefix to use, usually 'taler' or 'donau' * @param dkc function to call with key information * @param dkc_cls closure for @a dkc * @return NULL on error (such as bad @a cfg). @@ -1386,6 +2374,7 @@ typedef void struct TALER_CRYPTO_RsaDenominationHelper * TALER_CRYPTO_helper_rsa_connect ( const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, void *dkc_cls); @@ -1404,8 +2393,30 @@ TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh); /** - * Request helper @a dh to sign @a msg using the public key corresponding to - * @a h_denom_pub. + * Information needed for an RSA signature request. + */ +struct TALER_CRYPTO_RsaSignRequest +{ + /** + * Hash of the RSA public key. + */ + const struct TALER_RsaPubHashP *h_rsa; + + /** + * Message to be (blindly) signed. + */ + const void *msg; + + /** + * Number of bytes in @e msg. + */ + size_t msg_size; +}; + + +/** + * Request helper @a dh to sign message in @a rsr using the public key + * corresponding to the key in @a rsr. * * This operation will block until the signature has been obtained. Should * this process receive a signal (that is not ignored) while the operation is @@ -1414,24 +2425,48 @@ TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh); * differences in the signature counters. Retrying in this case may work. * * @param dh helper process connection - * @param h_rsa hash of the RSA public key to use to sign - * @param msg message to sign - * @param msg_size number of bytes in @a msg - * @param[out] ec set to the error code (or #TALER_EC_NONE on success) - * @return signature, the value inside the structure will be NULL on failure, - * see @a ec for details about the failure + * @param rsr details about the requested signature + * @param[out] bs set to the blind signature + * @return #TALER_EC_NONE on success */ -struct TALER_BlindedDenominationSignature +enum TALER_ErrorCode TALER_CRYPTO_helper_rsa_sign ( struct TALER_CRYPTO_RsaDenominationHelper *dh, - const struct TALER_RsaPubHashP *h_rsa, - const void *msg, - size_t msg_size, - enum TALER_ErrorCode *ec); + const struct TALER_CRYPTO_RsaSignRequest *rsr, + struct TALER_BlindedDenominationSignature *bs); + + +/** + * Request helper @a dh to batch sign messages in @a rsrs using the public key + * corresponding to the keys in @a rsrs. + * + * This operation will block until all the signatures have been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * Note that in case of errors, the @a bss array may still have been partially + * filled with signatures, which in this case must be freed by the caller + * (this is in contrast to the #TALER_CRYPTO_helper_rsa_sign() API which never + * returns any signatures if there was an error). + * + * @param dh helper process connection + * @param rsrs array with details about the requested signatures + * @param rsrs_length length of the @a rsrs array + * @param[out] bss array set to the blind signatures, must be of length @a rsrs_length! + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_rsa_batch_sign ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + unsigned int rsrs_length, + const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length], + struct TALER_BlindedDenominationSignature bss[static rsrs_length]); /** - * Ask the helper to revoke the public key associated with @param h_denom_pub . + * Ask the helper to revoke the public key associated with @a h_denom_pub. * Will cause the helper to tell all clients that the key is now unavailable, * and to create a replacement key. * @@ -1461,6 +2496,235 @@ TALER_CRYPTO_helper_rsa_disconnect ( struct TALER_CRYPTO_RsaDenominationHelper *dh); +/* **************** Helper-based CS operations **************** */ + +/** + * Handle for talking to an Denomination key signing helper. + */ +struct TALER_CRYPTO_CsDenominationHelper; + +/** + * Function called with information about available keys for signing. Usually + * only called once per key upon connect. Also called again in case a key is + * being revoked, in that case with an @a end_time of zero. + * + * @param cls closure + * @param section_name name of the denomination type in the configuration; + * NULL if the key has been revoked or purged + * @param start_time when does the key become available for signing; + * zero if the key has been revoked or purged + * @param validity_duration how long does the key remain available for signing; + * zero if the key has been revoked or purged + * @param h_cs hash of the CS @a denom_pub that is available (or was purged) + * @param bsign_pub the public key itself, NULL if the key was revoked or purged + * @param sm_pub public key of the security module, NULL if the key was revoked or purged + * @param sm_sig signature from the security module, NULL if the key was revoked or purged + * The signature was already verified against @a sm_pub. + */ +typedef void +(*TALER_CRYPTO_CsDenominationKeyStatusCallback)( + void *cls, + const char *section_name, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Relative validity_duration, + const struct TALER_CsPubHashP *h_cs, + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub, + const struct TALER_SecurityModulePublicKeyP *sm_pub, + const struct TALER_SecurityModuleSignatureP *sm_sig); + + +/** + * Initiate connection to an denomination key helper. + * + * @param cfg configuration to use + * @param section configuration section prefix to use, usually 'taler' or 'donau' + * @param dkc function to call with key information + * @param dkc_cls closure for @a dkc + * @return NULL on error (such as bad @a cfg). + */ +struct TALER_CRYPTO_CsDenominationHelper * +TALER_CRYPTO_helper_cs_connect ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + TALER_CRYPTO_CsDenominationKeyStatusCallback dkc, + void *dkc_cls); + + +/** + * Function to call to 'poll' for updates to the available key material. + * Should be called whenever it is important that the key material status is + * current, like when handling a "/keys" request. This function basically + * briefly checks if there are messages from the helper announcing changes to + * denomination keys. + * + * @param dh helper process connection + */ +void +TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh); + + +/** + * Information about what we should sign over. + */ +struct TALER_CRYPTO_CsSignRequest +{ + /** + * Hash of the CS public key to use to sign. + */ + const struct TALER_CsPubHashP *h_cs; + + /** + * Blinded planchet containing c and the nonce. + */ + const struct GNUNET_CRYPTO_CsBlindedMessage *blinded_planchet; + +}; + + +/** + * Request helper @a dh to sign @a req. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper process connection + * @param req information about the key to sign with and the value to sign + * @param for_melt true if for melt operation + * @param[out] bs set to the blind signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_sign ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CRYPTO_CsSignRequest *req, + bool for_melt, + struct TALER_BlindedDenominationSignature *bs); + + +/** + * Request helper @a dh to sign batch of @a reqs requests. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper process connection + * @param reqs information about the keys to sign with and the values to sign + * @param reqs_length length of the @a reqs array + * @param for_melt true if this is for a melt operation + * @param[out] bss array set to the blind signatures, must be of length @a reqs_length! + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_batch_sign ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + unsigned int reqs_length, + const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length], + bool for_melt, + struct TALER_BlindedDenominationSignature bss[static reqs_length]); + + +/** + * Ask the helper to revoke the public key associated with @a h_cs. + * Will cause the helper to tell all clients that the key is now unavailable, + * and to create a replacement key. + * + * This operation will block until the revocation request has been + * transmitted. Should this process receive a signal (that is not ignored) + * while the operation is pending, the operation may fail. If the key is + * unknown, this function will also appear to have succeeded. To be sure that + * the revocation worked, clients must watch the denomination key status + * callback. + * + * @param dh helper to process connection + * @param h_cs hash of the CS public key to revoke + */ +void +TALER_CRYPTO_helper_cs_revoke ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CsPubHashP *h_cs); + + +/** + * Information about what we should derive for. + */ +struct TALER_CRYPTO_CsDeriveRequest +{ + /** + * Hash of the CS public key to use to sign. + */ + const struct TALER_CsPubHashP *h_cs; + + /** + * Nonce to use for the /csr request. + */ + const struct GNUNET_CRYPTO_CsSessionNonce *nonce; +}; + + +/** + * Ask the helper to derive R using the information + * from @a cdr. + * + * This operation will block until the R has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper to process connection + * @param cdr derivation input data + * @param for_melt true if this is for a melt operation + * @param[out] crp set to the pair of R values + * @return set to the error code (or #TALER_EC_NONE on success) + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_r_derive ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CRYPTO_CsDeriveRequest *cdr, + bool for_melt, + struct GNUNET_CRYPTO_CSPublicRPairP *crp); + + +/** + * Ask the helper to derive R using the information from @a cdrs. + * + * This operation will block until the R has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper to process connection + * @param cdrs_length length of the @a cdrs array + * @param cdrs array with derivation input data + * @param for_melt true if this is for a melt operation + * @param[out] crps array set to the pair of R values, must be of length @a cdrs_length + * @return set to the error code (or #TALER_EC_NONE on success) + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_r_batch_derive ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + unsigned int cdrs_length, + const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length], + bool for_melt, + struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length]); + + +/** + * Close connection to @a dh. + * + * @param[in] dh connection to close + */ +void +TALER_CRYPTO_helper_cs_disconnect ( + struct TALER_CRYPTO_CsDenominationHelper *dh); + /** * Handle for talking to an online key signing helper. */ @@ -1484,7 +2748,7 @@ struct TALER_CRYPTO_ExchangeSignHelper; typedef void (*TALER_CRYPTO_ExchangeKeyStatusCallback)( void *cls, - struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Relative validity_duration, const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_SecurityModulePublicKeyP *sm_pub, @@ -1495,6 +2759,7 @@ typedef void * Initiate connection to an online signing key helper. * * @param cfg configuration to use + * @param section configuration section prefix to use, usually 'taler' or 'donau' * @param ekc function to call with key information * @param ekc_cls closure for @a ekc * @return NULL on error (such as bad @a cfg). @@ -1502,6 +2767,7 @@ typedef void struct TALER_CRYPTO_ExchangeSignHelper * TALER_CRYPTO_helper_esign_connect ( const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, TALER_CRYPTO_ExchangeKeyStatusCallback ekc, void *ekc_cls); @@ -1572,7 +2838,7 @@ TALER_CRYPTO_helper_esign_sign_ ( /** - * Ask the helper to revoke the public key @param exchange_pub . + * Ask the helper to revoke the public key @a exchange_pub . * Will cause the helper to tell all clients that the key is now unavailable, * and to create a replacement key. * @@ -1601,41 +2867,510 @@ TALER_CRYPTO_helper_esign_disconnect ( struct TALER_CRYPTO_ExchangeSignHelper *esh); -/* ********************* exchange signing ************************** */ +/* ********************* wallet signing ************************** */ /** - * Verify a deposit confirmation. + * Sign a request to create a purse. * - * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param h_wire hash of the merchant’s account details - * @param h_extensions hash over the extensions, can be NULL - * @param exchange_timestamp timestamp when the contract was finalized, must not be too far off - * @param wire_deadline date until which the exchange should wire the funds - * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param amount_without_fee the amount to be deposited after fees - * @param coin_pub public key of the deposited coin - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param exchange_pub exchange's online signing public key - * @param exchange_sig the signature made with purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param merge_pub public key defining the merge capability + * @param min_age age restriction to apply for deposits into the purse + * @param amount total amount in the purse (including fees) + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_create_sign ( + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PurseMergePublicKeyP *merge_pub, + uint32_t min_age, + const struct TALER_Amount *amount, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse creation request. + * + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param merge_pub public key defining the merge capability + * @param min_age age restriction to apply for deposits into the purse + * @param amount total amount in the purse (including fees) + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE * @return #GNUNET_OK if the signature is valid */ enum GNUNET_GenericReturnValue -TALER_exchange_deposit_confirm_verify ( - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_ExtensionContractHash *h_extensions, - struct GNUNET_TIME_Absolute exchange_timestamp, - struct GNUNET_TIME_Absolute wire_deadline, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_Amount *amount_without_fee, +TALER_wallet_purse_create_verify ( + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PurseMergePublicKeyP *merge_pub, + uint32_t min_age, + const struct TALER_Amount *amount, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to delete a purse. + * + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_delete_sign ( + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse deletion request. + * + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_DELETE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_delete_verify ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to upload an encrypted contract. + * + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param contract_pub public key for the DH-encryption + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_econtract_upload_sign ( + const void *econtract, + size_t econtract_size, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a signature over encrypted contract. + * + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param contract_pub public key for the DH-encryption + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_econtract_upload_verify ( + const void *econtract, + size_t econtract_size, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a signature over encrypted contract. + * + * @param h_econtract hashed encrypted contract + * @param contract_pub public key for the DH-encryption + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_econtract_upload_verify2 ( + const struct GNUNET_HashCode *h_econtract, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to inquire about a purse's status. + * + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_status_sign ( + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse status request signature. + * + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_STATUS + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_status_verify ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to deposit a coin into a purse. + * + * @param exchange_base_url URL of the exchange hosting the purse + * @param purse_pub purse’s public key + * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment + * @param coin_priv key identifying the coin to be deposited + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_purse_deposit_sign ( + const char *exchange_base_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify a purse deposit request. + * + * @param exchange_base_url URL of the exchange hosting the purse + * @param purse_pub purse’s public key + * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment + * @param coin_pub key identifying the coin that is being deposited + * @param[out] coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_deposit_verify ( + const char *exchange_base_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_ExchangePublicKeyP *exchange_pub, - const struct TALER_ExchangeSignatureP *exchange_sig); + const struct TALER_CoinSpendSignatureP *coin_sig); -/* ********************* wallet signing ************************** */ +/** + * Sign a request by a purse to merge it into an account. + * + * @param reserve_uri identifies the location of the reserve + * @param merge_timestamp time when the merge happened + * @param purse_pub key identifying the purse + * @param merge_priv key identifying the merge capability + * @param[out] merge_sig resulting signature + */ +void +TALER_wallet_purse_merge_sign ( + const char *reserve_uri, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + struct TALER_PurseMergeSignatureP *merge_sig); + + +/** + * Verify a purse merge request. + * + * @param reserve_uri identifies the location of the reserve + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param merge_pub public key of the merge capability + * @param merge_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_MERGE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_merge_verify ( + const char *reserve_uri, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + const struct TALER_PurseMergeSignatureP *merge_sig); + + +/** + * Flags for a merge signature. + */ +enum TALER_WalletAccountMergeFlags +{ + + /** + * A mode must be set. None is not a legal mode! + */ + TALER_WAMF_MODE_NONE = 0, + + /** + * We are merging a fully paid-up purse into a reserve. + */ + TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE = 1, + + /** + * We are creating a fresh purse, from the contingent + * of free purses that our account brings. + */ + TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA = 2, + + /** + * The account owner is willing to pay the purse_fee for the purse to be + * created from the account balance. + */ + TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE = 3, + + /** + * Bitmask to AND the full flags with to get the mode. + */ + TALER_WAMF_MERGE_MODE_MASK = 3 + +}; + + +/** + * Sign a request by an account to merge a purse. + * + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param amount total amount in the purse (including fees) + * @param purse_fee purse fee the reserve will pay, + * only used if @a flags is #TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE + * @param min_age age restriction to apply for deposits into the purse + * @param flags flags for the operation + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_account_merge_sign ( + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *purse_fee, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify an account's request to merge a purse. + * + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param amount total amount in the purse (including fees) + * @param purse_fee purse fee the reserve will pay, + * only used if @a flags is #TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE + * @param min_age age restriction to apply for deposits into the purse + * @param flags flags for the operation + * @param reserve_pub account’s public key + * @param reserve_sig the signature made with purpose #TALER_SIGNATURE_WALLET_ACCOUNT_MERGE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_account_merge_verify ( + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *purse_fee, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign a request to keep a reserve open. + * + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_open_sign ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify a request to keep a reserve open. + * + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_pub key identifying the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_open_verify ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign to deposit coin to pay for keeping a reserve open. + * + * @param coin_contribution how much the coin should contribute + * @param reserve_sig signature over the reserve open operation + * @param coin_priv private key of the coin + * @param[out] coin_sig signature by the coin + */ +void +TALER_wallet_reserve_open_deposit_sign ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify signature that deposits coin to pay for keeping a reserve open. + * + * @param coin_contribution how much the coin should contribute + * @param reserve_sig signature over the reserve open operation + * @param coin_pub public key of the coin + * @param coin_sig signature by the coin + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_open_deposit_verify ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign a request to close a reserve. + * + * @param request_timestamp when was the request created + * @param h_payto where to send the funds (NULL allowed to send + * to origin of the reserve) + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_close_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify wallet request to close an account. + * + * @param request_timestamp when was the request created + * @param h_payto where to send the funds (NULL/all zeros + * allowed to send to origin of the reserve) + * @param reserve_pub account’s public key + * @param reserve_sig the signature made with purpose #TALER_SIGNATURE_WALLET_RESERVE_CLOSE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_close_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign a request by a wallet to perform a KYC check. + * + * @param reserve_priv key identifying the wallet/account + * @param balance_threshold the balance threshold the wallet is about to cross + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_account_setup_sign ( + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *balance_threshold, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify account setup request. + * + * @param reserve_pub reserve the setup request was for + * @param balance_threshold the balance threshold the wallet is about to cross + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_account_setup_verify ( + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *balance_threshold, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign request to the exchange to confirm certain + * @a details about the owner of a reserve. + * + * @param request_timestamp when was the request created + * @param details which attributes are requested + * @param reserve_priv private key of the reserve + * @param[out] reserve_sig where to store the signature + */ +void +TALER_wallet_reserve_attest_request_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify request to the exchange to confirm certain + * @a details about the owner of a reserve. + * + * @param request_timestamp when was the request created + * @param details which attributes are requested + * @param reserve_pub public key of the reserve + * @param reserve_sig where to store the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_attest_request_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); /** @@ -1645,7 +3380,9 @@ TALER_exchange_deposit_confirm_verify ( * @param deposit_fee the deposit fee we expect to pay * @param h_wire hash of the merchant’s account details * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param h_extensions hash over the extensions + * @param wallet_data_hash hash over wallet inputs into the contract (maybe NULL) + * @param h_age_commitment hash over the age commitment, if applicable to the denomination (maybe NULL) + * @param h_policy hash over the policy extension * @param h_denom_pub hash of the coin denomination's public key * @param coin_priv coin’s private key * @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future @@ -1657,13 +3394,15 @@ void TALER_wallet_deposit_sign ( const struct TALER_Amount *amount, const struct TALER_Amount *deposit_fee, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_ExtensionContractHash *h_extensions, - const struct TALER_DenominationHash *h_denom_pub, - struct GNUNET_TIME_Absolute wallet_timestamp, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct GNUNET_HashCode *wallet_data_hash, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_ExtensionPolicyHashP *h_policy, + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp wallet_timestamp, const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig); @@ -1675,7 +3414,9 @@ TALER_wallet_deposit_sign ( * @param deposit_fee the deposit fee we expect to pay * @param h_wire hash of the merchant’s account details * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param h_extensions hash over the extensions + * @param wallet_data_hash hash over wallet inputs into the contract (maybe NULL) + * @param h_age_commitment hash over the age commitment (maybe all zeroes, if not applicable to the denomination) + * @param h_policy hash over the policy extension * @param h_denom_pub hash of the coin denomination's public key * @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) @@ -1688,13 +3429,60 @@ enum GNUNET_GenericReturnValue TALER_wallet_deposit_verify ( const struct TALER_Amount *amount, const struct TALER_Amount *deposit_fee, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_ExtensionContractHash *h_extensions, - const struct TALER_DenominationHash *h_denom_pub, - struct GNUNET_TIME_Absolute wallet_timestamp, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct GNUNET_HashCode *wallet_data_hash, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_ExtensionPolicyHashP *h_policy, + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp wallet_timestamp, const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign a melt request. + * + * @param amount_with_fee the amount to be melted (with fee) + * @param melt_fee the melt fee we expect to pay + * @param rc refresh session we are committed to + * @param h_denom_pub hash of the coin denomination's public key + * @param h_age_commitment hash of the age commitment (may be NULL) + * @param coin_priv coin’s private key + * @param[out] coin_sig set to the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT + */ +void +TALER_wallet_melt_sign ( + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *melt_fee, + const struct TALER_RefreshCommitmentP *rc, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify a melt request. + * + * @param amount_with_fee the amount to be melted (with fee) + * @param melt_fee the melt fee we expect to pay + * @param rc refresh session we are committed to + * @param h_denom_pub hash of the coin denomination's public key + * @param h_age_commitment hash of the age commitment (may be NULL) + * @param coin_pub coin’s public key + * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_melt_verify ( + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *melt_fee, + const struct TALER_RefreshCommitmentP *rc, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig); @@ -1704,18 +3492,17 @@ TALER_wallet_deposit_verify ( * * @param h_denom_pub hash of the denomiantion public key of the new coin * @param transfer_pub transfer public key - * @param coin_ev coin envelope - * @param coin_ev_size number of bytes in @a coin_ev + * @param bch blinded coin hash * @param old_coin_priv private key to sign with * @param[out] coin_sig resulting signature */ void -TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub, - const struct TALER_TransferPublicKeyP *transfer_pub, - const void *coin_ev, - size_t coin_ev_size, - const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, - struct TALER_CoinSpendSignatureP *coin_sig); +TALER_wallet_link_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_TransferPublicKeyP *transfer_pub, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); /** @@ -1723,25 +3510,1269 @@ TALER_wallet_link_sign (const struct TALER_DenominationHash *h_denom_pub, * * @param h_denom_pub hash of the denomiantion public key of the new coin * @param transfer_pub transfer public key - * @param coin_ev coin envelope - * @param coin_ev_size number of bytes in @a coin_ev + * @param h_coin_ev hash of the coin envelope * @param old_coin_pub old coin key that the link signature is for * @param coin_sig resulting signature * @return #GNUNET_OK if the signature is valid */ enum GNUNET_GenericReturnValue TALER_wallet_link_verify ( - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_TransferPublicKeyP *transfer_pub, - const void *coin_ev, - size_t coin_ev_size, + const struct TALER_BlindedCoinHashP *h_coin_ev, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig); + +/** + * Sign withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_priv private key to sign with + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_withdraw_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_pub public key of the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_withdraw_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign age-withdraw request. + * + * @param h_commitment hash over all n*kappa blinded coins in the commitment for the age-withdraw + * @param amount_with_fee amount to debit the reserve for + * @param mask the mask that defines the age groups + * @param max_age maximum age from which the age group is derived, that the withdrawn coins must be restricted to. + * @param reserve_priv private key to sign with + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_age_withdraw_sign ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + +/** + * Verify an age-withdraw request. + * + * @param h_commitment hash all n*kappa blinded coins in the commitment for the age-withdraw + * @param amount_with_fee amount to debit the reserve for + * @param mask the mask that defines the age groups + * @param max_age maximum age from which the age group is derived, that the withdrawn coins must be restricted to. + * @param reserve_pub public key of the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_age_withdraw_verify ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + +/** + * Verify exchange melt confirmation. + * + * @param rc refresh session this is about + * @param noreveal_index gamma value chosen by the exchange + * @param exchange_pub public signing key used + * @param exchange_sig signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_melt_confirmation_verify ( + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +/** + * Verify recoup signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_pub coin key of the coin to be recouped + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_recoup_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create recoup signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_priv coin key of the coin to be recouped + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_recoup_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify recoup-refresh signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_pub coin key of the coin to be recouped + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_recoup_refresh_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create recoup-refresh signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_priv coin key of the coin to be recouped + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_recoup_refresh_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify reserve history request signature. + * + * @param start_off start of the requested range + * @param reserve_pub reserve the history request was for + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_history_verify ( + uint64_t start_off, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Create reserve status request signature. + * + * @param start_off start of the requested range + * @param reserve_priv private key of the reserve the history request is for + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_history_sign ( + uint64_t start_off, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify coin history request signature. + * + * @param start_off start of the requested range + * @param coin_pub coin the history request was for + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_coin_history_verify ( + uint64_t start_off, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create coin status request signature. + * + * @param start_off start of the requested range + * @param coin_priv private key of the coin the history request is for + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_coin_history_sign ( + uint64_t start_off, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/* ********************* merchant signing ************************** */ + + +/** + * Create merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_priv private key to sign with + * @param[out] merchant_sig where to write the signature + */ +void +TALER_merchant_refund_sign ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Verify merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_pub public key of the merchant + * @param merchant_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_refund_verify ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/* ********************* exchange deposit signing ************************* */ + +/** + * Sign a deposit. + * + * @param h_contract_terms hash of contract terms + * @param h_wire hash of the merchant account details + * @param coin_pub coin to be deposited + * @param merchant_priv private key to sign with + * @param[out] merchant_sig where to write the signature + */ +void +TALER_merchant_deposit_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Verify a deposit. + * + * @param merchant merchant public key + * @param coin_pub public key of the deposited coin + * @param h_contract_terms hash of contract terms + * @param h_wire hash of the merchant account details + * @param merchant_sig signature of the merchant + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_deposit_verify ( + const struct TALER_MerchantPublicKeyP *merchant, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/* ********************* exchange online signing ************************** */ + + +/** + * Signature of a function that signs the message in @a purpose with the + * exchange's signing key. + * + * The @a purpose data is the beginning of the data of which the signature is + * to be created. The `size` field in @a purpose must correctly indicate the + * number of bytes of the data structure, including its header. * + * @param purpose the message to sign + * @param[out] pub set to the current public signing key of the exchange + * @param[out] sig signature over purpose using current signing key + * @return #TALER_EC_NONE on success + */ +typedef enum TALER_ErrorCode +(*TALER_ExchangeSignCallback)( + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Signature of a function that signs the message in @a purpose with the + * exchange's signing key. + * + * The @a purpose data is the beginning of the data of which the signature is + * to be created. The `size` field in @a purpose must correctly indicate the + * number of bytes of the data structure, including its header. * + * @param cls closure + * @param purpose the message to sign + * @param[out] pub set to the current public signing key of the exchange + * @param[out] sig signature over purpose using current signing key + * @return #TALER_EC_NONE on success + */ +typedef enum TALER_ErrorCode +(*TALER_ExchangeSignCallback2)( + void *cls, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Create deposit confirmation signature. + * + * @param scb function to call to create the signature + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param h_wire hash of the merchant’s account details + * @param h_policy hash over the policy extension, can be NULL + * @param exchange_timestamp timestamp when the contract was finalized, must not be too far off + * @param wire_deadline date until which the exchange should wire the funds + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param total_without_fee the total amount to be deposited after fees over all coins + * @param num_coins length of @a coin_sigs array + * @param coin_sigs signatures of the deposited coins + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_deposit_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], + const struct TALER_MerchantPublicKeyP *merchant_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify deposit confirmation signature. + * + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param h_wire hash of the merchant’s account details + * @param h_policy hash over the policy extension, can be NULL + * @param exchange_timestamp timestamp when the contract was finalized, must not be too far off + * @param wire_deadline date until which the exchange should wire the funds + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param total_without_fee the total amount to be deposited after fees over all coins + * @param num_coins length of @a coin_sigs array + * @param coin_sigs signatures of the deposited coins + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_deposit_confirmation_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create refund confirmation signature. + * + * @param scb function to call to create the signature + * @param h_contract_terms hash of contract being refunded + * @param coin_pub public key of the coin receiving the refund + * @param merchant public key of the merchant that granted the refund + * @param rtransaction_id refund transaction ID used by the merchant + * @param refund_amount amount refunded + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_refund_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + uint64_t rtransaction_id, + const struct TALER_Amount *refund_amount, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify refund confirmation signature. + * + * @param h_contract_terms hash of contract being refunded + * @param coin_pub public key of the coin receiving the refund + * @param merchant public key of the merchant that granted the refund + * @param rtransaction_id refund transaction ID used by the merchant + * @param refund_amount amount refunded + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_refund_confirmation_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + uint64_t rtransaction_id, + const struct TALER_Amount *refund_amount, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create refresh melt confirmation signature. + * + * @param scb function to call to create the signature + * @param rc refresh commitment that identifies the melt operation + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_melt_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify refresh melt confirmation signature. + * + * @param rc refresh commitment that identifies the melt operation + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_melt_confirmation_verify ( + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create exchange purse refund confirmation signature. + * + * @param scb function to call to create the signature + * @param amount_without_fee refunded amount + * @param refund_fee refund fee charged + * @param coin_pub coin that was refunded + * @param purse_pub public key of the expired purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_refund_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *refund_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature of exchange affirming purse refund + * from purse expiration. + * + * @param amount_without_fee refunded amount + * @param refund_fee refund fee charged + * @param coin_pub coin that was refunded + * @param purse_pub public key of the expired purse + * @param pub public key to verify signature against + * @param sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_refund_verify ( + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *refund_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create exchange key set signature. + * + * @param scb function to call to create the signature + * @param cls closure for @a scb + * @param timestamp time when the key set was issued + * @param hc hash over all the keys + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_key_set_sign ( + TALER_ExchangeSignCallback2 scb, + void *cls, + struct GNUNET_TIME_Timestamp timestamp, + const struct GNUNET_HashCode *hc, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify key set signature. + * + * @param timestamp time when the key set was issued + * @param hc hash over all the keys + * @param pub public key to verify signature against + * @param sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_key_set_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct GNUNET_HashCode *hc, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create account KYC setup success signature. + * + * @param scb function to call to create the signature + * @param h_payto target of the KYC account + * @param kyc JSON data describing which KYC checks + * were satisfied + * @param timestamp time when the KYC was confirmed + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_account_setup_success_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PaytoHashP *h_payto, + const json_t *kyc, + struct GNUNET_TIME_Timestamp timestamp, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify account KYC setup success signature. + * + * @param h_payto target of the KYC account + * @param kyc JSON data describing which KYC checks + * were satisfied + * @param timestamp time when the KYC was confirmed + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_account_setup_success_verify ( + const struct TALER_PaytoHashP *h_payto, + const json_t *kyc, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Hash normalized @a j JSON object or array and + * store the result in @a hc. + * + * @param j JSON to hash + * @param[out] hc where to write the hash + */ +void +TALER_json_hash (const json_t *j, + struct GNUNET_HashCode *hc); + + +/** + * Update the @a hash_context in the computation of the + * h_details for a wire status signature. + * + * @param[in,out] hash_context context to update + * @param h_contract_terms hash of the contract + * @param execution_time when was the wire transfer initiated + * @param coin_pub deposited coin + * @param deposit_value contribution of the coin + * @param deposit_fee how high was the deposit fee + */ +void +TALER_exchange_online_wire_deposit_append ( + struct GNUNET_HashContext *hash_context, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee); + + +/** + * Create wire deposit signature. + * + * @param scb function to call to create the signature + * @param total amount the merchant was credited + * @param wire_fee fee charged by the exchange for the wire transfer + * @param merchant_pub which merchant was credited + * @param payto payto://-URI of the merchant account + * @param h_details hash over the aggregation details + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_wire_deposit_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_Amount *total, + const struct TALER_Amount *wire_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *payto, + const struct GNUNET_HashCode *h_details, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify wire deposit signature. + * + * @param total amount the merchant was credited + * @param wire_fee fee charged by the exchange for the wire transfer + * @param merchant_pub which merchant was credited + * @param h_payto hash of the payto://-URI of the merchant account + * @param h_details hash over the aggregation details + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_wire_deposit_verify ( + const struct TALER_Amount *total, + const struct TALER_Amount *wire_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PaytoHashP *h_payto, + const struct GNUNET_HashCode *h_details, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create wire confirmation signature. + * + * @param scb function to call to create the signature + * @param h_wire hash of the merchant's account + * @param h_contract_terms hash of the contract + * @param wtid wire transfer this deposit was aggregated into + * @param coin_pub public key of the deposited coin + * @param execution_time when was wire transfer initiated + * @param coin_contribution what was @a coin_pub's contribution to the wire transfer + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_wire_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_Amount *coin_contribution, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm wire signature. + * + * @param h_wire hash of the merchant's account + * @param h_contract_terms hash of the contract + * @param wtid wire transfer this deposit was aggregated into + * @param coin_pub public key of the deposited coin + * @param execution_time when was wire transfer initiated + * @param coin_contribution what was @a coin_pub's contribution to the wire transfer + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_wire_verify ( + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_Amount *coin_contribution, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create confirm recoup signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param reserve_pub reserve that was credited + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_recoup_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm recoup signature. + * + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param reserve_pub reserve that was credited + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_recoup_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create confirm recoup refresh signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param old_coin_pub old coin that was credited + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_recoup_refresh_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm recoup refresh signature. + * + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param old_coin_pub old coin that was credited + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_recoup_refresh_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create denomination unknown signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is unknown + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_denomination_unknown_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify denomination unknown signature. + * + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is unknown + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_denomination_unknown_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create denomination expired signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is expired + * @param op character string describing the operation for which + * the denomination is expired + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_denomination_expired_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const char *op, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify denomination expired signature. + * + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is expired + * @param op character string describing the operation for which + * the denomination is expired + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_denomination_expired_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const char *op, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create reserve closure signature. + * + * @param scb function to call to create the signature + * @param timestamp time when the reserve was closed + * @param closing_amount amount left in the reserve + * @param closing_fee closing fee charged + * @param payto target of the wire transfer + * @param wtid wire transfer subject used + * @param reserve_pub public key of the closed reserve + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_reserve_closed_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *closing_amount, + const struct TALER_Amount *closing_fee, + const char *payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify reserve closure signature. + * + * @param timestamp time when the reserve was closed + * @param closing_amount amount left in the reserve + * @param closing_fee closing fee charged + * @param payto target of the wire transfer + * @param wtid wire transfer subject used + * @param reserve_pub public key of the closed reserve + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_reserve_closed_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *closing_amount, + const struct TALER_Amount *closing_fee, + const char *payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create signature by exchange affirming that a reserve + * has had certain attributes verified via KYC. + * + * @param scb function to call to create the signature + * @param attest_timestamp our time + * @param expiration_time when does the KYC data expire + * @param reserve_pub for which reserve are attributes attested + * @param attributes JSON object with attributes being attested to + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_reserve_attest_details_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature by exchange affirming that a reserve + * has had certain attributes verified via KYC. + * + * @param attest_timestamp our time + * @param expiration_time when does the KYC data expire + * @param reserve_pub for which reserve are attributes attested + * @param attributes JSON object with attributes being attested to + * @param pub exchange public key + * @param sig exchange signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_reserve_attest_details_verify ( + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Create signature by exchange affirming that a purse was created. + * + * @param scb function to call to create the signature + * @param exchange_time our time + * @param purse_expiration when will the purse expire + * @param amount_without_fee total amount to be put into the purse (without deposit fees) + * @param total_deposited total currently in the purse + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract for the purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_created_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *total_deposited, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify exchange signature about a purse creation and balance. + * + * @param exchange_time our time + * @param purse_expiration when will the purse expire + * @param amount_without_fee total amount to be put into the purse (without deposit fees) + * @param total_deposited total currently in the purse + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract for the purse + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_created_verify ( + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *total_deposited, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Sign affirmation that a purse was merged. + * + * @param scb function to call to create the signature + * @param exchange_time our time + * @param purse_expiration when does the purse expire + * @param amount_without_fee total amount that should be in the purse without deposit fees + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract of the purse + * @param reserve_pub reserve the purse will be merged into + * @param exchange_url exchange at which the @a reserve_pub lives + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_merged_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *exchange_url, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify affirmation that a purse will be merged. + * + * @param exchange_time our time + * @param purse_expiration when does the purse expire + * @param amount_without_fee total amount that should be in the purse without deposit fees + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract of the purse + * @param reserve_pub reserve the purse will be merged into + * @param exchange_url exchange at which the @a reserve_pub lives + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_merged_verify ( + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *exchange_url, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Sign information about the status of a purse. + * + * @param scb function to call to create the signature + * @param merge_timestamp when was the purse merged (can be never) + * @param deposit_timestamp when was the purse fully paid up (can be never) + * @param balance current balance of the purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_status_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp merge_timestamp, + struct GNUNET_TIME_Timestamp deposit_timestamp, + const struct TALER_Amount *balance, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature over information about the status of a purse. + * + * @param merge_timestamp when was the purse merged (can be never) + * @param deposit_timestamp when was the purse fully paid up (can be never) + * @param balance current balance of the purse + * @param exchange_pub the public key of the exchange to check against + * @param exchange_sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_status_verify ( + struct GNUNET_TIME_Timestamp merge_timestamp, + struct GNUNET_TIME_Timestamp deposit_timestamp, + const struct TALER_Amount *balance, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +/** + * Create age-withdraw confirmation signature. + * + * @param scb function to call to create the signature + * @param h_commitment age-withdraw commitment that identifies the n*kappa blinded coins + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_age_withdraw_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + uint32_t noreveal_index, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify an exchange age-withdraw confirmation + * + * @param h_commitment Commitment over all n*kappa coin candidates from the original request to age-withdraw + * @param noreveal_index The index returned by the exchange + * @param exchange_pub The public key used for signing + * @param exchange_sig The signature from the exchange + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_age_withdraw_confirmation_verify ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + /* ********************* offline signing ************************** */ /** + * Create AML officer status change signature. + * + * @param officer_pub public key of the AML officer + * @param officer_name name of the officer + * @param change_date when to affect the status change + * @param is_active true to enable the officer + * @param read_only true to only allow read-only access + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_aml_officer_status_sign ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *officer_name, + struct GNUNET_TIME_Timestamp change_date, + bool is_active, + bool read_only, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify AML officer status change signature. + * + * @param officer_pub public key of the AML officer + * @param officer_name name of the officer + * @param change_date when to affect the status change + * @param is_active true to enable the officer + * @param read_only true to only allow read-only access + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_aml_officer_status_verify ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *officer_name, + struct GNUNET_TIME_Timestamp change_date, + bool is_active, + bool read_only, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** * Create auditor addition signature. * * @param auditor_pub public key of the auditor @@ -1754,7 +4785,7 @@ void TALER_exchange_offline_auditor_add_sign ( const struct TALER_AuditorPublicKeyP *auditor_pub, const char *auditor_url, - struct GNUNET_TIME_Absolute start_date, + struct GNUNET_TIME_Timestamp start_date, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -1773,7 +4804,7 @@ enum GNUNET_GenericReturnValue TALER_exchange_offline_auditor_add_verify ( const struct TALER_AuditorPublicKeyP *auditor_pub, const char *auditor_url, - struct GNUNET_TIME_Absolute start_date, + struct GNUNET_TIME_Timestamp start_date, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -1789,7 +4820,7 @@ TALER_exchange_offline_auditor_add_verify ( void TALER_exchange_offline_auditor_del_sign ( const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Absolute end_date, + struct GNUNET_TIME_Timestamp end_date, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -1806,7 +4837,7 @@ TALER_exchange_offline_auditor_del_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_auditor_del_verify ( const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Absolute end_date, + struct GNUNET_TIME_Timestamp end_date, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -1820,7 +4851,7 @@ TALER_exchange_offline_auditor_del_verify ( */ void TALER_exchange_offline_denomination_revoke_sign ( - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -1835,7 +4866,7 @@ TALER_exchange_offline_denomination_revoke_sign ( */ enum GNUNET_GenericReturnValue TALER_exchange_offline_denomination_revoke_verify ( - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -1882,9 +4913,9 @@ TALER_exchange_offline_signkey_revoke_verify ( void TALER_exchange_offline_signkey_validity_sign ( const struct TALER_ExchangePublicKeyP *exchange_pub, - struct GNUNET_TIME_Absolute start_sign, - struct GNUNET_TIME_Absolute end_sign, - struct GNUNET_TIME_Absolute end_legal, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Timestamp end_sign, + struct GNUNET_TIME_Timestamp end_legal, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -1903,9 +4934,9 @@ TALER_exchange_offline_signkey_validity_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_signkey_validity_verify ( const struct TALER_ExchangePublicKeyP *exchange_pub, - struct GNUNET_TIME_Absolute start_sign, - struct GNUNET_TIME_Absolute end_sign, - struct GNUNET_TIME_Absolute end_legal, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Timestamp end_sign, + struct GNUNET_TIME_Timestamp end_legal, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -1919,25 +4950,19 @@ TALER_exchange_offline_signkey_validity_verify ( * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key * @param coin_value what is the value of coins signed with this key - * @param fee_withdraw what withdraw fee does the exchange charge for this denomination - * @param fee_deposit what deposit fee does the exchange charge for this denomination - * @param fee_refresh what refresh fee does the exchange charge for this denomination - * @param fee_refund what refund fee does the exchange charge for this denomination + * @param fees fees for this denomination * @param master_priv private key to sign with * @param[out] master_sig where to write the signature */ void TALER_exchange_offline_denom_validity_sign ( - const struct TALER_DenominationHash *h_denom_pub, - struct GNUNET_TIME_Absolute stamp_start, - struct GNUNET_TIME_Absolute stamp_expire_withdraw, - struct GNUNET_TIME_Absolute stamp_expire_deposit, - struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, const struct TALER_Amount *coin_value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund, + const struct TALER_DenomFeeSet *fees, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -1951,26 +4976,118 @@ TALER_exchange_offline_denom_validity_sign ( * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key * @param coin_value what is the value of coins signed with this key - * @param fee_withdraw what withdraw fee does the exchange charge for this denomination - * @param fee_deposit what deposit fee does the exchange charge for this denomination - * @param fee_refresh what refresh fee does the exchange charge for this denomination - * @param fee_refund what refund fee does the exchange charge for this denomination + * @param fees fees for this denomination * @param master_pub public key to verify against * @param master_sig the signature the signature * @return #GNUNET_OK if the signature is valid */ enum GNUNET_GenericReturnValue TALER_exchange_offline_denom_validity_verify ( - const struct TALER_DenominationHash *h_denom_pub, - struct GNUNET_TIME_Absolute stamp_start, - struct GNUNET_TIME_Absolute stamp_expire_withdraw, - struct GNUNET_TIME_Absolute stamp_expire_deposit, - struct GNUNET_TIME_Absolute stamp_expire_legal, + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, const struct TALER_Amount *coin_value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund, + const struct TALER_DenomFeeSet *fees, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create offline signature about an exchange's partners. + * + * @param partner_pub master public key of the partner + * @param start_date validity period start + * @param end_date validity period end + * @param wad_frequency how often will we do wad transfers to this partner + * @param wad_fee what is the wad fee to this partner + * @param partner_base_url what is the base URL of the @a partner_pub exchange + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_partner_details_sign ( + const struct TALER_MasterPublicKeyP *partner_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify signature about an exchange's partners. + * + * @param partner_pub master public key of the partner + * @param start_date validity period start + * @param end_date validity period end + * @param wad_frequency how often will we do wad transfers to this partner + * @param wad_fee what is the wad fee to this partner + * @param partner_base_url what is the base URL of the @a partner_pub exchange + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_partner_details_verify ( + const struct TALER_MasterPublicKeyP *partner_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create offline signature about wiring profits to a + * regular non-escrowed account of the exchange. + * + * @param wtid (random) wire transfer ID to be used + * @param date when was the profit drain approved (not exact time of execution) + * @param amount how much should be wired + * @param account_section configuration section of the + * exchange specifying the account to be debited + * @param payto_uri target account to be credited + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_profit_drain_sign ( + const struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp date, + const struct TALER_Amount *amount, + const char *account_section, + const char *payto_uri, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify offline signature about wiring profits to a + * regular non-escrowed account of the exchange. + * + * @param wtid (random) wire transfer ID to be used + * @param date when was the profit drain approved (not exact time of execution) + * @param amount how much should be wired + * @param account_section configuration section of the + * exchange specifying the account to be debited + * @param payto_uri target account to be credited + * @param master_pub public key to verify signature against + * @param master_sig the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_profit_drain_verify ( + const struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp date, + const struct TALER_Amount *amount, + const char *account_section, + const char *payto_uri, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -1987,7 +5104,7 @@ TALER_exchange_offline_denom_validity_verify ( void TALER_exchange_secmod_eddsa_sign ( const struct TALER_ExchangePublicKeyP *exchange_pub, - struct GNUNET_TIME_Absolute start_sign, + struct GNUNET_TIME_Timestamp start_sign, struct GNUNET_TIME_Relative duration, const struct TALER_SecurityModulePrivateKeyP *secm_priv, struct TALER_SecurityModuleSignatureP *secm_sig); @@ -2006,7 +5123,7 @@ TALER_exchange_secmod_eddsa_sign ( enum GNUNET_GenericReturnValue TALER_exchange_secmod_eddsa_verify ( const struct TALER_ExchangePublicKeyP *exchange_pub, - struct GNUNET_TIME_Absolute start_sign, + struct GNUNET_TIME_Timestamp start_sign, struct GNUNET_TIME_Relative duration, const struct TALER_SecurityModulePublicKeyP *secm_pub, const struct TALER_SecurityModuleSignatureP *secm_sig); @@ -2026,7 +5143,7 @@ void TALER_exchange_secmod_rsa_sign ( const struct TALER_RsaPubHashP *h_rsa, const char *section_name, - struct GNUNET_TIME_Absolute start_sign, + struct GNUNET_TIME_Timestamp start_sign, struct GNUNET_TIME_Relative duration, const struct TALER_SecurityModulePrivateKeyP *secm_priv, struct TALER_SecurityModuleSignatureP *secm_sig); @@ -2047,7 +5164,48 @@ enum GNUNET_GenericReturnValue TALER_exchange_secmod_rsa_verify ( const struct TALER_RsaPubHashP *h_rsa, const char *section_name, - struct GNUNET_TIME_Absolute start_sign, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePublicKeyP *secm_pub, + const struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Create security module denomination signature. + * + * @param h_cs hash of the CS public key to sign + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_priv security module key to sign with + * @param[out] secm_sig where to write the signature + */ +void +TALER_exchange_secmod_cs_sign ( + const struct TALER_CsPubHashP *h_cs, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePrivateKeyP *secm_priv, + struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Verify security module denomination signature. + * + * @param h_cs hash of the public key to validate + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_pub public key to verify against + * @param secm_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_secmod_cs_verify ( + const struct TALER_CsPubHashP *h_cs, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, struct GNUNET_TIME_Relative duration, const struct TALER_SecurityModulePublicKeyP *secm_pub, const struct TALER_SecurityModuleSignatureP *secm_sig); @@ -2064,27 +5222,21 @@ TALER_exchange_secmod_rsa_verify ( * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key * @param coin_value what is the value of coins signed with this key - * @param fee_withdraw what withdraw fee does the exchange charge for this denomination - * @param fee_deposit what deposit fee does the exchange charge for this denomination - * @param fee_refresh what refresh fee does the exchange charge for this denomination - * @param fee_refund what refund fee does the exchange charge for this denomination + * @param fees fees the exchange charges for this denomination * @param auditor_priv private key to sign with * @param[out] auditor_sig where to write the signature */ void TALER_auditor_denom_validity_sign ( const char *auditor_url, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute stamp_start, - struct GNUNET_TIME_Absolute stamp_expire_withdraw, - struct GNUNET_TIME_Absolute stamp_expire_deposit, - struct GNUNET_TIME_Absolute stamp_expire_legal, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, const struct TALER_Amount *coin_value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund, + const struct TALER_DenomFeeSet *fees, const struct TALER_AuditorPrivateKeyP *auditor_priv, struct TALER_AuditorSignatureP *auditor_sig); @@ -2100,10 +5252,7 @@ TALER_auditor_denom_validity_sign ( * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key * @param coin_value what is the value of coins signed with this key - * @param fee_withdraw what withdraw fee does the exchange charge for this denomination - * @param fee_deposit what deposit fee does the exchange charge for this denomination - * @param fee_refresh what refresh fee does the exchange charge for this denomination - * @param fee_refund what refund fee does the exchange charge for this denomination + * @param fees fees the exchange charges for this denomination * @param auditor_pub public key to verify against * @param auditor_sig the signature the signature * @return #GNUNET_OK if the signature is valid @@ -2111,17 +5260,14 @@ TALER_auditor_denom_validity_sign ( enum GNUNET_GenericReturnValue TALER_auditor_denom_validity_verify ( const char *auditor_url, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute stamp_start, - struct GNUNET_TIME_Absolute stamp_expire_withdraw, - struct GNUNET_TIME_Absolute stamp_expire_deposit, - struct GNUNET_TIME_Absolute stamp_expire_legal, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, const struct TALER_Amount *coin_value, - const struct TALER_Amount *fee_withdraw, - const struct TALER_Amount *fee_deposit, - const struct TALER_Amount *fee_refresh, - const struct TALER_Amount *fee_refund, + const struct TALER_DenomFeeSet *fees, const struct TALER_AuditorPublicKeyP *auditor_pub, const struct TALER_AuditorSignatureP *auditor_sig); @@ -2135,18 +5281,16 @@ TALER_auditor_denom_validity_verify ( * @param payment_method the payment method * @param start_time when do the fees start to apply * @param end_time when do the fees start to apply - * @param wire_fee the wire fee - * @param closing_fee the closing fee + * @param fees the wire fees * @param master_priv private key to sign with * @param[out] master_sig where to write the signature */ void TALER_exchange_offline_wire_fee_sign ( const char *payment_method, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -2157,8 +5301,7 @@ TALER_exchange_offline_wire_fee_sign ( * @param payment_method the payment method * @param start_time when do the fees start to apply * @param end_time when do the fees start to apply - * @param wire_fee the wire fee - * @param closing_fee the closing fee + * @param fees the wire fees * @param master_pub public key to verify against * @param master_sig the signature the signature * @return #GNUNET_OK if the signature is valid @@ -2166,10 +5309,58 @@ TALER_exchange_offline_wire_fee_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_fee_verify ( const char *payment_method, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create global fees signature. + * + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the global fees + * @param purse_timeout how long do unmerged purses stay around + * @param history_expiration how long do we keep the history of an account + * @param purse_account_limit how many concurrent purses are free per account holder + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_global_fee_sign ( + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify global fees signature. + * + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the global fees + * @param purse_timeout how long do unmerged purses stay around + * @param history_expiration how long do we keep the history of an account + * @param purse_account_limit how many concurrent purses are free per account holder + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_global_fee_verify ( + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -2178,6 +5369,9 @@ TALER_exchange_offline_wire_fee_verify ( * Create wire account addition signature. * * @param payto_uri bank account + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param now timestamp to use for the signature (rounded) * @param master_priv private key to sign with * @param[out] master_sig where to write the signature @@ -2185,7 +5379,10 @@ TALER_exchange_offline_wire_fee_verify ( void TALER_exchange_offline_wire_add_sign ( const char *payto_uri, - struct GNUNET_TIME_Absolute now, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp now, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -2194,6 +5391,9 @@ TALER_exchange_offline_wire_add_sign ( * Verify wire account addition signature. * * @param payto_uri bank account + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param sign_time timestamp when signature was created * @param master_pub public key to verify against * @param master_sig the signature the signature @@ -2202,7 +5402,10 @@ TALER_exchange_offline_wire_add_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_add_verify ( const char *payto_uri, - struct GNUNET_TIME_Absolute sign_time, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp sign_time, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -2218,7 +5421,7 @@ TALER_exchange_offline_wire_add_verify ( void TALER_exchange_offline_wire_del_sign ( const char *payto_uri, - struct GNUNET_TIME_Absolute now, + struct GNUNET_TIME_Timestamp now, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -2235,7 +5438,7 @@ TALER_exchange_offline_wire_del_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_del_verify ( const char *payto_uri, - struct GNUNET_TIME_Absolute sign_time, + struct GNUNET_TIME_Timestamp sign_time, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -2244,6 +5447,9 @@ TALER_exchange_offline_wire_del_verify ( * Check the signature in @a master_sig. * * @param payto_uri URI that is signed + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param master_pub master public key of the exchange * @param master_sig signature of the exchange * @return #GNUNET_OK if signature is valid @@ -2251,6 +5457,9 @@ TALER_exchange_offline_wire_del_verify ( enum GNUNET_GenericReturnValue TALER_exchange_wire_signature_check ( const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_MasterSignatureP *master_sig); @@ -2259,12 +5468,18 @@ TALER_exchange_wire_signature_check ( * Create a signed wire statement for the given account. * * @param payto_uri account specification + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param master_priv private key to sign with * @param[out] master_sig where to write the signature */ void TALER_exchange_wire_signature_make ( const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -2280,8 +5495,8 @@ TALER_exchange_wire_signature_make ( */ void TALER_merchant_wire_signature_hash (const char *payto_uri, - const struct TALER_WireSalt *salt, - struct TALER_MerchantWireHash *hc); + const struct TALER_WireSaltP *salt, + struct TALER_MerchantWireHashP *hc); /** @@ -2296,7 +5511,7 @@ TALER_merchant_wire_signature_hash (const char *payto_uri, enum GNUNET_GenericReturnValue TALER_merchant_wire_signature_check ( const char *payto_uri, - const struct TALER_WireSalt *salt, + const struct TALER_WireSaltP *salt, const struct TALER_MerchantPublicKeyP *merch_pub, const struct TALER_MerchantSignatureP *merch_sig); @@ -2312,9 +5527,444 @@ TALER_merchant_wire_signature_check ( void TALER_merchant_wire_signature_make ( const char *payto_uri, - const struct TALER_WireSalt *salt, + const struct TALER_WireSaltP *salt, + const struct TALER_MerchantPrivateKeyP *merch_priv, + struct TALER_MerchantSignatureP *merch_sig); + + +/** + * Sign a payment confirmation. + * + * @param h_contract_terms hash of the contact of the merchant with the customer + * @param merch_priv private key to sign with + * @param[out] merch_sig where to write the signature + */ +void +TALER_merchant_pay_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_MerchantPrivateKeyP *merch_priv, struct TALER_MerchantSignatureP *merch_sig); +/** + * Verify payment confirmation signature. + * + * @param h_contract_terms hash of the contact of the merchant with the customer + * @param merchant_pub public key of the merchant + * @param merchant_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_pay_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Sign contract sent by the merchant to the wallet. + * + * @param h_contract_terms hash of the contract terms + * @param merch_priv private key to sign with + * @param[out] merch_sig where to write the signature + */ +void +TALER_merchant_contract_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantPrivateKeyP *merch_priv, + struct GNUNET_CRYPTO_EddsaSignature *merch_sig); + + +/* **************** /management/extensions offline signing **************** */ + +/** + * Create a signature for the hash of the manifests of extensions + * + * @param h_manifests hash of the JSON object representing the manifests + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_extension_manifests_hash_sign ( + const struct TALER_ExtensionManifestsHashP *h_manifests, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify the signature in @a master_sig of the given hash, taken over the JSON + * blob representing the manifests of extensions + * + * @param h_manifest hash of the JSON blob of manifests of extensions + * @param master_pub master public key of the exchange + * @param master_sig signature of the exchange + * @return #GNUNET_OK if signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_extension_manifests_hash_verify ( + const struct TALER_ExtensionManifestsHashP *h_manifest, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig + ); + + +/** + * @brief Representation of an age commitment: one public key per age group. + * + * The number of keys must be be the same as the number of bits set in the + * corresponding age mask. + */ +struct TALER_AgeCommitment +{ + + /** + * The age mask defines the age groups that were a parameter during the + * generation of this age commitment + */ + struct TALER_AgeMask mask; + + /** + * The number of public keys, which must be the same as the number of + * groups in the mask. + */ + size_t num; + + /** + * The list of @e num public keys. In must have same size as the number of + * age groups defined in the mask. + * + * A hash of this list is the hashed commitment that goes into FDC + * calculation during the withdraw and refresh operations for new coins. That + * way, the particular age commitment becomes mandatory and bound to a coin. + * + * The list has been allocated via GNUNET_malloc(). + */ + struct TALER_AgeCommitmentPublicKeyP *keys; +}; + + +/** + * @brief Proof for a particular age commitment, used in age attestation + * + * This struct is used in a call to TALER_age_commitment_attest to create an + * attestation for a minimum age (if that minimum age is less or equal to the + * committed age for this proof). It consists of a list private keys, one per + * age group, for which the committed age is either lager or within that + * particular group. + */ +struct TALER_AgeProof +{ + /** + * The number of private keys, which must be at most num_pub_keys. One minus + * this number corresponds to the largest age group that is supported with + * this age commitment. + * **Note**, that this and the next field are only relevant on the wallet + * side for attestation and derive operations. + */ + size_t num; + + /** + * List of @e num private keys. + * + * Note that the list can be _smaller_ than the corresponding list of public + * keys. In that case, the wallet can sign off only for a subset of the age + * groups. + * + * The list has been allocated via GNUNET_malloc. + */ + struct TALER_AgeCommitmentPrivateKeyP *keys; +}; + + +/** + * @brief Commitment and Proof for a maximum age + * + * Calling TALER_age_restriction_commit on an (maximum) age value returns this + * data structure. It consists of the proof, which is used to create + * attestations for compatible minimum ages, and the commitment, which is used + * to verify the attestations and derived commitments. + * + * The hash value of the commitment is bound to a particular coin with age + * restriction. + */ +struct TALER_AgeCommitmentProof +{ + /** + * The commitment is used to verify a particular attestation. Its hash value + * is bound to a particular coin with age restriction. This structure is + * sent to the merchant in order to verify a particular attestation for a + * minimum age. + * In itself, it does not convey any information about the maximum age that + * went into the call to TALER_age_restriction_commit. + */ + struct TALER_AgeCommitment commitment; + + /** + * The proof is used to create an attestation for a (compatible) minimum age. + */ + struct TALER_AgeProof proof; +}; + + +/** + * @brief Generates a hash of the public keys in the age commitment. + * + * @param commitment the age commitment - one public key per age group + * @param[out] hash resulting hash + */ +void +TALER_age_commitment_hash ( + const struct TALER_AgeCommitment *commitment, + struct TALER_AgeCommitmentHash *hash); + + +/** + * @brief Generates an age commitent for the given age. + * + * @param mask The age mask the defines the age groups + * @param age The actual age for which an age commitment is generated + * @param seed The seed that goes into the key generation. MUST be chosen uniformly random. + * @param[out] comm_proof The generated age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success + */ +void +TALER_age_restriction_commit ( + const struct TALER_AgeMask *mask, + uint8_t age, + const struct GNUNET_HashCode *seed, + struct TALER_AgeCommitmentProof *comm_proof); + + +/** + * @brief Derives another, equivalent age commitment for a given one. + * + * @param orig Original age commitment + * @param salt Salt to randomly move the points on the elliptic curve in order to generate another, equivalent commitment. + * @param[out] derived The resulting age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success. + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_derive ( + const struct TALER_AgeCommitmentProof *orig, + const struct GNUNET_HashCode *salt, + struct TALER_AgeCommitmentProof *derived); + + +/** + * @brief Provide attestation for a given age, from a given age commitment, if possible. + * + * @param comm_proof The age commitment to be used for attestation. For successful attestation, it must contain the private key for the corresponding age group. + * @param age Age (not age group) for which the an attestation should be done + * @param[out] attest Signature of the age with the appropriate key from the age commitment for the corresponding age group, if applicable. + * @return #GNUNET_OK on success, #GNUNET_NO when no attestation can be made for that age with the given commitment, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_attest ( + const struct TALER_AgeCommitmentProof *comm_proof, + uint8_t age, + struct TALER_AgeAttestation *attest); + + +/** + * @brief Verify the attestation for an given age and age commitment + * + * @param commitment The age commitment that went into the attestation. Only the public keys are needed. + * @param age Age (not age group) for which the an attestation should be done + * @param attest Signature of the age with the appropriate key from the age commitment for the corresponding age group, if applicable. + * @return #GNUNET_OK when the attestation was successful, #GNUNET_NO no attestation couldn't be verified, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_verify ( + const struct TALER_AgeCommitment *commitment, + uint8_t age, + const struct TALER_AgeAttestation *attest); + + +/** + * @brief helper function to free memory of a struct TALER_AgeCommitment + * + * @param ac the commitment from which all memory should be freed. + */ +void +TALER_age_commitment_free ( + struct TALER_AgeCommitment *ac); + + +/** + * @brief helper function to free memory of a struct TALER_AgeProof + * + * @param ap the proof of commitment from which all memory should be freed. + */ +void +TALER_age_proof_free ( + struct TALER_AgeProof *ap); + + +/** + * @brief helper function to free memory of a struct TALER_AgeCommitmentProof + * + * @param acp the commitment and its proof from which all memory should be freed. + */ +void +TALER_age_commitment_proof_free ( + struct TALER_AgeCommitmentProof *acp); + + +/** + * @brief helper function to allocate and copy a struct TALER_AgeCommitmentProof + * + * @param[in] acp The original age commitment proof + * @return The deep copy of @e acp, allocated + */ +struct TALER_AgeCommitmentProof * +TALER_age_commitment_proof_duplicate ( + const struct TALER_AgeCommitmentProof *acp); + +/** + * @brief helper function to copy a struct TALER_AgeCommitmentProof + * + * @param[in] acp The original age commitment proof + * @param[out] nacp The struct to copy the data into, with freshly allocated and copied keys. + */ +void +TALER_age_commitment_proof_deep_copy ( + const struct TALER_AgeCommitmentProof *acp, + struct TALER_AgeCommitmentProof *nacp); + +/** + * @brief For age-withdraw, clients have to prove that the public keys for all + * age groups larger than the allowed maximum age group are derived by scalar + * multiplication from this Edx25519 public key (in Crockford Base32 encoding): + * + * DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG + * + * Its private key was chosen randomly and then deleted. + */ +extern struct +#ifndef AGE_RESTRICTION_WITH_ECDSA +GNUNET_CRYPTO_Edx25519PublicKey +#else +GNUNET_CRYPTO_EcdsaPublicKey +#endif +TALER_age_commitment_base_public_key; + +/** + * @brief Similar to TALER_age_restriction_commit, but takes the coin's + * private key as seed input and calculates the public keys in the slots larger + * than the given age as derived from TALER_age_commitment_base_public_key. + * + * See https://docs.taler.net/core/api-exchange.html#withdraw-with-age-restriction + * + * @param secret The master secret of the coin from which we derive the age restriction + * @param mask The age mask, defining the age groups + * @param max_age The maximum age for this coin. + * @param[out] comm_proof The commitment and proof for age restriction for age @a max_age + */ +void +TALER_age_restriction_from_secret ( + const struct TALER_PlanchetMasterSecretP *secret, + const struct TALER_AgeMask *mask, + const uint8_t max_age, + struct TALER_AgeCommitmentProof *comm_proof); + + +/** + * Group of Denominations. These are the common fields of an array of + * denominations. + * + * The corresponding JSON-blob will also contain an array of particular + * denominations with only the timestamps, cipher-specific public key and the + * master signature. + */ +struct TALER_DenominationGroup +{ + + /** + * Value of coins in this denomination group. + */ + struct TALER_Amount value; + + /** + * Fee structure for all coins in the group. + */ + struct TALER_DenomFeeSet fees; + + /** + * Cipher used for the denomination. + */ + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher; + + /** + * Age mask for the denomination. + */ + struct TALER_AgeMask age_mask; + +}; + + +/** + * Compute a unique key for the meta data of a denomination group. + * + * @param dg denomination group to evaluate + * @param[out] key key to set + */ +void +TALER_denomination_group_get_key ( + const struct TALER_DenominationGroup *dg, + struct GNUNET_HashCode *key); + + +/** + * Token family public key. + */ +struct TALER_TokenFamilyPublicKey +{ + /** + * Type of the signature. + */ + struct GNUNET_CRYPTO_BlindSignPublicKey public_key; +}; + +/** + * Hash of a public key of a token family. + */ +struct TALER_TokenFamilyPublicKeyHash +{ + /** + * Hash of the token public key. + */ + struct GNUNET_HashCode hash; +}; + +/** + * Token family private key. + */ +struct TALER_TokenFamilyPrivateKey +{ + struct GNUNET_CRYPTO_BlindSignPrivateKey private_key; +}; + +/** + * Token public key. + */ +struct TALER_TokenPublicKey +{ + struct GNUNET_CRYPTO_EddsaPublicKey public_key; +}; + +/** + * Signature made using a token private key. + */ +struct TALER_TokenSignature +{ + struct GNUNET_CRYPTO_EddsaSignature signature; +}; + +/** + * Blind signature for a token (signed by merchant). + */ +struct TALER_TokenBlindSignature +{ + struct GNUNET_CRYPTO_BlindedSignature signature; +}; + #endif diff --git a/src/include/taler_curl_lib.h b/src/include/taler_curl_lib.h index 5151f4cf6..f108e6158 100644 --- a/src/include/taler_curl_lib.h +++ b/src/include/taler_curl_lib.h @@ -47,6 +47,11 @@ struct TALER_CURL_PostContext * Custom headers. */ struct curl_slist *headers; + + /** + * Set to true to disable compression of the body. + */ + bool disable_compression; }; @@ -74,4 +79,17 @@ void TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx); +/** + * Set a secure redirection policy, allowing a limited + * number of redirects and only going from HTTP to HTTPS + * but not from HTTPS to HTTP. + * + * @param[in,out] eh easy handle to modify + * @param url URL to base the redirect policy on; + * must start with "http://" or "https://" + */ +void +TALER_curl_set_secure_redirect_policy (CURL *eh, + const char *url); + #endif diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index 09c50b17e..0597799b5 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1,23 +1,26 @@ /* - This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + This file is part of TALER + Copyright (C) 2014-2024 Taler Systems SA - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ /** * @file include/taler_exchange_service.h * @brief C interface of libtalerexchange, a C library to use exchange's HTTP API + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef _TALER_EXCHANGE_SERVICE_H #define _TALER_EXCHANGE_SERVICE_H @@ -25,31 +28,17 @@ #include <jansson.h> #include "taler_util.h" #include "taler_error_codes.h" +#include "taler_kyclogic_lib.h" #include <gnunet/gnunet_curl_lib.h> -/* ********************* /keys *********************** */ - /** - * List of possible options to be passed to - * #TALER_EXCHANGE_connect(). + * Version of the Taler Exchange API, in hex. + * Thus 0.8.4-1 = 0x00080401. */ -enum TALER_EXCHANGE_Option -{ - /** - * Terminator (end of option list). - */ - TALER_EXCHANGE_OPTION_END = 0, +#define TALER_EXCHANGE_API_VERSION 0x00100000 - /** - * Followed by a "const json_t *" that was previously returned for - * this exchange URL by #TALER_EXCHANGE_serialize_data(). Used to - * resume a connection to an exchange without having to re-download - * /keys data (or at least only download the deltas). - */ - TALER_EXCHANGE_OPTION_DATA - -}; +/* ********************* /keys *********************** */ /** @@ -70,17 +59,17 @@ struct TALER_EXCHANGE_SigningPublicKey /** * Validity start time */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Validity expiration time (how long the exchange may use it). */ - struct GNUNET_TIME_Absolute valid_until; + struct GNUNET_TIME_Timestamp valid_until; /** * Validity expiration time for legal disputes. */ - struct GNUNET_TIME_Absolute valid_legal; + struct GNUNET_TIME_Timestamp valid_legal; }; @@ -97,7 +86,7 @@ struct TALER_EXCHANGE_DenomPublicKey /** * The hash of the public key. */ - struct TALER_DenominationHash h_key; + struct TALER_DenominationHashP h_key; /** * Exchange's master signature over this denomination record. @@ -107,18 +96,18 @@ struct TALER_EXCHANGE_DenomPublicKey /** * Timestamp indicating when the denomination key becomes valid */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Timestamp indicating when the denomination key can’t be used anymore to * withdraw new coins. */ - struct GNUNET_TIME_Absolute withdraw_valid_until; + struct GNUNET_TIME_Timestamp withdraw_valid_until; /** * Timestamp indicating when coins of this denomination become invalid. */ - struct GNUNET_TIME_Absolute expire_deposit; + struct GNUNET_TIME_Timestamp expire_deposit; /** * When do signatures with this denomination key become invalid? @@ -127,7 +116,7 @@ struct TALER_EXCHANGE_DenomPublicKey * of the evidence. @e expire_legal is expected to be significantly * larger than @e expire_deposit (by a year or more). */ - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp expire_legal; /** * The value of this denomination @@ -135,30 +124,23 @@ struct TALER_EXCHANGE_DenomPublicKey struct TALER_Amount value; /** - * The applicable fee for withdrawing a coin of this denomination - */ - struct TALER_Amount fee_withdraw; - - /** - * The applicable fee to spend a coin of this denomination - */ - struct TALER_Amount fee_deposit; - - /** - * The applicable fee to melt/refresh a coin of this denomination + * The applicable fees for this denomination */ - struct TALER_Amount fee_refresh; + struct TALER_DenomFeeSet fees; /** - * The applicable fee to refund a coin of this denomination + * Set to true if the private denomination key has been + * lost by the exchange and thus the key cannot be + * used for withdrawing at this time. */ - struct TALER_Amount fee_refund; + bool lost; /** * Set to true if this denomination key has been * revoked by the exchange. */ bool revoked; + }; @@ -219,6 +201,227 @@ struct TALER_EXCHANGE_AuditorInformation /** + * Global fees and options of an exchange for a given time period. + */ +struct TALER_EXCHANGE_GlobalFee +{ + + /** + * Signature affirming all of the data. + */ + struct TALER_MasterSignatureP master_sig; + + /** + * Starting time of the validity period (inclusive). + */ + struct GNUNET_TIME_Timestamp start_date; + + /** + * End time of the validity period (exclusive). + */ + struct GNUNET_TIME_Timestamp end_date; + + /** + * Unmerged purses will be timed out after at most this time. + */ + struct GNUNET_TIME_Relative purse_timeout; + + /** + * Account history is limited to this timeframe. + */ + struct GNUNET_TIME_Relative history_expiration; + + /** + * Fees that apply globally, independent of denomination + * and wire method. + */ + struct TALER_GlobalFeeSet fees; + + /** + * Number of free purses per account. + */ + uint32_t purse_account_limit; +}; + + +/** + * List sorted by @a start_date with fees to be paid for aggregate wire transfers. + */ +struct TALER_EXCHANGE_WireAggregateFees +{ + /** + * This is a linked list. + */ + struct TALER_EXCHANGE_WireAggregateFees *next; + + /** + * Fee to be paid whenever the exchange wires funds to the merchant. + */ + struct TALER_WireFeeSet fees; + + /** + * Time when this fee goes into effect (inclusive) + */ + struct GNUNET_TIME_Timestamp start_date; + + /** + * Time when this fee stops being in effect (exclusive). + */ + struct GNUNET_TIME_Timestamp end_date; + + /** + * Signature affirming the above fee structure. + */ + struct TALER_MasterSignatureP master_sig; +}; + + +/** + * Information about wire fees by wire method. + */ +struct TALER_EXCHANGE_WireFeesByMethod +{ + /** + * Wire method with the given @e fees. + */ + char *method; + + /** + * Linked list of wire fees the exchange charges for + * accounts of the wire @e method. + */ + struct TALER_EXCHANGE_WireAggregateFees *fees_head; + +}; + + +/** + * Type of an account restriction. + */ +enum TALER_EXCHANGE_AccountRestrictionType +{ + /** + * Invalid restriction. + */ + TALER_EXCHANGE_AR_INVALID = 0, + + /** + * Account must not be used for this operation. + */ + TALER_EXCHANGE_AR_DENY = 1, + + /** + * Other account must match given regular expression. + */ + TALER_EXCHANGE_AR_REGEX = 2 +}; + +/** + * Restrictions that apply to using a given exchange bank account. + */ +struct TALER_EXCHANGE_AccountRestriction +{ + + /** + * Type of the account restriction. + */ + enum TALER_EXCHANGE_AccountRestrictionType type; + + /** + * Restriction details depending on @e type. + */ + union + { + /** + * Details if type is #TALER_EXCHANGE_AR_REGEX. + */ + struct + { + /** + * Regular expression that the payto://-URI of the partner account must + * follow. The regular expression should follow posix-egrep, but + * without support for character classes, GNU extensions, + * back-references or intervals. See + * https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html + * for a description of the posix-egrep syntax. Applications may support + * regexes with additional features, but exchanges must not use such + * regexes. + */ + char *posix_egrep; + + /** + * Hint for a human to understand the restriction. + */ + char *human_hint; + + /** + * Internationalizations for the @e human_hint. Map from IETF BCP 47 + * language tax to localized human hints. + */ + json_t *human_hint_i18n; + } regex; + } details; + +}; + + +/** + * Information about a wire account of the exchange. + */ +struct TALER_EXCHANGE_WireAccount +{ + /** + * payto://-URI of the exchange. + */ + char *payto_uri; + + /** + * URL of a conversion service in case using this account is subject to + * currency conversion. NULL for no conversion needed. + */ + char *conversion_url; + + /** + * Array of restrictions that apply when crediting + * this account. + */ + struct TALER_EXCHANGE_AccountRestriction *credit_restrictions; + + /** + * Array of restrictions that apply when debiting + * this account. + */ + struct TALER_EXCHANGE_AccountRestriction *debit_restrictions; + + /** + * Length of the @e credit_restrictions array. + */ + unsigned int credit_restrictions_length; + + /** + * Length of the @e debit_restrictions array. + */ + unsigned int debit_restrictions_length; + + /** + * Signature of the exchange over the account (was checked by the API). + */ + struct TALER_MasterSignatureP master_sig; + + /** + * Display label for the account, can be NULL. + */ + char *bank_label; + + /** + * Priority for ordering the account in the display. + */ + int64_t priority; + +}; + + +/** * @brief Information about keys from the exchange. */ struct TALER_EXCHANGE_Keys @@ -230,6 +433,11 @@ struct TALER_EXCHANGE_Keys struct TALER_MasterPublicKeyP master_pub; /** + * Signature over extension configuration data, if any. + */ + struct TALER_MasterSignatureP extensions_sig; + + /** * Array of the exchange's online signing keys. */ struct TALER_EXCHANGE_SigningPublicKey *sign_keys; @@ -245,6 +453,16 @@ struct TALER_EXCHANGE_Keys struct TALER_EXCHANGE_AuditorInformation *auditors; /** + * Array with the global fees of the exchange. + */ + struct TALER_EXCHANGE_GlobalFee *global_fees; + + /** + * Configuration data for extensions. + */ + json_t *extensions; + + /** * Supported Taler protocol version by the exchange. * String in the format current:revision:age using the * semantics of GNU libtool. See @@ -258,6 +476,41 @@ struct TALER_EXCHANGE_Keys char *currency; /** + * What is the base URL of the exchange that returned + * these keys? + */ + char *exchange_url; + + /** + * Asset type used by the exchange. Typical values + * are "fiat" or "crypto" or "regional" or "stock". + * Wallets should adjust their UI/UX based on this + * value. + */ + char *asset_type; + + /** + * Array of amounts a wallet is allowed to hold from + * this exchange before it must undergo further KYC checks. + */ + struct TALER_Amount *wallet_balance_limit_without_kyc; + + /** + * Array of accounts of the exchange. + */ + struct TALER_EXCHANGE_WireAccount *accounts; + + /** + * Array of wire fees by wire method. + */ + struct TALER_EXCHANGE_WireFeesByMethod *fees; + + /** + * Currency rendering specification for this exchange. + */ + struct TALER_CurrencySpecification cspec; + + /** * How long after a reserve went idle will the exchange close it? * This is an approximate number, not cryptographically signed by * the exchange (advisory-only, may change anytime). @@ -265,22 +518,62 @@ struct TALER_EXCHANGE_Keys struct GNUNET_TIME_Relative reserve_closing_delay; /** - * Maximum amount a wallet is allowed to hold from - * this exchange before it must undergo a KYC check. + * Timestamp indicating the /keys generation. */ - struct TALER_Amount wallet_balance_limit_without_kyc; + struct GNUNET_TIME_Timestamp list_issue_date; /** - * Timestamp indicating the /keys generation. + * When does this keys data expire? */ - struct GNUNET_TIME_Absolute list_issue_date; + struct GNUNET_TIME_Timestamp key_data_expiration; /** * Timestamp indicating the creation time of the last * denomination key in /keys. * Used to fetch /keys incrementally. */ - struct GNUNET_TIME_Absolute last_denom_issue_date; + struct GNUNET_TIME_Timestamp last_denom_issue_date; + + /** + * If age restriction is enabled on the exchange, we get an non-zero age_mask + */ + struct TALER_AgeMask age_mask; + + /** + * Absolute STEFAN parameter. + */ + struct TALER_Amount stefan_abs; + + /** + * Logarithmic STEFAN parameter. + */ + struct TALER_Amount stefan_log; + + /** + * Linear STEFAN parameter. + */ + double stefan_lin; + + /** + * Length of @e accounts array. + */ + unsigned int accounts_len; + + /** + * Length of @e fees array. + */ + unsigned int fees_len; + + /** + * Length of the @e wallet_balance_limit_without_kyc + * array. + */ + unsigned int wblwk_length; + + /** + * Length of the @e global_fees array. + */ + unsigned int num_global_fees; /** * Length of the @e sign_keys array (number of valid entries). @@ -307,6 +600,16 @@ struct TALER_EXCHANGE_Keys */ unsigned int denom_keys_size; + /** + * Reference counter for this structure. + * Freed when it reaches 0. + */ + unsigned int rc; + + /** + * Set to true if rewards are allowed at this exchange. + */ + bool rewards_allowed; }; @@ -403,151 +706,195 @@ struct TALER_EXCHANGE_HttpResponse /** + * Response from /keys. + */ +struct TALER_EXCHANGE_KeysResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status code. + */ + union + { + + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + /** + * Information about the various keys used by the exchange. + */ + const struct TALER_EXCHANGE_Keys *keys; + + /** + * Protocol compatibility information + */ + enum TALER_EXCHANGE_VersionCompatibility compat; + } ok; + } details; + +}; + + +/** * Function called with information about who is auditing * a particular exchange and what keys the exchange is using. + * The ownership over the @a keys object is passed to + * the callee, thus it is given explicitly and not + * (only) via @a kr. * * @param cls closure - * @param hr HTTP response data - * @param keys information about the various keys used - * by the exchange, NULL if /keys failed - * @param compat protocol compatibility information + * @param kr response from /keys + * @param[in] keys keys object passed to callback with + * reference counter of 1. Must be freed by callee + * using #TALER_EXCHANGE_keys_decref(). NULL on failure. */ typedef void -(*TALER_EXCHANGE_CertificationCallback) ( +(*TALER_EXCHANGE_GetKeysCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_Keys *keys, - enum TALER_EXCHANGE_VersionCompatibility compat); + const struct TALER_EXCHANGE_KeysResponse *kr, + struct TALER_EXCHANGE_Keys *keys); /** - * @brief Handle to the exchange. This is where we interact with - * a particular exchange and keep the per-exchange information. + * @brief Handle for a GET /keys request. */ -struct TALER_EXCHANGE_Handle; +struct TALER_EXCHANGE_GetKeysHandle; /** - * Initialise a connection to the exchange. Will connect to the - * exchange and obtain information about the exchange's master public - * key and the exchange's auditor. The respective information will - * be passed to the @a cert_cb once available, and all future - * interactions with the exchange will be checked to be signed - * (where appropriate) by the respective master key. + * Fetch the main /keys resources from an exchange. Does an incremental + * fetch if @a last_keys is given. The obtained information will be passed to + * the @a cert_cb (possibly after first merging it with @a last_keys to + * produce a full picture; expired keys (for deposit) will be removed from @a + * last_keys if there are any). * * @param ctx the context * @param url HTTP base URL for the exchange + * @param[in,out] last_keys previous keys object, NULL for none * @param cert_cb function to call with the exchange's certification information, * possibly called repeatedly if the information changes * @param cert_cb_cls closure for @a cert_cb - * @param ... list of additional arguments, terminated by #TALER_EXCHANGE_OPTION_END. * @return the exchange handle; NULL upon error */ -struct TALER_EXCHANGE_Handle * -TALER_EXCHANGE_connect (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_EXCHANGE_CertificationCallback cert_cb, - void *cert_cb_cls, - ...); +struct TALER_EXCHANGE_GetKeysHandle * +TALER_EXCHANGE_get_keys ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *last_keys, + TALER_EXCHANGE_GetKeysCallback cert_cb, + void *cert_cb_cls); /** - * Serialize the latest key data from @a exchange to be persisted - * on disk (to be used with #TALER_EXCHANGE_OPTION_DATA to more - * efficiently recover the state). + * Serialize the latest data from @a keys to be persisted + * (for example, to be used as @a last_keys later). * - * @param exchange which exchange's key and wire data should be serialized - * @return NULL on error (i.e. no current data available); otherwise - * json object owned by the caller + * @param kd the key data to serialize + * @return NULL on error; otherwise JSON object owned by the caller */ json_t * -TALER_EXCHANGE_serialize_data (struct TALER_EXCHANGE_Handle *exchange); +TALER_EXCHANGE_keys_to_json (const struct TALER_EXCHANGE_Keys *kd); /** - * Disconnect from the exchange. + * Deserialize keys data stored in @a j. * - * @param exchange the exchange handle + * @param j JSON keys data previously returned from #TALER_EXCHANGE_keys_to_json() + * @return NULL on error (i.e. invalid JSON); otherwise + * keys object with reference counter 1 owned by the caller */ -void -TALER_EXCHANGE_disconnect (struct TALER_EXCHANGE_Handle *exchange); +struct TALER_EXCHANGE_Keys * +TALER_EXCHANGE_keys_from_json (const json_t *j); /** - * Obtain the keys from the exchange. + * Cancel GET /keys operation. * - * @param exchange the exchange handle - * @return the exchange's key set + * @param[in] gkh the GET /keys handle */ -const struct TALER_EXCHANGE_Keys * -TALER_EXCHANGE_get_keys (struct TALER_EXCHANGE_Handle *exchange); +void +TALER_EXCHANGE_get_keys_cancel (struct TALER_EXCHANGE_GetKeysHandle *gkh); /** - * Let the user set the last valid denomination time manually. + * Increment reference counter for @a keys * - * @param exchange the exchange handle. - * @param last_denom_new new last denomination time. + * @param[in,out] keys object to increment reference counter for + * @return keys, with incremented reference counter */ -void -TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange, - struct GNUNET_TIME_Absolute last_denom_new); +struct TALER_EXCHANGE_Keys * +TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys); /** - * Flags for #TALER_EXCHANGE_check_keys_current(). + * Decrement reference counter for @a keys. + * Frees @a keys if reference counter becomes zero. + * + * @param[in,out] keys object to decrement reference counter for */ -enum TALER_EXCHANGE_CheckKeysFlags -{ - /** - * No special options. - */ - TALER_EXCHANGE_CKF_NONE, - - /** - * Force downloading /keys now, even if /keys is still valid - * (that is, the period advertised by the exchange for re-downloads - * has not yet expired). - */ - TALER_EXCHANGE_CKF_FORCE_DOWNLOAD = 1, - - /** - * Pull all keys again, resetting the client state to the original state. - * Using this flag disables the incremental download, and also prevents using - * the context until the re-download has completed. - */ - TALER_EXCHANGE_CKF_PULL_ALL_KEYS = 2, +void +TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys); - /** - * Force downloading all keys now. - */ - TALER_EXCHANGE_CKF_FORCE_ALL_NOW = TALER_EXCHANGE_CKF_FORCE_DOWNLOAD - | TALER_EXCHANGE_CKF_PULL_ALL_KEYS -}; +/** + * Use STEFAN curve in @a keys to convert @a brut to @a net. Computes the + * expected minimum (!) @a net amount that should for sure arrive in the + * target amount at cost of @a brut to the wallet. Note that STEFAN curves by + * design over-estimate actual fees and a wallet may be able to achieve the + * same @a net amount with less fees --- or if the available coins are + * abnormal in structure, it may take more. + * + * @param keys exchange key data + * @param brut gross amount (actual cost including fees) + * @param[out] net net amount (effective amount) + * @return #GNUNET_OK on success, #GNUNET_NO if the + * resulting @a net is zero (or lower) + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_keys_stefan_b2n ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *brut, + struct TALER_Amount *net); /** - * Check if our current response for /keys is valid, and if - * not, trigger /keys download. + * Use STEFAN curve in @a keys to convert @a net to @a brut. Computes the + * expected maximum (!) @a brut amount that should be needed in the wallet to + * transfer @a net amount to the target account. Note that STEFAN curves by + * design over-estimate actual fees and a wallet may be able to achieve the + * same @a net amount with less fees --- or if the available coins are + * abnormal in structure, it may take more. * - * @param exchange exchange to check keys for - * @param flags options controlling when to download what - * @return until when the existing response is current, 0 if we are re-downloading now + * @param keys exchange key data + * @param net net amount (effective amount) + * @param[out] brut gross amount (actual cost including fees) + * @return #GNUNET_OK on success, #GNUNET_NO if the + * resulting @a brut is zero (only if @a net was zero) */ -struct GNUNET_TIME_Absolute -TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange, - enum TALER_EXCHANGE_CheckKeysFlags flags); +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_keys_stefan_n2b ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *net, + struct TALER_Amount *brut); /** - * Obtain the keys from the exchange in the raw JSON format. + * Round brutto or netto value computed via STEFAN + * curve to decimal places commonly used at the exchange. * - * @param exchange the exchange handle - * @return the exchange's keys in raw JSON + * @param keys exchange keys response data + * @param[in,out] val value to round */ -json_t * -TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange); +void +TALER_EXCHANGE_keys_stefan_round ( + const struct TALER_EXCHANGE_Keys *keys, + struct TALER_Amount *val); /** @@ -559,18 +906,9 @@ TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange); * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key */ enum GNUNET_GenericReturnValue -TALER_EXCHANGE_test_signing_key (const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_ExchangePublicKeyP *pub); - - -/** - * Get exchange's base URL. - * - * @param exchange exchange handle. - * @return the base URL from the handle. - */ -const char * -TALER_EXCHANGE_get_base_url (const struct TALER_EXCHANGE_Handle *exchange); +TALER_EXCHANGE_test_signing_key ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ExchangePublicKeyP *pub); /** @@ -588,10 +926,24 @@ TALER_EXCHANGE_get_denomination_key ( /** + * Obtain the global fee details from the exchange. + * + * @param keys the exchange's key set + * @param ts time for when to fetch the fees + * @return details about the fees, NULL if no fees are known at @a ts + */ +const struct TALER_EXCHANGE_GlobalFee * +TALER_EXCHANGE_get_global_fee ( + const struct TALER_EXCHANGE_Keys *keys, + struct GNUNET_TIME_Timestamp ts); + + +/** * Create a copy of a denomination public key. * * @param key key to copy - * @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key + * @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key() + * @deprecated */ struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_copy_denomination_key ( @@ -600,9 +952,10 @@ TALER_EXCHANGE_copy_denomination_key ( /** * Destroy a denomination public key. - * Should only be called with keys created by #TALER_EXCHANGE_copy_denomination_key. + * Should only be called with keys created by #TALER_EXCHANGE_copy_denomination_key(). * * @param key key to destroy. + * @deprecated */ void TALER_EXCHANGE_destroy_denomination_key ( @@ -619,7 +972,7 @@ TALER_EXCHANGE_destroy_denomination_key ( const struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_get_denomination_key_by_hash ( const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_DenominationHash *hc); + const struct TALER_DenominationHashP *hc); /** @@ -636,176 +989,156 @@ TALER_EXCHANGE_get_signing_key_info ( const struct TALER_ExchangePublicKeyP *exchange_pub); -/* ********************* /wire *********************** */ +/* ********************* wire helpers *********************** */ /** - * Sorted list of fees to be paid for aggregate wire transfers. + * Parse array of @a accounts of the exchange into @a was. + * + * @param master_pub master public key of the exchange, NULL to not verify signatures + * @param accounts array of accounts to parse + * @param[out] was where to write the result (already allocated) + * @param was_length length of the @a was array, must match the length of @a accounts + * @return #GNUNET_OK if parsing @a accounts succeeded */ -struct TALER_EXCHANGE_WireAggregateFees +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_accounts ( + const struct TALER_MasterPublicKeyP *master_pub, + const json_t *accounts, + unsigned int was_length, + struct TALER_EXCHANGE_WireAccount was[static was_length]); + + +/** + * Free data within @a was, but not @a was itself. + * + * @param was array of wire account data + * @param was_len length of the @a was array + */ +void +TALER_EXCHANGE_free_accounts ( + unsigned int was_len, + struct TALER_EXCHANGE_WireAccount was[static was_len]); + + +/* ********************* /coins/$COIN_PUB/deposit *********************** */ + + +/** + * Information needed for a coin to be deposited. + */ +struct TALER_EXCHANGE_CoinDepositDetail { + /** - * This is a linked list. + * The amount to be deposited. */ - struct TALER_EXCHANGE_WireAggregateFees *next; + struct TALER_Amount amount; /** - * Fee to be paid whenever the exchange wires funds to the merchant. + * Hash over the age commitment of the coin. */ - struct TALER_Amount wire_fee; + struct TALER_AgeCommitmentHash h_age_commitment; /** - * Fee to be paid when the exchange closes a reserve and wires funds - * back to a customer. + * The coin’s public key. */ - struct TALER_Amount closing_fee; + struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Time when this fee goes into effect (inclusive) + * The signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made + * by the customer with the coin’s private key. */ - struct GNUNET_TIME_Absolute start_date; + struct TALER_CoinSpendSignatureP coin_sig; /** - * Time when this fee stops being in effect (exclusive). + * Exchange’s unblinded signature of the coin. */ - struct GNUNET_TIME_Absolute end_date; + struct TALER_DenominationSignature denom_sig; /** - * Signature affirming the above fee structure. + * Hash of the public key of the coin. */ - struct TALER_MasterSignatureP master_sig; + struct TALER_DenominationHashP h_denom_pub; }; /** - * Information about a wire account of the exchange. + * Meta information about the contract relevant for a coin's deposit + * operation. */ -struct TALER_EXCHANGE_WireAccount +struct TALER_EXCHANGE_DepositContractDetail { + /** - * payto://-URI of the exchange. + * Hash of the contact of the merchant with the customer (further details + * are never disclosed to the exchange) */ - const char *payto_uri; + struct TALER_PrivateContractHashP h_contract_terms; /** - * Signature of the exchange over the account (was checked by the API). + * The public key of the merchant (used to identify the merchant for refund + * requests). */ - struct TALER_MasterSignatureP master_sig; + struct TALER_MerchantPublicKeyP merchant_pub; /** - * Linked list of wire fees the exchange charges for - * accounts of the wire method matching @e payto_uri. + * Salt used to hash the @e merchant_payto_uri. */ - const struct TALER_EXCHANGE_WireAggregateFees *fees; - -}; - - -/** - * Callbacks of this type are used to serve the result of submitting a - * wire format inquiry request to a exchange. - * - * If the request fails to generate a valid response from the - * exchange, @a http_status will also be zero. - * - * @param cls closure - * @param hr HTTP response data - * @param accounts_len length of the @a accounts array - * @param accounts list of wire accounts of the exchange, NULL on error - */ -typedef void -(*TALER_EXCHANGE_WireCallback) ( - void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int accounts_len, - const struct TALER_EXCHANGE_WireAccount *accounts); - - -/** - * @brief A Wire format inquiry handle - */ -struct TALER_EXCHANGE_WireHandle; - + struct TALER_WireSaltP wire_salt; -/** - * Obtain information about a exchange's wire instructions. A - * exchange may provide wire instructions for creating a reserve. The - * wire instructions also indicate which wire formats merchants may - * use with the exchange. This API is typically used by a wallet for - * wiring funds, and possibly by a merchant to determine supported - * wire formats. - * - * Note that while we return the (main) response verbatim to the - * caller for further processing, we do already verify that the - * response is well-formed (i.e. that signatures included in the - * response are all valid). If the exchange's reply is not - * well-formed, we return an HTTP status code of zero to @a cb. - * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param wire_cb the callback to call when a reply for this request is available - * @param wire_cb_cls closure for the above callback - * @return a handle for this request - */ -struct TALER_EXCHANGE_WireHandle * -TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange, - TALER_EXCHANGE_WireCallback wire_cb, - void *wire_cb_cls); + /** + * Hash over data provided by the wallet to customize the contract. + * All zero if not used. + */ + struct GNUNET_HashCode wallet_data_hash; + /** + * Date until which the merchant can issue a refund to the customer via the + * exchange (can be zero if refunds are not allowed); must not be after the + * @e wire_deadline. + */ + struct GNUNET_TIME_Timestamp refund_deadline; -/** - * Cancel a wire information request. This function cannot be used - * on a request handle if a response is already served for it. - * - * @param wh the wire information request handle - */ -void -TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh); + /** + * Execution date, until which the merchant would like the exchange to + * settle the balance (advisory, the exchange cannot be forced to settle in + * the past or upon very short notice, but of course a well-behaved exchange + * will limit aggregation based on the advice received). + */ + struct GNUNET_TIME_Timestamp wire_deadline; + /** + * Timestamp when the contract was finalized, must match approximately the + * current time of the exchange. + */ + struct GNUNET_TIME_Timestamp wallet_timestamp; -/* ********************* /coins/$COIN_PUB/deposit *********************** */ + /** + * The merchant’s account details, in the payto://-format supported by the + * exchange. + */ + const char *merchant_payto_uri; + /** + * Policy extension specific details about the deposit relevant to the exchange. + */ + const json_t *policy_details; -/** - * Sign a deposit permission. Function for wallets. - * - * @param amount the amount to be deposited - * @param deposit_fee the deposit fee we expect to pay - * @param h_wire hash of the merchant’s account details - * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param h_extensions hash over the extensions - * @param h_denom_pub hash of the coin denomination's public key - * @param coin_priv coin’s private key - * @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param[out] coin_sig set to the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT - */ -void -TALER_EXCHANGE_deposit_permission_sign ( - const struct TALER_Amount *amount, - const struct TALER_Amount *deposit_fee, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_ExtensionContractHash *h_extensions, - const struct TALER_DenominationHash *h_denom_pub, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - struct GNUNET_TIME_Absolute wallet_timestamp, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, - struct TALER_CoinSpendSignatureP *coin_sig); +}; /** - * @brief A Deposit Handle + * @brief A Batch Deposit Handle */ -struct TALER_EXCHANGE_DepositHandle; +struct TALER_EXCHANGE_BatchDepositHandle; /** - * Structure with information about a deposit + * Structure with information about a batch deposit * operation's result. */ -struct TALER_EXCHANGE_DepositResult +struct TALER_EXCHANGE_BatchDepositResult { /** * HTTP response data @@ -822,12 +1155,12 @@ struct TALER_EXCHANGE_DepositResult struct { /** - * Time when the exchange generated the deposit confirmation + * Time when the exchange generated the batch deposit confirmation */ - struct GNUNET_TIME_Absolute deposit_timestamp; + struct GNUNET_TIME_Timestamp deposit_timestamp; /** - * signature provided by the exchange + * Deposit confirmation signature provided by the exchange */ const struct TALER_ExchangeSignatureP *exchange_sig; @@ -842,7 +1175,7 @@ struct TALER_EXCHANGE_DepositResult */ const char *transaction_base_url; - } success; + } ok; /** * Information returned if the HTTP status is @@ -850,7 +1183,11 @@ struct TALER_EXCHANGE_DepositResult */ struct { - /* TODO: returning full details is not implemented */ + /** + * The coin that had a conflict. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + } conflict; } details; @@ -865,64 +1202,46 @@ struct TALER_EXCHANGE_DepositResult * @param dr deposit response details */ typedef void -(*TALER_EXCHANGE_DepositResultCallback) ( +(*TALER_EXCHANGE_BatchDepositResultCallback) ( void *cls, - const struct TALER_EXCHANGE_DepositResult *dr); + const struct TALER_EXCHANGE_BatchDepositResult *dr); /** - * Submit a deposit permission to the exchange and get the exchange's - * response. This API is typically used by a merchant. Note that - * while we return the response verbatim to the caller for further - * processing, we do already verify that the response is well-formed - * (i.e. that signatures included in the response are all valid). If - * the exchange's reply is not well-formed, we return an HTTP status code - * of zero to @a cb. + * Submit a batch of deposit permissions to the exchange and get the + * exchange's response. This API is typically used by a merchant. Note that + * while we return the response verbatim to the caller for further processing, + * we do already verify that the response is well-formed (i.e. that signatures + * included in the response are all valid). If the exchange's reply is not + * well-formed, we return an HTTP status code of zero to @a cb. * - * We also verify that the @a coin_sig is valid for this deposit - * request, and that the @a ub_sig is a valid signature for @a + * We also verify that the @a cdds.coin_sig are valid for this deposit + * request, and that the @a cdds.ub_sig are a valid signatures for @a * coin_pub. Also, the @a exchange must be ready to operate (i.e. have * finished processing the /keys reply). If either check fails, we do * NOT initiate the transaction with the exchange and instead return NULL. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param amount the amount to be deposited - * @param wire_deadline execution date, until which the merchant would like the exchange to settle the balance (advisory, the exchange cannot be - * forced to settle in the past or upon very short notice, but of course a well-behaved exchange will limit aggregation based on the advice received) - * @param merchant_payto_uri the merchant’s account details, in the payto://-format supported by the exchange - * @param wire_salt salt used to hash the @a merchant_payto_uri - * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param extension_details extension-specific details about the deposit relevant to the exchange - * @param coin_pub coin’s public key - * @param denom_pub denomination key with which the coin is signed - * @param denom_sig exchange’s unblinded signature of the coin - * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the exchange - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key. + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param dcd details about the contract the deposit is for + * @param num_cdds length of the @a cdds array + * @param cdds array with details about the coins to be deposited * @param cb the callback to call when a reply for this request is available * @param cb_cls closure for the above callback * @param[out] ec if NULL is returned, set to the error code explaining why the operation failed * @return a handle for this request; NULL if the inputs are invalid (i.e. * signatures fail to verify). In this case, the callback is not called. */ -struct TALER_EXCHANGE_DepositHandle * -TALER_EXCHANGE_deposit ( - struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute wire_deadline, - const char *merchant_payto_uri, - const struct TALER_WireSalt *wire_salt, - const struct TALER_PrivateContractHash *h_contract_terms, - const json_t *extension_details, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_DenominationPublicKey *denom_pub, - struct GNUNET_TIME_Absolute timestamp, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_CoinSpendSignatureP *coin_sig, - TALER_EXCHANGE_DepositResultCallback cb, +struct TALER_EXCHANGE_BatchDepositHandle * +TALER_EXCHANGE_batch_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DepositContractDetail *dcd, + unsigned int num_cdds, + const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds], + TALER_EXCHANGE_BatchDepositResultCallback cb, void *cb_cls, enum TALER_ErrorCode *ec); @@ -931,20 +1250,22 @@ TALER_EXCHANGE_deposit ( * Change the chance that our deposit confirmation will be given to the * auditor to 100%. * - * @param deposit the deposit permission request handle + * @param[in,out] deposit the batch deposit permission request handle */ void -TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit); +TALER_EXCHANGE_batch_deposit_force_dc ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /** - * Cancel a deposit permission request. This function cannot be used + * Cancel a batch deposit permission request. This function cannot be used * on a request handle if a response is already served for it. * - * @param deposit the deposit permission request handle + * @param[in] deposit the deposit permission request handle */ void -TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit); +TALER_EXCHANGE_batch_deposit_cancel ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /* ********************* /coins/$COIN_PUB/refund *********************** */ @@ -954,23 +1275,51 @@ TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit); */ struct TALER_EXCHANGE_RefundHandle; +/** + * Response from the /refund API. + */ +struct TALER_EXCHANGE_RefundResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status code. + */ + union + { + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + /** + * Exchange key used to sign. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * The actual signature + */ + struct TALER_ExchangeSignatureP exchange_sig; + } ok; + } details; +}; + /** * Callbacks of this type are used to serve the result of submitting a * refund request to an exchange. * * @param cls closure - * @param hr HTTP response data - * @param sign_key exchange key used to sign @a obj, or NULL - * @param signature the actual signature, or NULL on error + * @param rr refund response */ typedef void (*TALER_EXCHANGE_RefundCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, - const struct TALER_ExchangeSignatureP *signature); - + const struct TALER_EXCHANGE_RefundResponse *rr); /** * Submit a refund request to the exchange and get the exchange's response. @@ -984,7 +1333,9 @@ typedef void * finished processing the /keys reply). If this check fails, we do * NOT initiate the transaction with the exchange and instead return NULL. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys * @param amount the amount to be refunded; must be larger than the refund fee * (as that fee is still being subtracted), and smaller than the amount * (with deposit fee) of the original deposit contribution of this coin @@ -1001,14 +1352,17 @@ typedef void * signatures fail to verify). In this case, the callback is not called. */ struct TALER_EXCHANGE_RefundHandle * -TALER_EXCHANGE_refund (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_MerchantPrivateKeyP *merchant_priv, - TALER_EXCHANGE_RefundCallback cb, - void *cb_cls); +TALER_EXCHANGE_refund ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *amount, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t rtransaction_id, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + TALER_EXCHANGE_RefundCallback cb, + void *cb_cls); /** @@ -1023,16 +1377,549 @@ void TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund); -/* ********************* GET /reserves/$RESERVE_PUB *********************** */ +/* ********************* POST /csr-melt *********************** */ /** - * @brief A /reserves/ GET Handle + * @brief A /csr-melt Handle */ -struct TALER_EXCHANGE_ReservesGetHandle; +struct TALER_EXCHANGE_CsRMeltHandle; + + +/** + * Details about a response for a CS R request. + */ +struct TALER_EXCHANGE_CsRMeltResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Length of the @e alg_values array. + */ + unsigned int alg_values_len; + + /** + * Values contributed by the exchange for the + * respective coin's withdraw operation. + */ + const struct TALER_ExchangeWithdrawValues *alg_values; + } ok; + + /** + * Details if the status is #MHD_HTTP_GONE. + */ + struct + { + /* FIXME: returning full details is not implemented */ + } gone; + + } details; +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * CS R request to a exchange. + * + * @param cls closure + * @param csrr response details + */ +typedef void +(*TALER_EXCHANGE_CsRMeltCallback) ( + void *cls, + const struct TALER_EXCHANGE_CsRMeltResponse *csrr); + + +/** + * Information we pass per coin to a /csr-melt request. + */ +struct TALER_EXCHANGE_NonceKey +{ + /** + * Which denomination key is the /csr-melt request for? + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + + /** + * What is number to derive the client nonce for the + * fresh coin? + */ + uint32_t cnc_num; +}; + + +/** + * Get a set of CS R values using a /csr-melt request. + * + * @param ctx curl context + * @param url exchange base URL + * @param rms master key used for the derivation of the CS values + * @param nks_len length of the @a nks array + * @param nks array of denominations and nonces + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return handle for the operation on success, NULL on error, i.e. + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_CsRMeltHandle * +TALER_EXCHANGE_csr_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_RefreshMasterSecretP *rms, + unsigned int nks_len, + struct TALER_EXCHANGE_NonceKey nks[static nks_len], + TALER_EXCHANGE_CsRMeltCallback res_cb, + void *res_cb_cls); + + +/** + * + * Cancel a CS R melt request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param csrh the withdraw handle + */ +void +TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh); + + +/* ********************* POST /csr-withdraw *********************** */ + + +/** + * @brief A /csr-withdraw Handle + */ +struct TALER_EXCHANGE_CsRWithdrawHandle; + + +/** + * Details about a response for a CS R request. + */ +struct TALER_EXCHANGE_CsRWithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Values contributed by the exchange for the + * respective coin's withdraw operation. + */ + struct TALER_ExchangeWithdrawValues alg_values; + + } ok; + + /** + * Details if the status is #MHD_HTTP_GONE. + */ + struct + { + /* TODO: returning full details is not implemented */ + } gone; + + } details; +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * CS R withdraw request to a exchange. + * + * @param cls closure + * @param csrr response details + */ +typedef void +(*TALER_EXCHANGE_CsRWithdrawCallback) ( + void *cls, + const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr); + + +/** + * Get a CS R using a /csr-withdraw request. + * + * @param curl_ctx The curl context to use for the requests + * @param exchange_url Base-URL to the excnange + * @param pk Which denomination key is the /csr request for + * @param nonce client nonce for the request + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return handle for the operation on success, NULL on error, i.e. + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_CsRWithdrawHandle * +TALER_EXCHANGE_csr_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + TALER_EXCHANGE_CsRWithdrawCallback res_cb, + void *res_cb_cls); + + +/** + * + * Cancel a CS R withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param csrh the withdraw handle + */ +void +TALER_EXCHANGE_csr_withdraw_cancel ( + struct TALER_EXCHANGE_CsRWithdrawHandle *csrh); + + +/* ********************* GET /coins/$COIN_PUB *********************** */ + +/** + * Ways how a coin's balance may change. + */ +enum TALER_EXCHANGE_CoinTransactionType +{ + + /** + * Reserved for uninitialized / none. + */ + TALER_EXCHANGE_CTT_NONE, + + /** + * Deposit into a contract. + */ + TALER_EXCHANGE_CTT_DEPOSIT, + + /** + * Spent on melt. + */ + TALER_EXCHANGE_CTT_MELT, + + /** + * Refunded by merchant. + */ + TALER_EXCHANGE_CTT_REFUND, + + /** + * Debited in recoup (to reserve) operation. + */ + TALER_EXCHANGE_CTT_RECOUP, + + /** + * Debited in recoup-and-refresh operation. + */ + TALER_EXCHANGE_CTT_RECOUP_REFRESH, + + /** + * Credited in recoup-refresh. + */ + TALER_EXCHANGE_CTT_OLD_COIN_RECOUP, + + /** + * Deposited into purse. + */ + TALER_EXCHANGE_CTT_PURSE_DEPOSIT, + + /** + * Refund from purse. + */ + TALER_EXCHANGE_CTT_PURSE_REFUND, + + /** + * Reserve open payment operation. + */ + TALER_EXCHANGE_CTT_RESERVE_OPEN_DEPOSIT + +}; + + +/** + * @brief Entry in the coin's transaction history. + */ +struct TALER_EXCHANGE_CoinHistoryEntry +{ + + /** + * Type of the transaction. + */ + enum TALER_EXCHANGE_CoinTransactionType type; + + /** + * Amount transferred (in or out). + */ + struct TALER_Amount amount; + + /** + * Details depending on @e type. + */ + union + { + + struct + { + struct TALER_MerchantWireHashP h_wire; + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_ExtensionPolicyHashP h_policy; + bool no_h_policy; + struct GNUNET_HashCode wallet_data_hash; + bool no_wallet_data_hash; + struct GNUNET_TIME_Timestamp wallet_timestamp; + struct TALER_MerchantPublicKeyP merchant_pub; + struct GNUNET_TIME_Timestamp refund_deadline; + struct TALER_CoinSpendSignatureP sig; + struct TALER_AgeCommitmentHash hac; + bool no_hac; + struct TALER_Amount deposit_fee; + } deposit; + + struct + { + struct TALER_CoinSpendSignatureP sig; + struct TALER_RefreshCommitmentP rc; + struct TALER_AgeCommitmentHash h_age_commitment; + bool no_hac; + struct TALER_Amount melt_fee; + } melt; + + struct + { + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_MerchantPublicKeyP merchant_pub; + struct TALER_MerchantSignatureP sig; + struct TALER_Amount refund_fee; + struct TALER_Amount sig_amount; + uint64_t rtransaction_id; + } refund; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp timestamp; + union GNUNET_CRYPTO_BlindingSecretP coin_bks; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } recoup; + + struct + { + struct TALER_CoinSpendPublicKeyP old_coin_pub; + union GNUNET_CRYPTO_BlindingSecretP coin_bks; + struct GNUNET_TIME_Timestamp timestamp; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } recoup_refresh; + + struct + { + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendPublicKeyP new_coin_pub; + struct GNUNET_TIME_Timestamp timestamp; + } old_coin_recoup; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_CoinSpendSignatureP coin_sig; + const char *exchange_base_url; + bool refunded; + struct TALER_AgeCommitmentHash phac; + } purse_deposit; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_Amount refund_fee; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + } purse_refund; + + struct + { + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } reserve_open_deposit; + + } details; + +}; + + +/** + * @brief A /coins/$RID/history Handle + */ +struct TALER_EXCHANGE_CoinsHistoryHandle; + + +/** + * Parses and verifies a coin's transaction history as + * returned by the exchange. Note that in case of + * incremental histories, the client must first combine + * the incremental histories into one complete history. + * + * @param keys /keys data of the exchange + * @param dk denomination key of the coin + * @param history JSON array with the coin's history + * @param coin_pub public key of the coin + * @param[out] total_in set to total amount credited to the coin in @a history + * @param[out] total_out set to total amount debited to the coin in @a history + * @param rlen length of the @a rhistory array + * @param[out] rhistory array where to write the parsed @a history + * @return #GNUNET_OK if @a history is valid, + * #GNUNET_SYSERR if not + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_coin_history ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *dk, + const json_t *history, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *total_in, + struct TALER_Amount *total_out, + unsigned int rlen, + struct TALER_EXCHANGE_CoinHistoryEntry rhistory[static rlen]); + + +/** + * Verify that @a coin_sig does NOT appear in the @a history of a coin's + * transactions and thus whatever transaction is authorized by @a coin_sig is + * a conflict with @a proof. + * + * @param history coin history to check + * @param coin_sig signature that must not be in @a history + * @return #GNUNET_OK if @a coin_sig is not in @a history + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_check_coin_signature_conflict ( + const json_t *history, + const struct TALER_CoinSpendSignatureP *coin_sig); /** + * Response to a GET /coins/$COIN_PUB/history request. + */ +struct TALER_EXCHANGE_CoinHistory +{ + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Coin transaction history (possibly partial). + * Not yet validated, combine with other already + * known history data for this coin and then use + * #TALER_EXCHANGE_parse_coin_history() to validate + * the complete history and obtain it in binary + * format. + */ + const json_t *history; + + /** + * The hash of the coin denomination's public key + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Coin balance. + */ + struct TALER_Amount balance; + + } ok; + + } details; + +}; + + +/** + * Signature of functions called with the result of + * a coin transaction history request. + * + * @param cls closure + * @param ch transaction history for the coin + */ +typedef void +(*TALER_EXCHANGE_CoinsHistoryCallback)( + void *cls, + const struct TALER_EXCHANGE_CoinHistory *ch); + + +/** + * Parses and verifies a coin's transaction history as + * returned by the exchange. Note that a client may + * have to combine multiple partial coin histories + * into one coherent history before calling this function. + * + * @param ctx context for managing request + * @param url base URL of the exchange + * @param coin_priv private key of the coin + * @param start_off offset from which on to request history + * @param cb function to call with results + * @param cb_cls closure for @a cb + * @return #GNUNET_OK if @a history is valid, + * #GNUNET_SYSERR if not + */ +struct TALER_EXCHANGE_CoinsHistoryHandle * +TALER_EXCHANGE_coins_history ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + uint64_t start_off, + TALER_EXCHANGE_CoinsHistoryCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_coins_history() operation. + * + * @param[in] rsh operation to cancel + */ +void +TALER_EXCHANGE_coins_history_cancel ( + struct TALER_EXCHANGE_CoinsHistoryHandle *rsh); + + +/* ********************* GET /reserves/$RESERVE_PUB *********************** */ + +/** * Ways how a reserve's balance may change. */ enum TALER_EXCHANGE_ReserveTransactionType @@ -1049,6 +1936,11 @@ enum TALER_EXCHANGE_ReserveTransactionType TALER_EXCHANGE_RTT_WITHDRAWAL, /** + * Age-Withdrawal from the reserve. + */ + TALER_EXCHANGE_RTT_AGEWITHDRAWAL, + + /** * /recoup operation. */ TALER_EXCHANGE_RTT_RECOUP, @@ -1056,6 +1948,21 @@ enum TALER_EXCHANGE_ReserveTransactionType /** * Reserve closed operation. */ + TALER_EXCHANGE_RTT_CLOSING, + + /** + * Reserve purse merge operation. + */ + TALER_EXCHANGE_RTT_MERGE, + + /** + * Reserve open request operation. + */ + TALER_EXCHANGE_RTT_OPEN, + + /** + * Reserve close request operation. + */ TALER_EXCHANGE_RTT_CLOSE }; @@ -1064,7 +1971,7 @@ enum TALER_EXCHANGE_ReserveTransactionType /** * @brief Entry in the reserve's transaction history. */ -struct TALER_EXCHANGE_ReserveHistory +struct TALER_EXCHANGE_ReserveHistoryEntry { /** @@ -1102,7 +2009,7 @@ struct TALER_EXCHANGE_ReserveHistory /** * When did the wire transfer happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; } in_details; @@ -1124,6 +2031,28 @@ struct TALER_EXCHANGE_ReserveHistory } withdraw; /** + * Information about withdraw operation. + * @e type is #TALER_EXCHANGE_RTT_AGEWITHDRAWAL. + */ + struct + { + /** + * Signature authorizing the withdrawal for outgoing transaction. + */ + json_t *out_authorization_sig; + + /** + * Maximum age committed + */ + uint8_t max_age; + + /** + * Fee that was charged for the withdrawal. + */ + struct TALER_Amount fee; + } age_withdraw; + + /** * Information provided if the reserve was filled via /recoup. * @e type is #TALER_EXCHANGE_RTT_RECOUP. */ @@ -1149,7 +2078,7 @@ struct TALER_EXCHANGE_ReserveHistory /** * When did the /recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; } recoup_details; @@ -1160,7 +2089,7 @@ struct TALER_EXCHANGE_ReserveHistory struct { /** - * Receiver account information for the outgoing wire transfer. + * Receiver account information for the outgoing wire transfer as a payto://-URI. */ const char *receiver_account_details; @@ -1183,7 +2112,7 @@ struct TALER_EXCHANGE_ReserveHistory /** * When did the wire transfer happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * Fee that was charged for the closing. @@ -1192,6 +2121,173 @@ struct TALER_EXCHANGE_ReserveHistory } close_details; + /** + * Information about a merge operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_MERGE. + */ + struct + { + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * When was the purse set to expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * Minimum age required for depositing into the purse. + */ + uint32_t min_age; + + /** + * Flags of the purse. + */ + enum TALER_WalletAccountMergeFlags flags; + + /** + * True if the purse was actually merged, false + * if only the @e purse_fee was charged. + */ + bool merged; + + } merge_details; + + /** + * Information about an open request operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_OPEN. + */ + struct + { + + /** + * Signature by the reserve approving the open. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Amount to be paid from the reserve balance to open + * the reserve. + */ + struct TALER_Amount reserve_payment; + + /** + * When was the request created. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * For how long should the reserve be kept open. + * (Determines amount to be paid.) + */ + struct GNUNET_TIME_Timestamp reserve_expiration; + + /** + * How many open purses should be included with the + * open reserve? + * (Determines amount to be paid.) + */ + uint32_t purse_limit; + + } open_request; + + /** + * Information about an close request operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_CLOSE. + */ + struct + { + + /** + * Signature by the reserve approving the close. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the request created. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + + } close_request; + + + } details; + +}; + + +/** + * @brief A /reserves/ GET Handle + */ +struct TALER_EXCHANGE_ReservesGetHandle; + + +/** + * @brief Reserve summary. + */ +struct TALER_EXCHANGE_ReserveSummary +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Reserve balance. + */ + struct TALER_Amount balance; + + } ok; + } details; }; @@ -1202,18 +2298,12 @@ struct TALER_EXCHANGE_ReserveHistory * reserve status request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param balance current balance in the reserve, NULL on error - * @param history_length number of entries in the transaction history, 0 on error - * @param history detailed transaction history, NULL on error + * @param rs HTTP response data */ typedef void (*TALER_EXCHANGE_ReservesGetCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_Amount *balance, - unsigned int history_length, - const struct TALER_EXCHANGE_ReserveHistory *history); + const struct TALER_EXCHANGE_ReserveSummary *rs); /** @@ -1225,7 +2315,8 @@ typedef void * reply is not well-formed, we return an HTTP status code of zero to * @a cb. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx curl context + * @param url exchange base URL * @param reserve_pub public key of the reserve to inspect * @param timeout how long to wait for an affirmative reply * (enables long polling if the reserve does not yet exist) @@ -1236,7 +2327,8 @@ typedef void */ struct TALER_EXCHANGE_ReservesGetHandle * TALER_EXCHANGE_reserves_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePublicKeyP *reserve_pub, struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_ReservesGetCallback cb, @@ -1254,19 +2346,187 @@ TALER_EXCHANGE_reserves_get_cancel ( struct TALER_EXCHANGE_ReservesGetHandle *rgh); -/* ********************* POST /reserves/$RESERVE_PUB/withdraw *********************** */ +/** + * @brief A /reserves/$RID/history Handle + */ +struct TALER_EXCHANGE_ReservesHistoryHandle; + + +/** + * @brief Reserve history details. + */ +struct TALER_EXCHANGE_ReserveHistory +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_history. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_history is #MHD_HTTP_OK + */ + struct + { + + /** + * Current reserve balance. May not be the difference between + * @e total_in and @e total_out because the @e may be truncated. + */ + struct TALER_Amount balance; + + /** + * Total of all inbound transactions in @e history. + */ + struct TALER_Amount total_in; + + /** + * Total of all outbound transactions in @e history. + */ + struct TALER_Amount total_out; + + /** + * Current etag / last entry in the history. + * Useful to filter requests by starting offset. + * Offsets are not necessarily contiguous. + */ + uint64_t etag; + + /** + * Reserve history. + */ + const struct TALER_EXCHANGE_ReserveHistoryEntry *history; + + /** + * Length of the @e history array. + */ + unsigned int history_len; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve history request to a exchange. + * + * @param cls closure + * @param rs HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesHistoryCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveHistory *rs); + + +/** + * Submit a request to obtain the reserve history. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve to inspect + * @param start_off offset of the oldest history entry to exclude from the response + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesHistoryHandle * +TALER_EXCHANGE_reserves_history ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + uint64_t start_off, + TALER_EXCHANGE_ReservesHistoryCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve history request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rsh the reserve request handle + */ +void +TALER_EXCHANGE_reserves_history_cancel ( + struct TALER_EXCHANGE_ReservesHistoryHandle *rsh); /** - * @brief A /reserves/$RESERVE_PUB/withdraw Handle + * Information input into the withdraw process per coin. */ -struct TALER_EXCHANGE_WithdrawHandle; +struct TALER_EXCHANGE_WithdrawCoinInput +{ + /** + * Denomination of the coin. + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + + /** + * Master key material for the coin. + */ + const struct TALER_PlanchetMasterSecretP *ps; + + /** + * Age commitment for the coin. + */ + const struct TALER_AgeCommitmentHash *ach; + +}; /** - * Details about a response for a withdraw request. + * All the details about a coin that are generated during withdrawal and that + * may be needed for future operations on the coin. */ -struct TALER_EXCHANGE_WithdrawResponse +struct TALER_EXCHANGE_PrivateCoinDetails +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Value used to blind the key for the signature. + * Needed for recoup operations. + */ + union GNUNET_CRYPTO_BlindingSecretP bks; + + /** + * Signature over the coin. + */ + struct TALER_DenominationSignature sig; + + /** + * Values contributed from the exchange during the + * withdraw protocol. + */ + struct TALER_ExchangeWithdrawValues exchange_vals; +}; + + +/** + * @brief A /reserves/$RESERVE_PUB/batch-withdraw Handle + */ +struct TALER_EXCHANGE_BatchWithdrawHandle; + + +/** + * Details about a response for a batch withdraw request. + */ +struct TALER_EXCHANGE_BatchWithdrawResponse { /** * HTTP response data. @@ -1283,23 +2543,35 @@ struct TALER_EXCHANGE_WithdrawResponse */ struct { + + /** + * Array of coins returned by the batch withdraw operation. + */ + struct TALER_EXCHANGE_PrivateCoinDetails *coins; + /** - * Signature over the coin. + * Length of the @e coins array. */ - struct TALER_DenominationSignature sig; - } success; + unsigned int num_coins; + } ok; /** - * Details if the status is #MHD_HTTP_ACCEPTED. + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. */ struct { + /** - * Payment target that the merchant should use - * to check for its KYC status. + * Hash of the payto-URI of the account to KYC; */ - uint64_t payment_target_uuid; - } accepted; + struct TALER_PaytoHashP h_payto; + + /** + * Legitimization requirement that the merchant should use + * to check for its KYC status, 0 if not known. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; /** * Details if the status is #MHD_HTTP_CONFLICT. @@ -1323,71 +2595,103 @@ struct TALER_EXCHANGE_WithdrawResponse /** * Callbacks of this type are used to serve the result of submitting a - * withdraw request to a exchange. + * batch withdraw request to a exchange. * * @param cls closure * @param wr response details */ typedef void -(*TALER_EXCHANGE_WithdrawCallback) ( +(*TALER_EXCHANGE_BatchWithdrawCallback) ( void *cls, - const struct TALER_EXCHANGE_WithdrawResponse *wr); + const struct TALER_EXCHANGE_BatchWithdrawResponse *wr); /** - * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/withdraw - * request. This API is typically used by a wallet to withdraw from a - * reserve. + * Withdraw multiple coins from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a wallet to withdraw many coins from a + * reserve. The blind signatures are unblinded and verified before being returned + * to the caller at @a res_cb. * * Note that to ensure that no money is lost in case of hardware * failures, the caller must have committed (most of) the arguments to * disk before calling, and be ready to repeat the request with the * same arguments in case of failures. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param pk kind of coin to create + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange * @param reserve_priv private key of the reserve to withdraw from - * @param ps secrets of the planchet - * caller must have committed this value to disk before the call (with @a pk) + * @param wci_length number of entries in @a wcis + * @param wcis inputs that determine the planchets * @param res_cb the callback to call when the final result for this request is available * @param res_cb_cls closure for @a res_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). * In this case, the callback is not called. */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw ( - struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, +struct TALER_EXCHANGE_BatchWithdrawHandle * +TALER_EXCHANGE_batch_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_PlanchetSecretsP *ps, - TALER_EXCHANGE_WithdrawCallback res_cb, + unsigned int wci_length, + const struct TALER_EXCHANGE_WithdrawCoinInput wcis[static wci_length], + TALER_EXCHANGE_BatchWithdrawCallback res_cb, void *res_cb_cls); /** - * Cancel a withdraw status request. This function cannot be used - * on a request handle if a response is already served for it. + * Cancel a batch withdraw status request. This function cannot be used on a + * request handle if a response is already served for it. * - * @param wh the withdraw handle + * @param wh the batch withdraw handle */ void -TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh); +TALER_EXCHANGE_batch_withdraw_cancel ( + struct TALER_EXCHANGE_BatchWithdrawHandle *wh); /** + * Response from a withdraw2 request. + */ +struct TALER_EXCHANGE_Withdraw2Response +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * blind signature over the coin + */ + struct TALER_BlindedDenominationSignature blind_sig; + } ok; + } details; + +}; + +/** * Callbacks of this type are used to serve the result of submitting a * withdraw request to a exchange without the (un)blinding factor. * * @param cls closure - * @param hr HTTP response data - * @param blind_sig blind signature over the coin, NULL on error + * @param w2r response data */ typedef void (*TALER_EXCHANGE_Withdraw2Callback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_BlindedDenominationSignature *blind_sig); + const struct TALER_EXCHANGE_Withdraw2Response *w2r); /** @@ -1403,14 +2707,20 @@ struct TALER_EXCHANGE_Withdraw2Handle; /** * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/withdraw * request. This API is typically used by a merchant to withdraw a tip - * where the blinding factor is unknown to the merchant. + * where the blinding factor is unknown to the merchant. Note that unlike + * the #TALER_EXCHANGE_batch_withdraw() API, this API neither unblinds the signatures + * nor can it verify that the exchange signatures are valid, so these tasks + * are left to the caller. Wallets probably should use #TALER_EXCHANGE_batch_withdraw() + * which integrates these steps. * * Note that to ensure that no money is lost in case of hardware * failures, the caller must have committed (most of) the arguments to * disk before calling, and be ready to repeat the request with the * same arguments in case of failures. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param curl_ctx The curl-context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange * @param pd planchet details of the planchet to withdraw * @param reserve_priv private key of the reserve to withdraw from * @param res_cb the callback to call when the final result for this request is available @@ -1420,11 +2730,14 @@ struct TALER_EXCHANGE_Withdraw2Handle; * In this case, the callback is not called. */ struct TALER_EXCHANGE_Withdraw2Handle * -TALER_EXCHANGE_withdraw2 (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_PlanchetDetail *pd, - const struct TALER_ReservePrivateKeyP *reserve_priv, - TALER_EXCHANGE_Withdraw2Callback res_cb, - void *res_cb_cls); +TALER_EXCHANGE_withdraw2 ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_PlanchetDetail *pd, + const struct TALER_ReservePrivateKeyP *reserve_priv, + TALER_EXCHANGE_Withdraw2Callback res_cb, + void *res_cb_cls); /** @@ -1437,54 +2750,592 @@ void TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh); -/* ********************* /refresh/melt+reveal ***************************** */ +/** + * Response from a batch-withdraw request (2nd variant). + */ +struct TALER_EXCHANGE_BatchWithdraw2Response +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * array of blind signatures over the coins. + */ + const struct TALER_BlindedDenominationSignature *blind_sigs; + + /** + * length of @e blind_sigs + */ + unsigned int blind_sigs_length; + + } ok; + + struct + { + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + /** + * ID identifying the KYC requirement to withdraw. + */ + uint64_t kyc_requirement_id; + + } unavailable_for_legal_reasons; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a batch + * withdraw request to a exchange without the (un)blinding factor. + * + * @param cls closure + * @param bw2r response data + */ +typedef void +(*TALER_EXCHANGE_BatchWithdraw2Callback) ( + void *cls, + const struct TALER_EXCHANGE_BatchWithdraw2Response *bw2r); + + +/** + * @brief A /reserves/$RESERVE_PUB/batch-withdraw Handle, 2nd variant. + * This variant does not do the blinding/unblinding and only + * fetches the blind signatures on the already blinded planchets. + * Used internally by the `struct TALER_EXCHANGE_BatchWithdrawHandle` + * implementation as well as for the tipping logic of merchants. + */ +struct TALER_EXCHANGE_BatchWithdraw2Handle; + + +/** + * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a merchant to withdraw a tip + * where the blinding factor is unknown to the merchant. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param pds array of planchet details of the planchet to withdraw + * @param pds_length number of entries in the @a pds array + * @param reserve_priv private key of the reserve to withdraw from + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_BatchWithdraw2Handle * +TALER_EXCHANGE_batch_withdraw2 ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int pds_length, + const struct TALER_PlanchetDetail pds[static pds_length], + TALER_EXCHANGE_BatchWithdraw2Callback res_cb, + void *res_cb_cls); + + +/** + * Cancel a batch withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param wh the withdraw handle + */ +void +TALER_EXCHANGE_batch_withdraw2_cancel ( + struct TALER_EXCHANGE_BatchWithdraw2Handle *wh); + + +/* ********************* /reserve/$RESERVE_PUB/age-withdraw *************** */ + +/** + * @brief Information needed to withdraw (and reveal) age restricted coins. + */ +struct TALER_EXCHANGE_AgeWithdrawCoinInput +{ + /** + * The master secret from which we derive all other relevant values for + * the coin: private key, nonces (if applicable) and age restriction + */ + struct TALER_PlanchetMasterSecretP secrets[TALER_CNC_KAPPA]; + + /** + * The denomination of the coin. Must support age restriction, i.e + * its .keys.age_mask MUST not be 0 + */ + struct TALER_EXCHANGE_DenomPublicKey *denom_pub; +}; + + +/** + * All the details about a coin that are generated during age-withdrawal and + * that may be needed for future operations on the coin. + */ +struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Hash of the public key of the coin. + */ + struct TALER_CoinPubHashP h_coin_pub; + + /** + * Value used to blind the key for the signature. + * Needed for recoup operations. + */ + union GNUNET_CRYPTO_BlindingSecretP blinding_key; + + /** + * The age commitment, proof for the coin, derived from the + * Master secret and maximum age in the originating request + */ + struct TALER_AgeCommitmentProof age_commitment_proof; + + /** + * The hash of the age commitment + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Values contributed from the exchange during the + * withdraw protocol. + */ + struct TALER_ExchangeWithdrawValues alg_values; + + /** + * The planchet constructed + */ + struct TALER_PlanchetDetail planchet; +}; +/** + * @brief A handle to a /reserves/$RESERVE_PUB/age-withdraw request + */ +struct TALER_EXCHANGE_AgeWithdrawHandle; /** - * Melt (partially spent) coins to obtain fresh coins that are - * unlinkable to the original coin(s). Note that melting more - * than one coin in a single request will make those coins linkable, - * so the safest operation only melts one coin at a time. + * @brief Details about the response for a age withdraw request. + */ +struct TALER_EXCHANGE_AgeWithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Index that should not be revealed during the age-withdraw reveal + * phase. + */ + uint8_t noreveal_index; + + /** + * The commitment of the age-withdraw request, needed for the + * subsequent call to /age-withdraw/$ACH/reveal + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * The number of elements in @e coins, each referring to + * TALER_CNC_KAPPA elements + */ + size_t num_coins; + + /** + * The computed details of the non-revealed @e num_coins coins to keep. + */ + const struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails *coin_details; + + /** + * The array of blinded hashes of the non-revealed + * @e num_coins coins, needed for the reveal step; + */ + const struct TALER_BlindedCoinHashP *blinded_coin_hs; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + } ok; + } details; +}; + + +typedef void +(*TALER_EXCHANGE_AgeWithdrawCallback)( + void *cls, + const struct TALER_EXCHANGE_AgeWithdrawResponse *awr); + +/** + * Submit an age-withdraw request to the exchange and get the exchange's + * response. * * This API is typically used by a wallet. Note that to ensure that - * no money is lost in case of hardware failures, is operation does - * not actually initiate the request. Instead, it generates a buffer - * which the caller must store before proceeding with the actual call - * to #TALER_EXCHANGE_melt() that will generate the request. - * - * This function does verify that the given request data is internally - * consistent. However, the @a melts_sigs are NOT verified. - * - * Aside from some non-trivial cryptographic operations that might - * take a bit of CPU time to complete, this function returns - * its result immediately and does not start any asynchronous - * processing. This function is also thread-safe. - * - * @param melt_priv private keys of the coin to melt - * @param melt_amount amount specifying how much - * the coin will contribute to the melt (including fee) - * @param melt_sig signatures affirming the - * validity of the public keys corresponding to the - * @a melt_priv private key - * @param melt_pk denomination key information - * record corresponding to the @a melt_sig - * validity of the keys - * @param fresh_pks_len length of the @a pks array - * @param fresh_pks array of @a pks_len denominations of fresh coins to create + * no money is lost in case of hardware failures, the provided + * argument @a rd should be committed to persistent storage + * prior to calling this function. + * + * @param curl_ctx The curl context + * @param exchange_url The base url of the exchange + * @param keys The denomination keys from the exchange + * @param reserve_priv The private key to the reserve + * @param num_coins The number of elements in @e coin_inputs + * @param coin_inputs The input for the coins to withdraw + * @param max_age The maximum age we commit to. + * @param res_cb A callback for the result, maybe NULL + * @param res_cb_cls A closure for @e res_cb, maybe NULL + * @return a handle for this request; NULL if the argument was invalid. + * In this case, the callback will not be called. + */ +struct TALER_EXCHANGE_AgeWithdrawHandle * +TALER_EXCHANGE_age_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + struct TALER_EXCHANGE_Keys *keys, + const char *exchange_url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + size_t num_coins, + const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[static + num_coins], + uint8_t max_age, + TALER_EXCHANGE_AgeWithdrawCallback res_cb, + void *res_cb_cls); + +/** + * Cancel a age-withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param awh the age-withdraw handle + */ +void +TALER_EXCHANGE_age_withdraw_cancel ( + struct TALER_EXCHANGE_AgeWithdrawHandle *awh); + + +/**++++++ age-withdraw with pre-blinded planchets ***************************/ + +/** + * @brief Information needed to withdraw (and reveal) age restricted coins. + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedInput +{ + /** + * The denomination of the coin. Must support age restriction, i.e + * its .keys.age_mask MUST not be 0 + */ + const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; + + /** + * Blinded Planchets + */ + struct TALER_PlanchetDetail planchet_details[TALER_CNC_KAPPA]; +}; + +/** + * Response from an age-withdraw request with pre-blinded planchets + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * Index that should not be revealed during the age-withdraw reveal phase. + * The struct TALER_PlanchetMasterSecretP * from the request + * with this index are the ones to keep. + */ + uint8_t noreveal_index; + + /** + * The commitment of the call to age-withdraw, needed for the subsequent + * call to /age-withdraw/$ACH/reveal. + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + } ok; + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting an + * age-withdraw request to a exchange with pre-blinded planchets + * without the (un)blinding factor. + * + * @param cls closure + * @param awbr response data + */ +typedef void +(*TALER_EXCHANGE_AgeWithdrawBlindedCallback) ( + void *cls, + const struct TALER_EXCHANGE_AgeWithdrawBlindedResponse *awbr); + + +/** + * @brief A /reserves/$RESERVE_PUB/age-withdraw Handle, 2nd variant with + * pre-blinded planchets. + * + * This variant does not do the blinding/unblinding and only + * fetches the blind signatures on the already blinded planchets. + * Used internally by the `struct TALER_EXCHANGE_BatchWithdrawHandle` + * implementation as well as for the reward logic of merchants. + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedHandle; + +/** + * Withdraw age-restricted coins from the exchange using a + * /reserves/$RESERVE_PUB/age-withdraw request. This API is typically used + * by a merchant to withdraw a reward where the planchets are pre-blinded and + * the blinding factor is unknown to the merchant. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param max_age The maximum age that the coins are committed to. + * @param num_input number of entries in the @a blinded_input array + * @param blinded_input array of planchet details of the planchet to withdraw + * @param reserve_priv private key of the reserve to withdraw from + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). - * Otherwise, JSON data structure to store persistently - * before proceeding to #TALER_EXCHANGE_melt(). - * Non-null results should be freed using GNUNET_free(). + * In this case, the callback is not called. */ -json_t * -TALER_EXCHANGE_refresh_prepare ( - const struct TALER_CoinSpendPrivateKeyP *melt_priv, - const struct TALER_Amount *melt_amount, - const struct TALER_DenominationSignature *melt_sig, - const struct TALER_EXCHANGE_DenomPublicKey *melt_pk, - unsigned int fresh_pks_len, - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks); +struct TALER_EXCHANGE_AgeWithdrawBlindedHandle * +TALER_EXCHANGE_age_withdraw_blinded ( + struct GNUNET_CURL_Context *curl_ctx, + struct TALER_EXCHANGE_Keys *keys, + const char *exchange_url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + uint8_t max_age, + unsigned int num_input, + const struct TALER_EXCHANGE_AgeWithdrawBlindedInput blinded_input[static + num_input], + TALER_EXCHANGE_AgeWithdrawBlindedCallback res_cb, + void *res_cb_cls); + + +/** + * Cancel an age-withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param awbh the age-withdraw handle + */ +void +TALER_EXCHANGE_age_withdraw_blinded_cancel ( + struct TALER_EXCHANGE_AgeWithdrawBlindedHandle *awbh); + + +/* ********************* /age-withdraw/$ACH/reveal ************************ */ + +/** + * @brief A handle to a /age-withdraw/$ACH/reveal request + */ +struct TALER_EXCHANGE_AgeWithdrawRevealHandle; + +/** + * The response from a /age-withdraw/$ACH/reveal request + */ +struct TALER_EXCHANGE_AgeWithdrawRevealResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Number of signatures returned. + */ + unsigned int num_sigs; + + /** + * Array of @e num_coins blinded denomination signatures, giving each + * coin its value and validity. The array give these coins in the same + * order (and should have the same length) in which the original + * age-withdraw request specified the respective denomination keys. + */ + const struct TALER_BlindedDenominationSignature *blinded_denom_sigs; + + } ok; + } details; + +}; + +typedef void +(*TALER_EXCHANGE_AgeWithdrawRevealCallback)( + void *cls, + const struct TALER_EXCHANGE_AgeWithdrawRevealResponse *awr); + +/** + * Submit an age-withdraw-reveal request to the exchange and get the exchange's + * response. + * + * This API is typically used by a wallet. Note that to ensure that + * no money is lost in case of hardware failures, the provided + * argument @a rd should be committed to persistent storage + * prior to calling this function. + * + * @param curl_ctx The curl context + * @param exchange_url The base url of the exchange + * @param num_coins The number of elements in @e coin_inputs and @e alg_values + * @param coin_inputs The input for the coins to withdraw, same as in the previous call to /age-withdraw + * @param noreveal_index The index into each of the kappa coin candidates, that should not be revealed to the exchange + * @param h_commitment The commmitment from the previous call to /age-withdraw + * @param reserve_pub The public key of the reserve the original call to /age-withdraw was made to + * @param res_cb A callback for the result, maybe NULL + * @param res_cb_cls A closure for @e res_cb, maybe NULL + * @return a handle for this request; NULL if the argument was invalid. + * In this case, the callback will not be called. + */ +struct TALER_EXCHANGE_AgeWithdrawRevealHandle * +TALER_EXCHANGE_age_withdraw_reveal ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + size_t num_coins, + const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[static + num_coins], + uint8_t noreveal_index, + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_ReservePublicKeyP *reserve_pub, + TALER_EXCHANGE_AgeWithdrawRevealCallback res_cb, + void *res_cb_cls); + + +/** + * @brief Cancel an age-withdraw-reveal request + * + * @param awrh Handle to an age-withdraw-reqveal request + */ +void +TALER_EXCHANGE_age_withdraw_reveal_cancel ( + struct TALER_EXCHANGE_AgeWithdrawRevealHandle *awrh); + + +/* ********************* /refresh/melt+reveal ***************************** */ + + +/** + * Information needed to melt (partially spent) coins to obtain fresh coins + * that are unlinkable to the original coin(s). Note that melting more than + * one coin in a single request will make those coins linkable, so we only melt + * one coin at a time. + */ +struct TALER_EXCHANGE_RefreshData +{ + /** + * private key of the coin to melt + */ + struct TALER_CoinSpendPrivateKeyP melt_priv; + + /** + * age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentProof *melt_age_commitment_proof; + + /** + * Hash of age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentHash *melt_h_age_commitment; + + /** + * amount specifying how much the coin will contribute to the melt + * (including fee) + */ + struct TALER_Amount melt_amount; + + /** + * signatures affirming the validity of the public keys corresponding to the + * @e melt_priv private key + */ + struct TALER_DenominationSignature melt_sig; + + /** + * denomination key information record corresponding to the @e melt_sig + * validity of the keys + */ + struct TALER_EXCHANGE_DenomPublicKey melt_pk; + + /** + * array of @e pks_len denominations of fresh coins to create + */ + const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; + + /** + * length of the @e pks array + */ + unsigned int fresh_pks_len; +}; /* ********************* /coins/$COIN_PUB/melt ***************************** */ @@ -1496,23 +3347,79 @@ struct TALER_EXCHANGE_MeltHandle; /** + * Information we obtain per coin during melting. + */ +struct TALER_EXCHANGE_MeltBlindingDetail +{ + /** + * Exchange values contributed to the refresh operation + */ + struct TALER_ExchangeWithdrawValues alg_value; + +}; + + +/** + * Response returned to a /melt request. + */ +struct TALER_EXCHANGE_MeltResponse +{ + /** + * Full HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + + /** + * Information returned per coin. + */ + const struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP sign_key; + + /** + * Length of the @a mbds array with the exchange values + * and blinding keys we are using. + */ + unsigned int num_mbds; + + /** + * Gamma value chosen by the exchange. + */ + uint32_t noreveal_index; + } ok; + + } details; +}; + + +/** * Callbacks of this type are used to notify the application about the result * of the /coins/$COIN_PUB/melt stage. If successful, the @a noreveal_index * should be committed to disk prior to proceeding * #TALER_EXCHANGE_refreshes_reveal(). * * @param cls closure - * @param hr HTTP response data - * @param noreveal_index choice by the exchange in the cut-and-choose protocol, - * UINT32_MAX on error - * @param sign_key exchange key used to sign @a full_response, or NULL + * @param mr response details */ typedef void (*TALER_EXCHANGE_MeltCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - uint32_t noreveal_index, - const struct TALER_ExchangePublicKeyP *sign_key); + const struct TALER_EXCHANGE_MeltResponse *mr); /** @@ -1521,23 +3428,28 @@ typedef void * * This API is typically used by a wallet. Note that to ensure that * no money is lost in case of hardware failures, the provided - * argument should have been constructed using - * #TALER_EXCHANGE_refresh_prepare and committed to persistent storage + * argument @a rd should be committed to persistent storage * prior to calling this function. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param refresh_data the refresh data as returned from - #TALER_EXCHANGE_refresh_prepare()) + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param rms the fresh secret that defines the refresh operation + * @param rd the refresh data specifying the characteristics of the operation * @param melt_cb the callback to call with the result * @param melt_cb_cls closure for @a melt_cb * @return a handle for this request; NULL if the argument was invalid. * In this case, neither callback will be called. */ struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, - const json_t *refresh_data, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls); +TALER_EXCHANGE_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_EXCHANGE_RefreshData *rd, + TALER_EXCHANGE_MeltCallback melt_cb, + void *melt_cb_cls); /** @@ -1554,26 +3466,92 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh); /** + * Information about a coin obtained via /refreshes/$RCH/reveal. + */ +struct TALER_EXCHANGE_RevealedCoinInfo +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Master secret of this coin. + */ + struct TALER_PlanchetMasterSecretP ps; + + /** + * Age commitment and its hash of the coin, might be NULL. + */ + struct TALER_AgeCommitmentProof *age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Blinding keys used to blind the fresh coin. + */ + union GNUNET_CRYPTO_BlindingSecretP bks; + + /** + * Signature affirming the validity of the coin. + */ + struct TALER_DenominationSignature sig; + +}; + + +/** + * Result of a /refreshes/$RCH/reveal request. + */ +struct TALER_EXCHANGE_RevealResult +{ + /** + * HTTP status. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + /** + * Array of @e num_coins values about the coins obtained via the refresh + * operation. The array give the coins in the same order (and should + * have the same length) in which the original melt request specified the + * respective denomination keys. + */ + const struct TALER_EXCHANGE_RevealedCoinInfo *coins; + + /** + * Number of coins returned. + */ + unsigned int num_coins; + } ok; + + } details; + +}; + + +/** * Callbacks of this type are used to return the final result of * submitting a refresh request to a exchange. If the operation was * successful, this function returns the signatures over the coins - * that were remelted. The @a coin_privs and @a sigs arrays give the - * coins in the same order (and should have the same length) in which - * the original request specified the respective denomination keys. + * that were remelted. * * @param cls closure - * @param hr HTTP response data - * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed - * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error - * @param sigs array of signature over @a num_coins coins, NULL on error + * @param rr result of the reveal operation */ typedef void (*TALER_EXCHANGE_RefreshesRevealCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_PlanchetSecretsP *coin_privs, - const struct TALER_DenominationSignature *sigs); + const struct TALER_EXCHANGE_RevealResult *rr); /** @@ -1591,9 +3569,12 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; * arguments should have been committed to persistent storage * prior to calling this function. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param refresh_data the refresh data as returned from - #TALER_EXCHANGE_refresh_prepare()) + * @param ctx curl context + * @param url exchange base URL + * @param rms the fresh secret that defines the refresh operation + * @param rd the refresh data that characterizes the refresh operation + * @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd + * @param alg_values array @a num_coins of exchange values contributed to the refresh operation * @param noreveal_index response from the exchange to the * #TALER_EXCHANGE_melt() invocation * @param reveal_cb the callback to call with the final result of the @@ -1604,8 +3585,12 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; */ struct TALER_EXCHANGE_RefreshesRevealHandle * TALER_EXCHANGE_refreshes_reveal ( - struct TALER_EXCHANGE_Handle *exchange, - const json_t *refresh_data, + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_EXCHANGE_RefreshData *rd, + unsigned int num_coins, + const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], uint32_t noreveal_index, TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, void *reveal_cb_cls); @@ -1632,26 +3617,90 @@ struct TALER_EXCHANGE_LinkHandle; /** + * Information about a coin obtained via /link. + */ +struct TALER_EXCHANGE_LinkedCoinInfo +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Age commitment and its hash, if applicable. + */ + bool has_age_commitment; + struct TALER_AgeCommitmentProof age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Master secret of this coin. + */ + struct TALER_PlanchetMasterSecretP ps; + + /** + * Signature affirming the validity of the coin. + */ + struct TALER_DenominationSignature sig; + + /** + * Denomination public key of the coin. + */ + struct TALER_DenominationPublicKey pub; +}; + + +/** + * Result of a /link request. + */ +struct TALER_EXCHANGE_LinkResult +{ + /** + * HTTP status. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + /** + * Array of @e num_coins values about the + * coins obtained via linkage. + */ + const struct TALER_EXCHANGE_LinkedCoinInfo *coins; + + /** + * Number of coins returned. + */ + unsigned int num_coins; + } ok; + + } details; + +}; + + +/** * Callbacks of this type are used to return the final result of submitting a * /coins/$COIN_PUB/link request to a exchange. If the operation was * successful, this function returns the signatures over the coins that were * created when the original coin was melted. * * @param cls closure - * @param hr HTTP response data - * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed - * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error - * @param sigs array of signature over @a num_coins coins, NULL on error - * @param pubs array of public keys for the @a sigs, NULL on error + * @param lr result of the /link operation */ typedef void (*TALER_EXCHANGE_LinkCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_CoinSpendPrivateKeyP *coin_privs, - const struct TALER_DenominationSignature *sigs, - const struct TALER_DenominationPublicKey *pubs); + const struct TALER_EXCHANGE_LinkResult *lr); /** @@ -1660,18 +3709,23 @@ typedef void * This API is typically not used by anyone, it is more a threat against those * trying to receive a funds transfer by abusing the refresh protocol. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx CURL context + * @param url exchange base URL * @param coin_priv private key to request link data for + * @param age_commitment_proof age commitment to the corresponding coin, might be NULL * @param link_cb the callback to call with the useful result of the * refresh operation the @a coin_priv was involved in (if any) * @param link_cb_cls closure for @a link_cb * @return a handle for this request */ struct TALER_EXCHANGE_LinkHandle * -TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - TALER_EXCHANGE_LinkCallback link_cb, - void *link_cb_cls); +TALER_EXCHANGE_link ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentProof *age_commitment_proof, + TALER_EXCHANGE_LinkCallback link_cb, + void *link_cb_cls); /** @@ -1711,12 +3765,12 @@ struct TALER_EXCHANGE_TransferData /** * hash of the payto:// URI the transfer went to */ - struct TALER_PaytoHash h_payto; + struct TALER_PaytoHashP h_payto; /** * time when the exchange claims to have performed the wire transfer */ - struct GNUNET_TIME_Absolute execution_time; + struct GNUNET_TIME_Timestamp execution_time; /** * Actual amount of the wire transfer, excluding the wire fee. @@ -1742,25 +3796,52 @@ struct TALER_EXCHANGE_TransferData /** + * Response for a GET /transfers request. + */ +struct TALER_EXCHANGE_TransfersGetResponse +{ + /** + * HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on HTTP status code. + */ + union + { + /** + * Details if status code is #MHD_HTTP_OK. + */ + struct + { + struct TALER_EXCHANGE_TransferData td; + } ok; + + } details; +}; + + +/** * Function called with detailed wire transfer data, including all * of the coin transactions that were combined into the wire transfer. * * @param cls closure - * @param hr HTTP response data - * @param ta transfer data, (set only if @a http_status is #MHD_HTTP_OK, otherwise NULL) + * @param tgr response data */ typedef void (*TALER_EXCHANGE_TransfersGetCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_TransferData *ta); + const struct TALER_EXCHANGE_TransfersGetResponse *tgr); /** * Query the exchange about which transactions were combined * to create a wire transfer. * - * @param exchange exchange to query + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys * @param wtid raw wire transfer identifier to get information about * @param cb callback to call * @param cb_cls closure for @a cb @@ -1768,7 +3849,9 @@ typedef void */ struct TALER_EXCHANGE_TransfersGetHandle * TALER_EXCHANGE_transfers_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_EXCHANGE_TransfersGetCallback cb, void *cb_cls); @@ -1837,7 +3920,7 @@ struct TALER_EXCHANGE_GetDepositResponse /** * actual execution time for the wire transfer */ - struct GNUNET_TIME_Absolute execution_time; + struct GNUNET_TIME_Timestamp execution_time; /** * contribution to the total amount by this coin, all zeros if exchange did not @@ -1845,12 +3928,7 @@ struct TALER_EXCHANGE_GetDepositResponse */ struct TALER_Amount coin_contribution; - /** - * Payment target that the merchant should use - * to check for its KYC status. - */ - uint64_t payment_target_uuid; - } success; + } ok; /** * Response if the status was #MHD_HTTP_ACCEPTED @@ -1861,13 +3939,19 @@ struct TALER_EXCHANGE_GetDepositResponse /** * planned execution time for the wire transfer */ - struct GNUNET_TIME_Absolute execution_time; + struct GNUNET_TIME_Timestamp execution_time; /** - * Payment target that the merchant should use - * to check for its KYC status. + * KYC legitimization requirement that the merchant should use to check + * for its KYC status. + */ + uint64_t requirement_row; + + /** + * Current AML state for the account. May explain why transfers are + * not happening. */ - uint64_t payment_target_uuid; + enum TALER_AmlDecisionState aml_decision; /** * Set to 'true' if the KYC check is already finished and @@ -1884,8 +3968,7 @@ struct TALER_EXCHANGE_GetDepositResponse * Function called with detailed wire transfer data. * * @param cls closure - * @param hr HTTP response data - * @param dd details about the deposit (NULL on errors) + * @param dr details about the deposit response */ typedef void (*TALER_EXCHANGE_DepositGetCallback)( @@ -1898,22 +3981,28 @@ typedef void * which aggregate wire transfer the deposit operation identified by @a coin_pub, * @a merchant_priv and @a h_contract_terms contributed to. * - * @param exchange the exchange to query + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys * @param merchant_priv the merchant's private key * @param h_wire hash of merchant's wire transfer details * @param h_contract_terms hash of the proposal data * @param coin_pub public key of the coin + * @param timeout timeout to use for long-polling, 0 for no long polling * @param cb function to call with the result * @param cb_cls closure for @a cb * @return handle to abort request */ struct TALER_EXCHANGE_DepositGetHandle * TALER_EXCHANGE_deposits_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, const struct TALER_MerchantPrivateKeyP *merchant_priv, - const struct TALER_MerchantWireHash *h_wire, - const struct TALER_PrivateContractHash *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_DepositGetCallback cb, void *cb_cls); @@ -1929,131 +4018,201 @@ TALER_EXCHANGE_deposits_get_cancel ( struct TALER_EXCHANGE_DepositGetHandle *dwh); +/* ********************* /recoup *********************** */ + + +/** + * @brief A /recoup Handle + */ +struct TALER_EXCHANGE_RecoupHandle; + + +/** + * Response from a recoup request. + */ +struct TALER_EXCHANGE_RecoupResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * public key of the reserve receiving the recoup + */ + struct TALER_ReservePublicKeyP reserve_pub; + + } ok; + } details; + +}; + + /** - * Convenience function. Verifies a coin's transaction history as - * returned by the exchange. + * Callbacks of this type are used to return the final result of + * submitting a recoup request to a exchange. If the operation was + * successful, this function returns the @a reserve_pub of the + * reserve that was credited. * - * @param dk fee structure for the coin, NULL to skip verifying fees - * @param currency expected currency for the coin - * @param coin_pub public key of the coin - * @param history history of the coin in json encoding - * @param[out] h_denom_pub set to the hash of the coin's denomination (if available) - * @param[out] total how much of the coin has been spent according to @a history - * @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not + * @param cls closure + * @param rr response data */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_verify_coin_history ( - const struct TALER_EXCHANGE_DenomPublicKey *dk, - const char *currency, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - json_t *history, - struct TALER_DenominationHash *h_denom_pub, - struct TALER_Amount *total); +typedef void +(*TALER_EXCHANGE_RecoupResultCallback) ( + void *cls, + const struct TALER_EXCHANGE_RecoupResponse *rr); /** - * Parse history given in JSON format and return it in binary - * format. + * Ask the exchange to pay back a coin due to the exchange triggering + * the emergency recoup protocol for a given denomination. The value + * of the coin will be refunded to the original customer (without fees). * - * @param exchange connection to the exchange we can use - * @param history JSON array with the history - * @param reserve_pub public key of the reserve to inspect - * @param currency currency we expect the balance to be in - * @param[out] balance final balance - * @param history_length number of entries in @a history - * @param[out] rhistory array of length @a history_length, set to the - * parsed history entries - * @return #GNUNET_OK if history was valid and @a rhistory and @a balance - * were set, - * #GNUNET_SYSERR if there was a protocol violation in @a history + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param pk kind of coin to pay back + * @param denom_sig signature over the coin by the exchange using @a pk + * @param exchange_vals contribution from the exchange on the withdraw + * @param ps secret internals of the original planchet + * @param recoup_cb the callback to call when the final result for this request is available + * @param recoup_cb_cls closure for @a recoup_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_parse_reserve_history ( - struct TALER_EXCHANGE_Handle *exchange, - const json_t *history, - const struct TALER_ReservePublicKeyP *reserve_pub, - const char *currency, - struct TALER_Amount *balance, - unsigned int history_length, - struct TALER_EXCHANGE_ReserveHistory *rhistory); +struct TALER_EXCHANGE_RecoupHandle * +TALER_EXCHANGE_recoup ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_PlanchetMasterSecretP *ps, + TALER_EXCHANGE_RecoupResultCallback recoup_cb, + void *recoup_cb_cls); /** - * Free memory (potentially) allocated by #TALER_EXCHANGE_parse_reserve_history(). + * Cancel a recoup request. This function cannot be used on a + * request handle if the callback was already invoked. * - * @param rhistory result to free - * @param len number of entries in @a rhistory + * @param ph the recoup handle */ void -TALER_EXCHANGE_free_reserve_history ( - struct TALER_EXCHANGE_ReserveHistory *rhistory, - unsigned int len); +TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph); -/* ********************* /recoup *********************** */ +/* ********************* /recoup-refresh *********************** */ /** - * @brief A /recoup Handle + * @brief A /recoup-refresh Handle */ -struct TALER_EXCHANGE_RecoupHandle; +struct TALER_EXCHANGE_RecoupRefreshHandle; + + +/** + * Response from a /recoup-refresh request. + */ +struct TALER_EXCHANGE_RecoupRefreshResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * public key of the dirty coin that was credited + */ + struct TALER_CoinSpendPublicKeyP old_coin_pub; + + } ok; + } details; + +}; /** * Callbacks of this type are used to return the final result of - * submitting a refresh request to a exchange. If the operation was - * successful, this function returns the signatures over the coins - * that were remelted. The @a coin_privs and @a sigs arrays give the - * coins in the same order (and should have the same length) in which - * the original request specified the respective denomination keys. + * submitting a recoup-refresh request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error - * @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error + * @param rrr response data */ typedef void -(*TALER_EXCHANGE_RecoupResultCallback) ( +(*TALER_EXCHANGE_RecoupRefreshResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinSpendPublicKeyP *old_coin_pub); + const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr); /** * Ask the exchange to pay back a coin due to the exchange triggering * the emergency recoup protocol for a given denomination. The value - * of the coin will be refunded to the original customer (without fees). + * of the coin will be refunded to the original coin that the + * revoked coin was refreshed from. The original coin is then + * considered a zombie. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys * @param pk kind of coin to pay back * @param denom_sig signature over the coin by the exchange using @a pk - * @param ps secret internals of the original planchet - * @param was_refreshed true if the coin in @a ps was refreshed + * @param exchange_vals contribution from the exchange on the withdraw + * @param rms melt secret of the refreshing operation + * @param ps coin-specific secrets derived for this coin during the refreshing operation + * @param idx index of the fresh coin in the refresh operation that is now being recouped * @param recoup_cb the callback to call when the final result for this request is available * @param recoup_cb_cls closure for @a recoup_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). * In this case, the callback is not called. */ -struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_PlanchetSecretsP *ps, - bool was_refreshed, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls); +struct TALER_EXCHANGE_RecoupRefreshHandle * +TALER_EXCHANGE_recoup_refresh ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_PlanchetMasterSecretP *ps, + unsigned int idx, + TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, + void *recoup_cb_cls); /** - * Cancel a recoup request. This function cannot be used on a - * request handle if the callback was already invoked. + * Cancel a recoup-refresh request. This function cannot be used on a request + * handle if the callback was already invoked. * * @param ph the recoup handle */ void -TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph); +TALER_EXCHANGE_recoup_refresh_cancel ( + struct TALER_EXCHANGE_RecoupRefreshHandle *ph); /* ********************* /kyc* *********************** */ @@ -2089,9 +4248,14 @@ struct TALER_EXCHANGE_KycStatus { /** + * Details about which KYC check(s) were passed. + */ + const json_t *kyc_details; + + /** * Time of the affirmation. */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * The signing public key used for @e exchange_sig. @@ -2100,19 +4264,50 @@ struct TALER_EXCHANGE_KycStatus /** * Signature of purpose - * #TALER_SIGNATURE_ACCOUNT_SETUP_SUCCESS affirming + * #TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS affirming * the successful KYC process. */ struct TALER_ExchangeSignatureP exchange_sig; - } kyc_ok; + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } ok; /** - * URL the user should open in a browser if - * the KYC process is to be run. Returned if - * @e http_status is #MHD_HTTP_ACCEPTED. + * KYC is required. */ - const char *kyc_url; + struct + { + + /** + * URL the user should open in a browser if + * the KYC process is to be run. Returned if + * @e http_status is #MHD_HTTP_ACCEPTED. + */ + const char *kyc_url; + + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } accepted; + + /** + * KYC is OK, but account needs positive AML decision. + */ + struct + { + + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } unavailable_for_legal_reasons; } details; @@ -2134,21 +4329,28 @@ typedef void * Run interaction with exchange to check KYC status * of a merchant. * - * @param eh exchange handle to use - * @param payment_target number identifying the target + * @param ctx CURL context + * @param url exchange base URL + * @param keys keys of the exchange + * @param requirement_row number identifying the KYC requirement * @param h_payto hash of the payto:// URI at @a payment_target + * @param ut type of the entity performing the KYC check * @param timeout how long to wait for a positive KYC status * @param cb function to call with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct TALER_EXCHANGE_KycCheckHandle * -TALER_EXCHANGE_kyc_check (struct TALER_EXCHANGE_Handle *eh, - uint64_t payment_target, - const struct TALER_PaytoHash *h_payto, - struct GNUNET_TIME_Relative timeout, - TALER_EXCHANGE_KycStatusCallback cb, - void *cb_cls); +TALER_EXCHANGE_kyc_check ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + uint64_t requirement_row, + const struct TALER_PaytoHashP *h_payto, + enum TALER_KYCLOGIC_KycUserType ut, + struct GNUNET_TIME_Relative timeout, + TALER_EXCHANGE_KycStatusCallback cb, + void *cb_cls); /** @@ -2194,7 +4396,7 @@ struct TALER_EXCHANGE_KycProofResponse * Function called with the result of a KYC check. * * @param cls closure - * @param ks the account's KYC status details + * @param kpr the account's KYC status details */ typedef void (*TALER_EXCHANGE_KycProofCallback)( @@ -2211,21 +4413,25 @@ struct TALER_EXCHANGE_KycProofHandle; /** * Run interaction with exchange to provide proof of KYC status. * - * @param eh exchange handle to use - * @param payment_target number identifying the target - * @param code OAuth 2.0 code argument - * @param state OAuth 2.0 state argument + * @param ctx CURL context + * @param url exchange base URL + * @param h_payto hash of payto URI identifying the target account + * @param logic name of the KYC logic to run + * @param args additional args to pass, can be NULL + * or a string to append to the URL. Must then begin with '&'. * @param cb function to call with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct TALER_EXCHANGE_KycProofHandle * -TALER_EXCHANGE_kyc_proof (struct TALER_EXCHANGE_Handle *eh, - uint64_t payment_target, - const char *code, - const char *state, - TALER_EXCHANGE_KycProofCallback cb, - void *cb_cls); +TALER_EXCHANGE_kyc_proof ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_PaytoHashP *h_payto, + const char *logic, + const char *args, + TALER_EXCHANGE_KycProofCallback cb, + void *cb_cls); /** @@ -2260,10 +4466,29 @@ struct TALER_EXCHANGE_WalletKycResponse enum TALER_ErrorCode ec; /** - * Wallet's payment target UUID. Only valid if - * @e http_status is #MHD_HTTP_OK + * Variants depending on @e http_status. */ - uint64_t payment_target_uuid; + union + { + + /** + * In case @e http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Wallet's KYC requirement row. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI identifying the wallet to KYC. + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; }; @@ -2284,17 +4509,22 @@ typedef void * Run interaction with exchange to find out the wallet's KYC * identifier. * - * @param eh exchange handle to use + * @param ctx CURL context + * @param url exchange base URL * @param reserve_priv wallet private key to check + * @param balance balance (or balance threshold) crossed by the wallet * @param cb function to call with the result * @param cb_cls closure for @a cb * @return NULL on error */ struct TALER_EXCHANGE_KycWalletHandle * -TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *eh, - const struct TALER_ReservePrivateKeyP *reserve_priv, - TALER_EXCHANGE_KycWalletCallback cb, - void *cb_cls); +TALER_EXCHANGE_kyc_wallet ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *balance, + TALER_EXCHANGE_KycWalletCallback cb, + void *cb_cls); /** @@ -2327,17 +4557,17 @@ struct TALER_EXCHANGE_FutureSigningPublicKey /** * Validity start time */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Validity expiration time (how long the exchange may use it). */ - struct GNUNET_TIME_Absolute valid_until; + struct GNUNET_TIME_Timestamp valid_until; /** * Validity expiration time for legal disputes. */ - struct GNUNET_TIME_Absolute valid_legal; + struct GNUNET_TIME_Timestamp valid_legal; }; @@ -2359,18 +4589,18 @@ struct TALER_EXCHANGE_FutureDenomPublicKey /** * Timestamp indicating when the denomination key becomes valid */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Timestamp indicating when the denomination key can’t be used anymore to * withdraw new coins. */ - struct GNUNET_TIME_Absolute withdraw_valid_until; + struct GNUNET_TIME_Timestamp withdraw_valid_until; /** * Timestamp indicating when coins of this denomination become invalid. */ - struct GNUNET_TIME_Absolute expire_deposit; + struct GNUNET_TIME_Timestamp expire_deposit; /** * When do signatures with this denomination key become invalid? @@ -2379,7 +4609,7 @@ struct TALER_EXCHANGE_FutureDenomPublicKey * of the evidence. @e expire_legal is expected to be significantly * larger than @e expire_deposit (by a year or more). */ - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp expire_legal; /** * The value of this denomination @@ -2431,11 +4661,16 @@ struct TALER_EXCHANGE_FutureKeys struct TALER_SecurityModulePublicKeyP signkey_secmod_public_key; /** - * Public key of the denomination security module. + * Public key of the RSA denomination security module. */ struct TALER_SecurityModulePublicKeyP denom_secmod_public_key; /** + * Public key of the CS denomination security module. + */ + struct TALER_SecurityModulePublicKeyP denom_secmod_cs_public_key; + + /** * Offline master public key used by this exchange. */ struct TALER_MasterPublicKeyP master_pub; @@ -2454,18 +4689,47 @@ struct TALER_EXCHANGE_FutureKeys /** + * Response from a /management/keys request. + */ +struct TALER_EXCHANGE_ManagementGetKeysResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * information about the various keys used + * by the exchange + */ + struct TALER_EXCHANGE_FutureKeys keys; + + } ok; + } details; + +}; + + +/** * Function called with information about future keys. * * @param cls closure - * @param hr HTTP response data - * @param keys information about the various keys used - * by the exchange, NULL if /management/keys failed + * @param mgr HTTP response data */ typedef void (*TALER_EXCHANGE_ManagementGetKeysCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_FutureKeys *keys); + const struct TALER_EXCHANGE_ManagementGetKeysResponse *mgr); /** @@ -2485,10 +4749,11 @@ struct TALER_EXCHANGE_ManagementGetKeysHandle; * @return the request handle; NULL upon error */ struct TALER_EXCHANGE_ManagementGetKeysHandle * -TALER_EXCHANGE_get_management_keys (struct GNUNET_CURL_Context *ctx, - const char *url, - TALER_EXCHANGE_ManagementGetKeysCallback cb, - void *cb_cls); +TALER_EXCHANGE_get_management_keys ( + struct GNUNET_CURL_Context *ctx, + const char *url, + TALER_EXCHANGE_ManagementGetKeysCallback cb, + void *cb_cls); /** @@ -2528,7 +4793,7 @@ struct TALER_EXCHANGE_DenominationKeySignature /** * The hash of the denomination's public key */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_DenominationHashP h_denom_pub; /** * Signature over this denomination key by the exchange's master signature. @@ -2568,15 +4833,28 @@ struct TALER_EXCHANGE_ManagementPostKeysData /** + * Response from a POST /management/keys request. + */ +struct TALER_EXCHANGE_ManagementPostKeysResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** * Function called with information about the post keys operation result. * * @param cls closure - * @param hr HTTP response data + * @param mr response data */ typedef void (*TALER_EXCHANGE_ManagementPostKeysCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementPostKeysResponse *mr); /** @@ -2613,6 +4891,163 @@ void TALER_EXCHANGE_post_management_keys_cancel ( struct TALER_EXCHANGE_ManagementPostKeysHandle *ph); + +/** + * Information needed for a POST /management/extensions operation. + * + * It represents the interface ExchangeKeysResponse as defined in + * https://docs.taler.net/design-documents/006-extensions.html#exchange + */ +struct TALER_EXCHANGE_ManagementPostExtensionsData +{ + const json_t *extensions; + struct TALER_MasterSignatureP extensions_sig; +}; + + +/** + * Response from a POST /management/extensions request. + */ +struct TALER_EXCHANGE_ManagementPostExtensionsResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** + * Function called with information about the post extensions operation result. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementPostExtensionsCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementPostExtensionsResponse *hr); + +/** + * @brief Handle for a POST /management/extensions request. + */ +struct TALER_EXCHANGE_ManagementPostExtensionsHandle; + + +/** + * Uploads the configurations of enabled extensions to the exchange, signed + * with the master key. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param ped signature data to POST + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementPostExtensionsHandle * +TALER_EXCHANGE_management_post_extensions ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped, + TALER_EXCHANGE_ManagementPostExtensionsCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_post_extensions() operation. + * + * @param ph handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_post_extensions_cancel ( + struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph); + + +/** + * Response from a POST /management/drain request. + */ +struct TALER_EXCHANGE_ManagementDrainResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** + * Function called with information about the drain profits result. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementDrainProfitsCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementDrainResponse *hr); + + +/** + * @brief Handle for a POST /management/drain request. + */ +struct TALER_EXCHANGE_ManagementDrainProfitsHandle; + + +/** + * Uploads the drain profits request. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param wtid wire transfer identifier to use + * @param amount total to transfer + * @param date when was the request created + * @param account_section configuration section identifying account to debit + * @param payto_uri RFC 8905 URI of the account to credit + * @param master_sig signature affirming the operation + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementDrainProfitsHandle * +TALER_EXCHANGE_management_drain_profits ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Timestamp date, + const char *account_section, + const char *payto_uri, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementDrainProfitsCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_drain_profits() operation. + * + * @param dp handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_drain_profits_cancel ( + struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp); + + +/** + * Response from a POST /management/denominations/$DENOM/revoke request. + */ +struct TALER_EXCHANGE_ManagementRevokeDenominationResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + /** * Function called with information about the post revocation operation result. * @@ -2622,7 +5057,7 @@ TALER_EXCHANGE_post_management_keys_cancel ( typedef void (*TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementRevokeDenominationResponse *hr); /** @@ -2646,7 +5081,7 @@ struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle * TALER_EXCHANGE_management_revoke_denomination_key ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb, void *cb_cls); @@ -2663,6 +5098,18 @@ TALER_EXCHANGE_management_revoke_denomination_key_cancel ( /** + * Response from a POST /management/signkeys/$SK/revoke request. + */ +struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + +/** * Function called with information about the post revocation operation result. * * @param cls closure @@ -2671,7 +5118,7 @@ TALER_EXCHANGE_management_revoke_denomination_key_cancel ( typedef void (*TALER_EXCHANGE_ManagementRevokeSigningKeyCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse *hr); /** @@ -2712,15 +5159,515 @@ TALER_EXCHANGE_management_revoke_signing_key_cancel ( /** - * Function called with information about the auditor setup operation result. + * Response from a POST /management/aml-officers request. + */ +struct TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + +/** + * Function called with information about the change to + * an AML officer status. * * @param cls closure * @param hr HTTP response data */ typedef void +(*TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementUpdateAmlOfficerResponse *hr); + + +/** + * @brief Handle for a POST /management/aml-officers/$OFFICER_PUB request. + */ +struct TALER_EXCHANGE_ManagementUpdateAmlOfficer; + + +/** + * Inform the exchange that the status of an AML officer has changed. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param officer_pub the public signing key of the officer + * @param officer_name name of the officer + * @param change_date when to affect the status change + * @param is_active true to enable the officer + * @param read_only true to only allow read-only access + * @param master_sig signature affirming the change + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementUpdateAmlOfficer * +TALER_EXCHANGE_management_update_aml_officer ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *officer_name, + struct GNUNET_TIME_Timestamp change_date, + bool is_active, + bool read_only, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementUpdateAmlOfficerCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_update_aml_officer() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_update_aml_officer_cancel ( + struct TALER_EXCHANGE_ManagementUpdateAmlOfficer *rh); + + +/** + * Summary data about an AML decision. + */ +struct TALER_EXCHANGE_AmlDecisionSummary +{ + /** + * What is the current monthly threshold. + */ + struct TALER_Amount threshold; + + /** + * Account the decision was made for. + */ + struct TALER_PaytoHashP h_payto; + + /** + * RowID of this decision. + */ + uint64_t rowid; + + /** + * Current decision state. + */ + enum TALER_AmlDecisionState current_state; +}; + + +/** + * Information about AML decisions returned by the exchange. + */ +struct TALER_EXCHANGE_AmlDecisionsResponse +{ + /** + * HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP response code. + */ + union + { + + /** + * Information returned on success (#MHD_HTTP_OK). + */ + struct + { + + /** + * Array of AML decision summaries returned by the exchange. + */ + const struct TALER_EXCHANGE_AmlDecisionSummary *decisions; + + /** + * Length of the @e decisions array. + */ + unsigned int decisions_length; + + } ok; + + } details; +}; + + +/** + * Function called with summary information about + * AML decisions. + * + * @param cls closure + * @param adr response data + */ +typedef void +(*TALER_EXCHANGE_LookupAmlDecisionsCallback) ( + void *cls, + const struct TALER_EXCHANGE_AmlDecisionsResponse *adr); + + +/** + * @brief Handle for a POST /aml/$OFFICER_PUB/decisions/$STATUS request. + */ +struct TALER_EXCHANGE_LookupAmlDecisions; + + +/** + * Inform the exchange that an AML decision has been taken. + * + * @param ctx the context + * @param exchange_url HTTP base URL for the exchange + * @param start row number starting point (exclusive rowid) + * @param delta number of records to return, negative for descending, positive for ascending from start + * @param state type of AML decisions to return + * @param officer_priv private key of the deciding AML officer + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_LookupAmlDecisions * +TALER_EXCHANGE_lookup_aml_decisions ( + struct GNUNET_CURL_Context *ctx, + const char *exchange_url, + uint64_t start, + int delta, + enum TALER_AmlDecisionState state, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + TALER_EXCHANGE_LookupAmlDecisionsCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_lookup_aml_decisions() operation. + * + * @param lh handle of the operation to cancel + */ +void +TALER_EXCHANGE_lookup_aml_decisions_cancel ( + struct TALER_EXCHANGE_LookupAmlDecisions *lh); + + +/** + * Detailed data about an AML decision. + */ +struct TALER_EXCHANGE_AmlDecisionDetail +{ + /** + * When was the decision made. + */ + struct GNUNET_TIME_Timestamp decision_time; + + /** + * New threshold set by this decision. + */ + struct TALER_Amount new_threshold; + + /** + * Who made the decision? + */ + struct TALER_AmlOfficerPublicKeyP decider_pub; + + /** + * Justification given for the decision. + */ + const char *justification; + + /** + * New decision state. + */ + enum TALER_AmlDecisionState new_state; +}; + + +/** + * Detailed data collected during a KYC process for the account. + */ +struct TALER_EXCHANGE_KycHistoryDetail +{ + /** + * Configuration section name of the KYC provider that contributed the data. + */ + const char *provider_section; + + /** + * The collected KYC data. + */ + const json_t *attributes; + + /** + * When was the data collection made. + */ + struct GNUNET_TIME_Timestamp collection_time; + +}; + + +/** + * Information about AML decision details returned by the exchange. + */ +struct TALER_EXCHANGE_AmlDecisionResponse +{ + /** + * HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP response code. + */ + union + { + + /** + * Information returned on success (#MHD_HTTP_OK). + */ + struct + { + + /** + * Array of AML decision details returned by the exchange. + */ + const struct TALER_EXCHANGE_AmlDecisionDetail *aml_history; + + /** + * Length of the @e aml_history array. + */ + unsigned int aml_history_length; + + /** + * Array of KYC data collections returned by the exchange. + */ + const struct TALER_EXCHANGE_KycHistoryDetail *kyc_attributes; + + /** + * Length of the @e kyc_attributes array. + */ + unsigned int kyc_attributes_length; + + } ok; + + } details; +}; + + +/** + * Function called with summary information about + * AML decisions. + * + * @param cls closure + * @param adr response data + */ +typedef void +(*TALER_EXCHANGE_LookupAmlDecisionCallback) ( + void *cls, + const struct TALER_EXCHANGE_AmlDecisionResponse *adr); + + +/** + * @brief Handle for a POST /aml/$OFFICER_PUB/decision/$H_PAYTO request. + */ +struct TALER_EXCHANGE_LookupAmlDecision; + + +/** + * Inform the exchange that an AML decision has been taken. + * + * @param ctx the context + * @param exchange_url HTTP base URL for the exchange + * @param h_payto which account to return the decision history for + * @param officer_priv private key of the deciding AML officer + * @param history true to return the full history, otherwise only the last decision + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_LookupAmlDecision * +TALER_EXCHANGE_lookup_aml_decision ( + struct GNUNET_CURL_Context *ctx, + const char *exchange_url, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + bool history, + TALER_EXCHANGE_LookupAmlDecisionCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_lookup_aml_decision() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_lookup_aml_decision_cancel ( + struct TALER_EXCHANGE_LookupAmlDecision *rh); + + +/** + * @brief Handle for a POST /aml-decision/$OFFICER_PUB request. + */ +struct TALER_EXCHANGE_AddAmlDecision; + + +/** + * Response when making an AML decision. + */ +struct TALER_EXCHANGE_AddAmlDecisionResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about storing an + * an AML decision. + * + * @param cls closure + * @param adr response data + */ +typedef void +(*TALER_EXCHANGE_AddAmlDecisionCallback) ( + void *cls, + const struct TALER_EXCHANGE_AddAmlDecisionResponse *adr); + +/** + * Inform the exchange that an AML decision has been taken. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param justification human-readable justification + * @param decision_time when was the decision made + * @param new_threshold at what monthly amount threshold + * should a revision be triggered + * @param h_payto payto URI hash of the account the + * decision is about + * @param new_state updated AML state + * @param kyc_requirements JSON array of KYC requirements being imposed, NULL for none + * @param officer_priv private key of the deciding AML officer + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_AddAmlDecision * +TALER_EXCHANGE_add_aml_decision ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const char *justification, + struct GNUNET_TIME_Timestamp decision_time, + const struct TALER_Amount *new_threshold, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState new_state, + const json_t *kyc_requirements, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + TALER_EXCHANGE_AddAmlDecisionCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_add_aml_decision() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_add_aml_decision_cancel ( + struct TALER_EXCHANGE_AddAmlDecision *rh); + + +/** + * Response when adding a partner exchange. + */ +struct TALER_EXCHANGE_ManagementAddPartnerResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + +/** + * Function called with information about the change to + * an AML officer status. + * + * @param cls closure + * @param apr response data + */ +typedef void +(*TALER_EXCHANGE_ManagementAddPartnerCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementAddPartnerResponse *apr); + + +/** + * @brief Handle for a POST /management/partners/$PARTNER_PUB request. + */ +struct TALER_EXCHANGE_ManagementAddPartner; + + +/** + * Inform the exchange that the status of a partnering + * exchange was defined. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param partner_pub the offline signing key of the partner + * @param start_date validity period start + * @param end_date validity period end + * @param wad_frequency how often will we do wad transfers to this partner + * @param wad_fee what is the wad fee to this partner + * @param partner_base_url what is the base URL of the @a partner_pub exchange + * @param master_sig the signature the signature + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementAddPartner * +TALER_EXCHANGE_management_add_partner ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_MasterPublicKeyP *partner_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementAddPartnerCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_add_partner() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_add_partner_cancel ( + struct TALER_EXCHANGE_ManagementAddPartner *rh); + + +/** + * Response when enabling an auditor. + */ +struct TALER_EXCHANGE_ManagementAuditorEnableResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + +/** + * Function called with information about the auditor setup operation result. + * + * @param cls closure + * @param aer response data + */ +typedef void (*TALER_EXCHANGE_ManagementAuditorEnableCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementAuditorEnableResponse *aer); /** @@ -2750,7 +5697,7 @@ TALER_EXCHANGE_management_enable_auditor ( const struct TALER_AuditorPublicKeyP *auditor_pub, const char *auditor_url, const char *auditor_name, - struct GNUNET_TIME_Absolute validity_start, + struct GNUNET_TIME_Timestamp validity_start, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementAuditorEnableCallback cb, void *cb_cls); @@ -2765,17 +5712,27 @@ void TALER_EXCHANGE_management_enable_auditor_cancel ( struct TALER_EXCHANGE_ManagementAuditorEnableHandle *ah); +/** + * Response when disabling an auditor. + */ +struct TALER_EXCHANGE_ManagementAuditorDisableResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; /** * Function called with information about the auditor disable operation result. * * @param cls closure - * @param hr HTTP response data + * @param adr HTTP response data */ typedef void (*TALER_EXCHANGE_ManagementAuditorDisableCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementAuditorDisableResponse *adr); /** @@ -2801,7 +5758,7 @@ TALER_EXCHANGE_management_disable_auditor ( struct GNUNET_CURL_Context *ctx, const char *url, const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Absolute validity_end, + struct GNUNET_TIME_Timestamp validity_end, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementAuditorDisableCallback cb, void *cb_cls); @@ -2818,15 +5775,27 @@ TALER_EXCHANGE_management_disable_auditor_cancel ( /** + * Response from an exchange account/enable operation. + */ +struct TALER_EXCHANGE_ManagementWireEnableResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** * Function called with information about the wire enable operation result. * * @param cls closure - * @param hr HTTP response data + * @param wer HTTP response data */ typedef void (*TALER_EXCHANGE_ManagementWireEnableCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementWireEnableResponse *wer); /** @@ -2841,11 +5810,16 @@ struct TALER_EXCHANGE_ManagementWireEnableHandle; * @param ctx the context * @param url HTTP base URL for the exchange * @param payto_uri RFC 8905 URI of the exchange's bank account + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param validity_start when was this decided? * @param master_sig1 signature affirming the wire addition * of purpose #TALER_SIGNATURE_MASTER_ADD_WIRE * @param master_sig2 signature affirming the validity of the account for clients; * of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS. + * @param bank_label label to use when showing the account, can be NULL + * @param priority priority for ordering the bank accounts * @param cb function to call with the exchange's result * @param cb_cls closure for @a cb * @return the request handle; NULL upon error @@ -2855,9 +5829,14 @@ TALER_EXCHANGE_management_enable_wire ( struct GNUNET_CURL_Context *ctx, const char *url, const char *payto_uri, - struct GNUNET_TIME_Absolute validity_start, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp validity_start, const struct TALER_MasterSignatureP *master_sig1, const struct TALER_MasterSignatureP *master_sig2, + const char *bank_label, + int64_t priority, TALER_EXCHANGE_ManagementWireEnableCallback cb, void *cb_cls); @@ -2873,15 +5852,26 @@ TALER_EXCHANGE_management_enable_wire_cancel ( /** + * Response from an exchange account/disable operation. + */ +struct TALER_EXCHANGE_ManagementWireDisableResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + +/** * Function called with information about the wire disable operation result. * * @param cls closure - * @param hr HTTP response data + * @param wdr response data */ typedef void (*TALER_EXCHANGE_ManagementWireDisableCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementWireDisableResponse *wdr); /** @@ -2908,7 +5898,7 @@ TALER_EXCHANGE_management_disable_wire ( struct GNUNET_CURL_Context *ctx, const char *url, const char *payto_uri, - struct GNUNET_TIME_Absolute validity_end, + struct GNUNET_TIME_Timestamp validity_end, const struct TALER_MasterSignatureP *master_sig, TALER_EXCHANGE_ManagementWireDisableCallback cb, void *cb_cls); @@ -2925,15 +5915,26 @@ TALER_EXCHANGE_management_disable_wire_cancel ( /** + * Response when setting wire fees. + */ +struct TALER_EXCHANGE_ManagementSetWireFeeResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + +/** * Function called with information about the wire enable operation result. * * @param cls closure - * @param hr HTTP response data + * @param wfr response data */ typedef void (*TALER_EXCHANGE_ManagementSetWireFeeCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementSetWireFeeResponse *wfr); /** @@ -2950,8 +5951,7 @@ struct TALER_EXCHANGE_ManagementSetWireFeeHandle; * @param wire_method for which wire method are fees provided * @param validity_start start date for the provided wire fees * @param validity_end end date for the provided wire fees - * @param wire_fee the wire fee for this time period - * @param closing_fee the closing fee for this time period + * @param fees the wire fees for this time period * @param master_sig signature affirming the wire fees; * of purpose #TALER_SIGNATURE_MASTER_WIRE_FEES * @param cb function to call with the exchange's result @@ -2963,12 +5963,11 @@ TALER_EXCHANGE_management_set_wire_fees ( struct GNUNET_CURL_Context *ctx, const char *exchange_base_url, const char *wire_method, - struct GNUNET_TIME_Absolute validity_start, - struct GNUNET_TIME_Absolute validity_end, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, + struct GNUNET_TIME_Timestamp validity_start, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_WireFeeSet *fees, const struct TALER_MasterSignatureP *master_sig, - TALER_EXCHANGE_ManagementWireEnableCallback cb, + TALER_EXCHANGE_ManagementSetWireFeeCallback cb, void *cb_cls); @@ -2983,16 +5982,100 @@ TALER_EXCHANGE_management_set_wire_fees_cancel ( /** + * Response when setting global fees. + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about the global fee setting operation result. + * + * @param cls closure + * @param gfr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementSetGlobalFeeCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse *gfr); + + +/** + * @brief Handle for a POST /management/global-fees request. + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle; + + +/** + * Inform the exchange about global fees. + * + * @param ctx the context + * @param exchange_base_url HTTP base URL for the exchange + * @param validity_start start date for the provided wire fees + * @param validity_end end date for the provided wire fees + * @param fees the wire fees for this time period + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account + * @param master_sig signature affirming the wire fees; + * of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle * +TALER_EXCHANGE_management_set_global_fees ( + struct GNUNET_CURL_Context *ctx, + const char *exchange_base_url, + struct GNUNET_TIME_Timestamp validity_start, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementSetGlobalFeeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_enable_wire() operation. + * + * @param sgfh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_set_global_fees_cancel ( + struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *sgfh); + + +/** + * Response when adding denomination signature by auditor. + */ +struct TALER_EXCHANGE_AuditorAddDenominationResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** * Function called with information about the POST * /auditor/$AUDITOR_PUB/$H_DENOM_PUB operation result. * * @param cls closure - * @param hr HTTP response data + * @param adr HTTP response data */ typedef void (*TALER_EXCHANGE_AuditorAddDenominationCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_AuditorAddDenominationResponse *adr); /** @@ -3018,7 +6101,7 @@ struct TALER_EXCHANGE_AuditorAddDenominationHandle * TALER_EXCHANGE_add_auditor_denomination ( struct GNUNET_CURL_Context *ctx, const char *url, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_AuditorPublicKeyP *auditor_pub, const struct TALER_AuditorSignatureP *auditor_sig, TALER_EXCHANGE_AuditorAddDenominationCallback cb, @@ -3035,4 +6118,1210 @@ TALER_EXCHANGE_add_auditor_denomination_cancel ( struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah); +/* ********************* W2W API ****************** */ + + +/** + * Response generated for a contract get request. + */ +struct TALER_EXCHANGE_ContractGetResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status code. + */ + union + { + /** + * Information returned on #MHD_HTTP_OK. + */ + struct + { + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Encrypted contract. + */ + const void *econtract; + + /** + * Number of bytes in @e econtract. + */ + size_t econtract_size; + + } ok; + + } details; + +}; + +/** + * Function called with information about the a purse. + * + * @param cls closure + * @param cgr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ContractGetCallback) ( + void *cls, + const struct TALER_EXCHANGE_ContractGetResponse *cgr); + + +/** + * @brief Handle for a GET /contracts/$CPUB request. + */ +struct TALER_EXCHANGE_ContractsGetHandle; + + +/** + * Request information about a contract from the exchange. + * + * @param ctx CURL context + * @param url exchange base URL + * @param contract_priv private key of the contract + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ContractsGetHandle * +TALER_EXCHANGE_contract_get ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ContractDiffiePrivateP *contract_priv, + TALER_EXCHANGE_ContractGetCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_contract_get() operation. + * + * @param cgh handle of the operation to cancel + */ +void +TALER_EXCHANGE_contract_get_cancel ( + struct TALER_EXCHANGE_ContractsGetHandle *cgh); + + +/** + * Response generated for a purse get request. + */ +struct TALER_EXCHANGE_PurseGetResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Response on #MHD_HTTP_OK. + */ + struct + { + + /** + * Time when the purse was merged (or zero if it + * was not merged). + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * Time when the full amount was deposited into + * the purse (or zero if a sufficient amount + * was not yet deposited). + */ + struct GNUNET_TIME_Timestamp deposit_timestamp; + + /** + * Reserve balance (how much was deposited in + * total into the reserve, minus deposit fees). + */ + struct TALER_Amount balance; + + /** + * Time when the purse will expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + } ok; + + } details; + +}; + + +/** + * Function called with information about the a purse. + * + * @param cls closure + * @param pgr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseGetCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseGetResponse *pgr); + + +/** + * @brief Handle for a GET /purses/$PPUB request. + */ +struct TALER_EXCHANGE_PurseGetHandle; + + +/** + * Request information about a purse from the exchange. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_pub public key of the purse + * @param timeout how long to wait for a change to happen + * @param wait_for_merge true to wait for a merge event, otherwise wait for a deposit event + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseGetHandle * +TALER_EXCHANGE_purse_get ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Relative timeout, + bool wait_for_merge, + TALER_EXCHANGE_PurseGetCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_get() operation. + * + * @param pgh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_get_cancel ( + struct TALER_EXCHANGE_PurseGetHandle *pgh); + + +/** + * Response generated for a purse creation request. + */ +struct TALER_EXCHANGE_PurseCreateDepositResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + /** + * Signing key used by the exchange to sign the + * purse create with deposit confirmation. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature from the exchange on the + * purse create with deposit confirmation. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + + } ok; + + } details; + +}; + +/** + * Function called with information about the creation + * of a new purse. + * + * @param cls closure + * @param pcr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseCreateDepositCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseCreateDepositResponse *pcr); + + +/** + * @brief Handle for a POST /purses/$PID/create request. + */ +struct TALER_EXCHANGE_PurseCreateDepositHandle; + + +/** + * Information about a coin to be deposited into a purse or reserve. + */ +struct TALER_EXCHANGE_PurseDeposit +{ + /** + * Age commitment data, might be NULL. + */ + const struct TALER_AgeCommitmentProof *age_commitment_proof; + + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Signature proving the validity of the coin. + */ + struct TALER_DenominationSignature denom_sig; + + /** + * Hash of the denomination's public key. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Amount of the coin to transfer into the purse. + */ + struct TALER_Amount amount; + +}; + + +/** + * Inform the exchange that a purse should be created + * and coins deposited into it. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_priv private key of the purse + * @param merge_priv the merge credential + * @param contract_priv key needed to obtain and decrypt the contract + * @param contract_terms contract the purse is about + * @param num_deposits length of the @a deposits array + * @param deposits array of deposits to make into the purse + * @param upload_contract true to upload the contract; must + * be FALSE for repeated calls to this API for the + * same purse (i.e. when adding more deposits). + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseCreateDepositHandle * +TALER_EXCHANGE_purse_create_with_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + unsigned int num_deposits, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], + bool upload_contract, + TALER_EXCHANGE_PurseCreateDepositCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_create_with_deposit() operation. + * + * @param pch handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_create_with_deposit_cancel ( + struct TALER_EXCHANGE_PurseCreateDepositHandle *pch); + + +/** + * Response generated for a purse deletion request. + */ +struct TALER_EXCHANGE_PurseDeleteResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about the deletion + * of a purse. + * + * @param cls closure + * @param pdr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseDeleteCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseDeleteResponse *pdr); + + +/** + * @brief Handle for a DELETE /purses/$PID request. + */ +struct TALER_EXCHANGE_PurseDeleteHandle; + + +/** + * Asks the exchange to delete a purse. Will only succeed if + * the purse was not yet merged and did not yet time out. + * + * @param ctx CURL context + * @param url exchange base URL + * @param purse_priv private key of the purse + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseDeleteHandle * +TALER_EXCHANGE_purse_delete ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + TALER_EXCHANGE_PurseDeleteCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_delete() operation. + * + * @param pdh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_delete_cancel ( + struct TALER_EXCHANGE_PurseDeleteHandle *pdh); + + +/** + * Response generated for an account merge request. + */ +struct TALER_EXCHANGE_AccountMergeResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Reserve signature affirming the merge. + */ + const struct TALER_ReserveSignatureP *reserve_sig; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + /** + * Signature by the exchange affirming the merge. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * Online signing key used by the exchange. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Timestamp of the exchange for @e exchange_sig. + */ + struct GNUNET_TIME_Timestamp etime; + + } ok; + + /** + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row target that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with information about an account merge + * operation. + * + * @param cls closure + * @param amr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_AccountMergeCallback) ( + void *cls, + const struct TALER_EXCHANGE_AccountMergeResponse *amr); + + +/** + * @brief Handle for a POST /purses/$PID/merge request. + */ +struct TALER_EXCHANGE_AccountMergeHandle; + + +/** + * Inform the exchange that a purse should be merged + * with a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_exchange_url base URL of the exchange with the reserve + * @param reserve_priv private key of the reserve to merge into + * @param purse_pub public key of the purse to merge + * @param merge_priv private key granting us the right to merge + * @param h_contract_terms hash of the purses' contract + * @param min_age minimum age of deposits into the purse + * @param purse_value_after_fees amount that should be in the purse + * @param purse_expiration when will the purse expire + * @param merge_timestamp when is the merge happening (current time) + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_AccountMergeHandle * +TALER_EXCHANGE_account_merge ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const char *reserve_exchange_url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint8_t min_age, + const struct TALER_Amount *purse_value_after_fees, + struct GNUNET_TIME_Timestamp purse_expiration, + struct GNUNET_TIME_Timestamp merge_timestamp, + TALER_EXCHANGE_AccountMergeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_account_merge() operation. + * + * @param amh handle of the operation to cancel + */ +void +TALER_EXCHANGE_account_merge_cancel ( + struct TALER_EXCHANGE_AccountMergeHandle *amh); + + +/** + * Response generated for a purse creation request. + */ +struct TALER_EXCHANGE_PurseCreateMergeResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Reserve signature generated for the request + * (client-side). + */ + const struct TALER_ReserveSignatureP *reserve_sig; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Details returned on #MHD_HTTP_OK. + */ + struct + { + + } ok; + + /** + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with information about the creation + * of a new purse. + * + * @param cls closure + * @param pcr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseCreateMergeCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseCreateMergeResponse *pcr); + + +/** + * @brief Handle for a POST /reserves/$RID/purse request. + */ +struct TALER_EXCHANGE_PurseCreateMergeHandle; + + +/** + * Inform the exchange that a purse should be created + * and merged with a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve + * @param purse_priv private key of the purse + * @param merge_priv private key of the merge capability + * @param contract_priv private key to get the contract + * @param contract_terms contract the purse is about + * @param upload_contract true to upload the contract + * @param pay_for_purse true to pay for purse creation + * @param merge_timestamp when should the merge happen (use current time) + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseCreateMergeHandle * +TALER_EXCHANGE_purse_create_with_merge ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + bool upload_contract, + bool pay_for_purse, + struct GNUNET_TIME_Timestamp merge_timestamp, + TALER_EXCHANGE_PurseCreateMergeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_create_with_merge() operation. + * + * @param pcm handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_create_with_merge_cancel ( + struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm); + + +/** + * Response generated for purse deposit request. + */ +struct TALER_EXCHANGE_PurseDepositResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + + /** + * When does the purse expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * How much was actually deposited into the purse. + */ + struct TALER_Amount total_deposited; + + /** + * How much should be in the purse in total in the end. + */ + struct TALER_Amount purse_value_after_fees; + + /** + * Hash of the contract (needed to verify signature). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + } ok; + } details; + +}; + +/** + * Function called with information about a purse-deposit + * operation. + * + * @param cls closure + * @param pdr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseDepositCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseDepositResponse *pdr); + + +/** + * @brief Handle for a POST /purses/$PID/deposit request. + */ +struct TALER_EXCHANGE_PurseDepositHandle; + + +/** + * Inform the exchange that a deposit should be made into + * a purse. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_exchange_url base URL of the exchange hosting the purse + * @param purse_pub public key of the purse to merge + * @param min_age minimum age we need to prove for the purse + * @param num_deposits length of the @a deposits array + * @param deposits array of deposits to make into the purse + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseDepositHandle * +TALER_EXCHANGE_purse_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const char *purse_exchange_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + uint8_t min_age, + unsigned int num_deposits, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], + TALER_EXCHANGE_PurseDepositCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_deposit() operation. + * + * @param amh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_deposit_cancel ( + struct TALER_EXCHANGE_PurseDepositHandle *amh); + + +/* ********************* /reserves/$RID/open *********************** */ + + +/** + * @brief A /reserves/$RID/open Handle + */ +struct TALER_EXCHANGE_ReservesOpenHandle; + + +/** + * @brief Reserve open result details. + */ +struct TALER_EXCHANGE_ReserveOpenResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + /** + * New expiration time + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Actual cost of the open operation. + */ + struct TALER_Amount open_cost; + + } ok; + + + /** + * Information returned if the payment provided is insufficient, if + * @e hr.http_status is #MHD_HTTP_PAYMENT_REQUIRED + */ + struct + { + /** + * Current expiration time of the reserve. + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Actual cost of the open operation that should have been paid. + */ + struct TALER_Amount open_cost; + + } payment_required; + + /** + * Information returned if status is + * #MHD_HTTP_CONFLICT. + */ + struct + { + /** + * Public key of the coin that caused the conflict. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + } conflict; + + /** + * Information returned if KYC is required to proceed, set if + * @e hr.http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve open request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesOpenCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveOpenResult *ror); + + +/** + * Submit a request to open a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve to open + * @param reserve_contribution amount to pay from the reserve's balance for the operation + * @param coin_payments_length length of the @a coin_payments array + * @param coin_payments array of coin payments to use for opening the reserve + * @param expiration_time desired new expiration time for the reserve + * @param min_purses minimum number of purses to allow being concurrently opened per reserve + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesOpenHandle * +TALER_EXCHANGE_reserves_open ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *reserve_contribution, + unsigned int coin_payments_length, + const struct TALER_EXCHANGE_PurseDeposit coin_payments[ + static coin_payments_length], + struct GNUNET_TIME_Timestamp expiration_time, + uint32_t min_purses, + TALER_EXCHANGE_ReservesOpenCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param[in] roh the reserve open request handle + */ +void +TALER_EXCHANGE_reserves_open_cancel ( + struct TALER_EXCHANGE_ReservesOpenHandle *roh); + + +/* ********************* /reserves/$RID/attest *********************** */ + + +/** + * @brief A Get /reserves/$RID/attest Handle + */ +struct TALER_EXCHANGE_ReservesGetAttestHandle; + + +/** + * @brief Reserve GET attest result details. + */ +struct TALER_EXCHANGE_ReserveGetAttestResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Length of the @e attributes array. + */ + unsigned int attributes_length; + + /** + * Array of attributes available about the user. + */ + const char **attributes; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve attest request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesGetAttestCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveGetAttestResult *ror); + + +/** + * Submit a request to get the list of attestable attributes for a reserve. + * + * @param ctx CURL context + * @param url exchange base URL + * @param reserve_pub public key of the reserve to get available attributes for + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesGetAttestHandle * +TALER_EXCHANGE_reserves_get_attestable ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePublicKeyP *reserve_pub, + TALER_EXCHANGE_ReservesGetAttestCallback cb, + void *cb_cls); + + +/** + * Cancel a request to get attestable attributes. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rgah the reserve get attestable request handle + */ +void +TALER_EXCHANGE_reserves_get_attestable_cancel ( + struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah); + + +/** + * @brief A POST /reserves/$RID/attest Handle + */ +struct TALER_EXCHANGE_ReservesPostAttestHandle; + + +/** + * @brief Reserve attest result details. + */ +struct TALER_EXCHANGE_ReservePostAttestResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + /** + * Time when the exchange made the signature. + */ + struct GNUNET_TIME_Timestamp exchange_time; + + /** + * Expiration time of the attested attributes. + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Signature by the exchange affirming the attributes. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * Online signing key used by the exchange. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Attributes being confirmed by the exchange. + */ + const json_t *attributes; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve attest request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesPostAttestCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReservePostAttestResult *ror); + + +/** + * Submit a request to attest attributes about the owner of a reserve. + * + * @param ctx CURL context + * @param url exchange base URL + * @param keys exchange key data + * @param reserve_priv private key of the reserve to attest + * @param attributes_length length of the @a attributes array + * @param attributes array of names of attributes to get attestations for + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesAttestHandle * +TALER_EXCHANGE_reserves_attest ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int attributes_length, + const char *attributes[const static attributes_length], + TALER_EXCHANGE_ReservesPostAttestCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve attestation request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rah the reserve attest request handle + */ +void +TALER_EXCHANGE_reserves_attest_cancel ( + struct TALER_EXCHANGE_ReservesAttestHandle *rah); + + +/* ********************* /reserves/$RID/close *********************** */ + + +/** + * @brief A /reserves/$RID/close Handle + */ +struct TALER_EXCHANGE_ReservesCloseHandle; + + +/** + * @brief Reserve close result details. + */ +struct TALER_EXCHANGE_ReserveCloseResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Amount wired to the target account. + */ + struct TALER_Amount wire_amount; + } ok; + + /** + * Information returned if KYC is required to proceed, set if + * @e hr.http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve close request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesCloseCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveCloseResult *ror); + + +/** + * Submit a request to close a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param reserve_priv private key of the reserve to close + * @param target_payto_uri where to send the payment, NULL to send to reserve origin + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesCloseHandle * +TALER_EXCHANGE_reserves_close ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const char *target_payto_uri, + TALER_EXCHANGE_ReservesCloseCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rch the reserve request handle + */ +void +TALER_EXCHANGE_reserves_close_cancel ( + struct TALER_EXCHANGE_ReservesCloseHandle *rch); + #endif /* _TALER_EXCHANGE_SERVICE_H */ diff --git a/src/include/taler_exchangedb_lib.h b/src/include/taler_exchangedb_lib.h index 7f466728a..d93cf9d6c 100644 --- a/src/include/taler_exchangedb_lib.h +++ b/src/include/taler_exchangedb_lib.h @@ -46,7 +46,6 @@ TALER_EXCHANGEDB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg); void TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin); - /** * Information about an account from the configuration. */ @@ -70,13 +69,13 @@ struct TALER_EXCHANGEDB_AccountInfo const char *method; /** - * true if this account is enabed to be debited + * true if this account is enabled to be debited * by the taler-exchange-aggregator. */ bool debit_enabled; /** - * true if this account is enabed to be credited by wallets + * true if this account is enabled to be credited by wallets * and needs to be watched by the taler-exchange-wirewatch. * Also, the account will only be included in /wire if credit * is enabled. @@ -95,7 +94,7 @@ struct TALER_EXCHANGEDB_AccountInfo * @param[out] ret where the resulting total is to be stored * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors */ -int +enum GNUNET_GenericReturnValue TALER_EXCHANGEDB_calculate_transaction_list_totals ( struct TALER_EXCHANGEDB_TransactionList *tl, const struct TALER_Amount *off, diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 9a1dc78b6..2d5857677 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,47 +18,89 @@ * @brief Low-level (statement-level) database access for the exchange * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H #include <jansson.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_db_lib.h> +#include "taler_json_lib.h" #include "taler_signatures.h" +#include "taler_extensions_policy.h" +/** + * The conflict that can occur for the age restriction + */ +enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict +{ + /** + * Value OK, no conflict + */ + TALER_AgeCommitmentHash_NoConflict = 0, -GNUNET_NETWORK_STRUCT_BEGIN + /** + * Given hash had a value, but NULL (or zero) was expected + */ + TALER_AgeCommitmentHash_NullExpected = 1, + + /** + * Given hash was NULL, but value was expected + */ + TALER_AgeCommitmentHash_ValueExpected = 2, + + /** + * Given hash differs from value in the known coin + */ + TALER_AgeCommitmentHash_ValueDiffers = 3, +}; /** - * @brief On disk format used for a exchange signing key. Signing keys are used - * by the exchange to affirm its messages, but not to create coins. - * Includes the private key followed by the public information about - * the signing key. + * Per-coin information returned when doing a batch insert. */ -struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP +struct TALER_EXCHANGEDB_CoinInfo { /** - * Private key part of the exchange's signing key. + * Row of the coin in the known_coins table. */ - struct TALER_ExchangePrivateKeyP signkey_priv; + uint64_t known_coin_id; /** - * Signature over @e issue + * Hash of the denomination, relevant on @e denom_conflict. */ - struct TALER_MasterSignatureP master_sig; + struct TALER_DenominationHashP denom_hash; /** - * Public information about a exchange signing key. + * Hash of the age commitment, relevant on @e age_conflict. */ - struct TALER_ExchangeSigningKeyValidityPS issue; + struct TALER_AgeCommitmentHash h_age_commitment; + /** + * True if the coin was known previously. + */ + bool existed; + + /** + * True if the known coin has a different denomination; + * application will find denomination of the already + * known coin in @e denom_hash. + */ + bool denom_conflict; + + /** + * Indicates if and what kind of conflict with the age + * restriction of the known coin was present; + * application will find age commitment of the already + * known coin in @e h_age_commitment. + */ + enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict age_conflict; }; /** * Information about a denomination key. */ -struct TALER_EXCHANGEDB_DenominationKeyInformationP +struct TALER_EXCHANGEDB_DenominationKeyInformation { /** @@ -67,14 +109,91 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP struct TALER_MasterSignatureP signature; /** - * Signed properties of the denomination key. + * Start time of the validity period for this key. */ - struct TALER_DenominationKeyValidityPS properties; + struct GNUNET_TIME_Timestamp start; + + /** + * The exchange will sign fresh coins between @e start and this time. + * @e expire_withdraw will be somewhat larger than @e start to + * ensure a sufficiently large anonymity set, while also allowing + * the Exchange to limit the financial damage in case of a key being + * compromised. Thus, exchanges with low volume are expected to have a + * longer withdraw period (@e expire_withdraw - @e start) than exchanges + * with high transaction volume. The period may also differ between + * types of coins. A exchange may also have a few denomination keys + * with the same value with overlapping validity periods, to address + * issues such as clock skew. + */ + struct GNUNET_TIME_Timestamp expire_withdraw; + + /** + * Coins signed with the denomination key must be spent or refreshed + * between @e start and this expiration time. After this time, the + * exchange will refuse transactions involving this key as it will + * "drop" the table with double-spending information (shortly after) + * this time. Note that wallets should refresh coins significantly + * before this time to be on the safe side. @e expire_deposit must be + * significantly larger than @e expire_withdraw (by months or even + * years). + */ + struct GNUNET_TIME_Timestamp expire_deposit; + + /** + * When do signatures with this denomination key become invalid? + * After this point, these signatures cannot be used in (legal) + * disputes anymore, as the Exchange is then allowed to destroy its side + * of the evidence. @e expire_legal is expected to be significantly + * larger than @e expire_deposit (by a year or more). + */ + struct GNUNET_TIME_Timestamp expire_legal; + + /** + * The value of the coins signed with this denomination key. + */ + struct TALER_Amount value; + + /** + * Fees for the coin. + */ + struct TALER_DenomFeeSet fees; + + /** + * Hash code of the denomination public key. (Used to avoid having + * the variable-size RSA key in this struct.) + */ + struct TALER_DenominationHashP denom_hash; + + /** + * If denomination was setup for age restriction, non-zero age mask. + * Note that the mask is not part of the signature. + */ + struct TALER_AgeMask age_mask; }; +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Events signalling that a coin deposit status + * changed. + */ +struct TALER_CoinDepositEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_DEPOSIT_STATUS_CHANGED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the merchant. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + +}; + /** - * Signature of events signalling a reserve got funding. + * Events signalling a reserve got funding. */ struct TALER_ReserveEventP { @@ -91,6 +210,24 @@ struct TALER_ReserveEventP /** + * Signature of events signalling a purse changed its status. + */ +struct TALER_PurseEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_PURSE_MERGED or + * #TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the purse the event is about. + */ + struct TALER_PurseContractPublicKeyP purse_pub; +}; + + +/** * Signature of events signalling a KYC process was completed. */ struct TALER_KycCompletedEventP @@ -103,7 +240,7 @@ struct TALER_KycCompletedEventP /** * Public key of the reserve the event is about. */ - struct TALER_PaytoHash h_payto; + struct TALER_PaytoHashP h_payto; }; @@ -117,12 +254,12 @@ struct TALER_EXCHANGEDB_SignkeyMetaData /** * Start time of the validity period for this key. */ - struct GNUNET_TIME_Absolute start; + struct GNUNET_TIME_Timestamp start; /** * The exchange will sign messages with this key between @e start and this time. */ - struct GNUNET_TIME_Absolute expire_sign; + struct GNUNET_TIME_Timestamp expire_sign; /** * When do signatures with this sign key become invalid? @@ -131,7 +268,7 @@ struct TALER_EXCHANGEDB_SignkeyMetaData * of the evidence. @e expire_legal is expected to be significantly * larger than @e expire_sign (by a year or more). */ - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp expire_legal; }; @@ -142,12 +279,17 @@ struct TALER_EXCHANGEDB_SignkeyMetaData */ enum TALER_EXCHANGEDB_ReplicatedTable { + /* From exchange-0002.sql: */ TALER_EXCHANGEDB_RT_DENOMINATIONS, TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS, TALER_EXCHANGEDB_RT_WIRE_TARGETS, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_REQUIREMENTS, TALER_EXCHANGEDB_RT_RESERVES, TALER_EXCHANGEDB_RT_RESERVES_IN, TALER_EXCHANGEDB_RT_RESERVES_CLOSE, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS, TALER_EXCHANGEDB_RT_RESERVES_OUT, TALER_EXCHANGEDB_RT_AUDITORS, TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS, @@ -157,13 +299,36 @@ enum TALER_EXCHANGEDB_ReplicatedTable TALER_EXCHANGEDB_RT_REFRESH_COMMITMENTS, TALER_EXCHANGEDB_RT_REFRESH_REVEALED_COINS, TALER_EXCHANGEDB_RT_REFRESH_TRANSFER_KEYS, - TALER_EXCHANGEDB_RT_DEPOSITS, + TALER_EXCHANGEDB_RT_BATCH_DEPOSITS, + TALER_EXCHANGEDB_RT_COIN_DEPOSITS, TALER_EXCHANGEDB_RT_REFUNDS, TALER_EXCHANGEDB_RT_WIRE_OUT, TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING, TALER_EXCHANGEDB_RT_WIRE_FEE, + TALER_EXCHANGEDB_RT_GLOBAL_FEE, TALER_EXCHANGEDB_RT_RECOUP, - TALER_EXCHANGEDB_RT_RECOUP_REFRESH + TALER_EXCHANGEDB_RT_RECOUP_REFRESH, + TALER_EXCHANGEDB_RT_EXTENSIONS, + TALER_EXCHANGEDB_RT_POLICY_DETAILS, + TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS, + TALER_EXCHANGEDB_RT_PURSE_REQUESTS, + TALER_EXCHANGEDB_RT_PURSE_DECISION, + TALER_EXCHANGEDB_RT_PURSE_MERGES, + TALER_EXCHANGEDB_RT_PURSE_DEPOSITS, + TALER_EXCHANGEDB_RT_ACCOUNT_MERGES, + TALER_EXCHANGEDB_RT_HISTORY_REQUESTS, + TALER_EXCHANGEDB_RT_CLOSE_REQUESTS, + TALER_EXCHANGEDB_RT_WADS_OUT, + TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES, + TALER_EXCHANGEDB_RT_WADS_IN, + TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES, + TALER_EXCHANGEDB_RT_PROFIT_DRAINS, + /* From exchange-0003.sql: */ + TALER_EXCHANGEDB_RT_AML_STAFF, + TALER_EXCHANGEDB_RT_AML_HISTORY, + TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, + TALER_EXCHANGEDB_RT_PURSE_DELETION, + TALER_EXCHANGEDB_RT_AGE_WITHDRAW, }; @@ -194,18 +359,15 @@ struct TALER_EXCHANGEDB_TableData struct { uint32_t denom_type; - uint32_t age_restrictions; + uint32_t age_mask; struct TALER_DenominationPublicKey denom_pub; struct TALER_MasterSignatureP master_sig; - struct GNUNET_TIME_Absolute valid_from; - struct GNUNET_TIME_Absolute expire_withdraw; - struct GNUNET_TIME_Absolute expire_deposit; - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp valid_from; + struct GNUNET_TIME_Timestamp expire_withdraw; + struct GNUNET_TIME_Timestamp expire_deposit; + struct GNUNET_TIME_Timestamp expire_legal; struct TALER_Amount coin; - struct TALER_Amount fee_withdraw; - struct TALER_Amount fee_deposit; - struct TALER_Amount fee_refresh; - struct TALER_Amount fee_refund; + struct TALER_DenomFeeSet fees; } denominations; struct @@ -217,49 +379,79 @@ struct TALER_EXCHANGEDB_TableData struct { char *payto_uri; - bool kyc_ok; - char *external_id; } wire_targets; struct { + struct TALER_PaytoHashP h_payto; + struct GNUNET_TIME_Timestamp expiration_time; + char *provider_section; + char *provider_user_id; + char *provider_legitimization_id; + } legitimization_processes; + + struct + { + struct TALER_PaytoHashP h_payto; struct TALER_ReservePublicKeyP reserve_pub; - /** - * Note: not useful for auditor, because not UPDATEd! - */ - struct TALER_Amount current_balance; - struct GNUNET_TIME_Absolute expiration_date; - struct GNUNET_TIME_Absolute gc_date; + bool no_reserve_pub; + char *required_checks; + } legitimization_requirements; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp expiration_date; + struct GNUNET_TIME_Timestamp gc_date; } reserves; struct { uint64_t wire_reference; struct TALER_Amount credit; - uint64_t sender_account; + struct TALER_PaytoHashP sender_account_h_payto; char *exchange_account_section; - struct GNUNET_TIME_Absolute execution_date; - uint64_t reserve_uuid; + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_ReservePublicKeyP reserve_pub; } reserves_in; struct { - uint64_t reserve_uuid; - struct GNUNET_TIME_Absolute execution_date; + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp request_timestamp; + struct GNUNET_TIME_Timestamp expiration_date; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount reserve_payment; + uint32_t requested_purse_limit; + } reserves_open_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount contribution; + } reserves_open_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp execution_date; struct TALER_WireTransferIdentifierRawP wtid; - uint64_t wire_target_serial_id; + struct TALER_PaytoHashP sender_account_h_payto; struct TALER_Amount amount; struct TALER_Amount closing_fee; } reserves_close; struct { - struct TALER_BlindedCoinHash h_blind_ev; + struct TALER_BlindedCoinHashP h_blind_ev; uint64_t denominations_serial; struct TALER_BlindedDenominationSignature denom_sig; uint64_t reserve_uuid; struct TALER_ReserveSignatureP reserve_sig; - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; struct TALER_Amount amount_with_fee; } reserves_out; @@ -269,7 +461,7 @@ struct TALER_EXCHANGEDB_TableData char *auditor_url; char *auditor_name; bool is_active; - struct GNUNET_TIME_Absolute last_change; + struct GNUNET_TIME_Timestamp last_change; } auditors; struct @@ -295,7 +487,7 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_AgeHash age_hash; + struct TALER_AgeCommitmentHash age_hash; uint64_t denominations_serial; struct TALER_DenominationSignature denom_sig; } known_coins; @@ -303,7 +495,7 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_RefreshCommitmentP rc; - uint64_t old_known_coin_id; + struct TALER_CoinSpendPublicKeyP old_coin_pub; struct TALER_CoinSpendSignatureP old_coin_sig; struct TALER_Amount amount_with_fee; uint32_t noreveal_index; @@ -317,6 +509,7 @@ struct TALER_EXCHANGEDB_TableData uint64_t denominations_serial; void *coin_ev; size_t coin_ev_size; + struct TALER_ExchangeWithdrawValues ewv; // h_coin_ev omitted, to be recomputed! struct TALER_BlindedDenominationSignature ev_sig; } refresh_revealed_coins; @@ -331,26 +524,33 @@ struct TALER_EXCHANGEDB_TableData struct { uint64_t shard; - uint64_t known_coin_id; - struct TALER_Amount amount_with_fee; - struct GNUNET_TIME_Absolute wallet_timestamp; - struct GNUNET_TIME_Absolute exchange_timestamp; - struct GNUNET_TIME_Absolute refund_deadline; - struct GNUNET_TIME_Absolute wire_deadline; struct TALER_MerchantPublicKeyP merchant_pub; - struct TALER_PrivateContractHash h_contract_terms; + struct GNUNET_TIME_Timestamp wallet_timestamp; + struct GNUNET_TIME_Timestamp exchange_timestamp; + struct GNUNET_TIME_Timestamp refund_deadline; + struct GNUNET_TIME_Timestamp wire_deadline; + struct TALER_PrivateContractHashP h_contract_terms; + struct GNUNET_HashCode wallet_data_hash; + bool no_wallet_data_hash; + struct TALER_WireSaltP wire_salt; + struct TALER_PaytoHashP wire_target_h_payto; + bool policy_blocked; + uint64_t policy_details_serial_id; + bool no_policy_details; + } batch_deposits; + + struct + { + uint64_t batch_deposit_serial_id; + struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; - struct TALER_WireSalt wire_salt; - uint64_t wire_target_serial_id; - bool tiny; - bool done; - bool extension_blocked; - uint64_t extension_details_serial_id; - } deposits; + struct TALER_Amount amount_with_fee; + } coin_deposits; struct { - uint64_t deposit_serial_id; + struct TALER_CoinSpendPublicKeyP coin_pub; + uint64_t batch_deposit_serial_id; struct TALER_MerchantSignatureP merchant_sig; uint64_t rtransaction_id; struct TALER_Amount amount_with_fee; @@ -358,49 +558,265 @@ struct TALER_EXCHANGEDB_TableData struct { - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; struct TALER_WireTransferIdentifierRawP wtid_raw; - uint64_t wire_target_serial_id; + struct TALER_PaytoHashP wire_target_h_payto; char *exchange_account_section; struct TALER_Amount amount; } wire_out; struct { - uint64_t deposit_serial_id; + uint64_t batch_deposit_serial_id; struct TALER_WireTransferIdentifierRawP wtid_raw; } aggregation_tracking; struct { char *wire_method; - struct GNUNET_TIME_Absolute start_date; - struct GNUNET_TIME_Absolute end_date; - struct TALER_Amount wire_fee; - struct TALER_Amount closing_fee; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_WireFeeSet fees; struct TALER_MasterSignatureP master_sig; } wire_fee; struct { - uint64_t known_coin_id; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_GlobalFeeSet fees; + struct GNUNET_TIME_Relative purse_timeout; + struct GNUNET_TIME_Relative history_expiration; + uint32_t purse_account_limit; + struct TALER_MasterSignatureP master_sig; + } global_fee; + + struct + { + struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; struct TALER_Amount amount; - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; uint64_t reserve_out_serial_id; } recoup; struct { uint64_t known_coin_id; + struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendSignatureP coin_sig; - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; struct TALER_Amount amount; - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; uint64_t rrc_serial; } recoup_refresh; + struct + { + char *name; + char *manifest; + } extensions; + + struct + { + struct GNUNET_HashCode hash_code; + json_t *policy_json; + bool no_policy_json; + struct GNUNET_TIME_Timestamp deadline; + struct TALER_Amount commitment; + struct TALER_Amount accumulated_total; + struct TALER_Amount fee; + struct TALER_Amount transferable; + uint16_t fulfillment_state; /* will also be recomputed */ + uint64_t fulfillment_id; + bool no_fulfillment_id; + } policy_details; + + struct + { + struct GNUNET_TIME_Timestamp fulfillment_timestamp; + char *fulfillment_proof; + struct GNUNET_HashCode h_fulfillment_proof; + struct GNUNET_HashCode *policy_hash_codes; + size_t policy_hash_codes_count; + } policy_fulfillments; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergePublicKeyP merge_pub; + struct GNUNET_TIME_Timestamp purse_creation; + struct GNUNET_TIME_Timestamp purse_expiration; + struct TALER_PrivateContractHashP h_contract_terms; + uint32_t age_limit; + uint32_t flags; + struct TALER_Amount amount_with_fee; + struct TALER_Amount purse_fee; + struct TALER_PurseContractSignatureP purse_sig; + } purse_requests; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct GNUNET_TIME_Timestamp action_timestamp; + bool refunded; + } purse_decision; + + struct + { + uint64_t partner_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergeSignatureP merge_sig; + struct GNUNET_TIME_Timestamp merge_timestamp; + } purse_merges; + + struct + { + uint64_t partner_serial_id; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_Amount amount_with_fee; + struct TALER_CoinSpendSignatureP coin_sig; + } purse_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PaytoHashP wallet_h_payto; + } account_merges; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct GNUNET_TIME_Timestamp request_timestamp; + struct TALER_Amount history_fee; + } history_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp close_timestamp; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount close; + struct TALER_Amount close_fee; + char *payto_uri; + } close_requests; + + struct + { + struct TALER_WadIdentifierP wad_id; + uint64_t partner_serial_id; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp execution_time; + } wads_out; + + struct + { + uint64_t wad_out_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_out_entries; + + struct + { + struct TALER_WadIdentifierP wad_id; + char *origin_exchange_url; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp arrival_time; + } wads_in; + + struct + { + uint64_t wad_in_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_in_entries; + + struct + { + struct TALER_WireTransferIdentifierRawP wtid; + char *account_section; + char *payto_uri; + struct GNUNET_TIME_Timestamp trigger_date; + struct TALER_Amount amount; + struct TALER_MasterSignatureP master_sig; + } profit_drains; + + struct + { + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_MasterSignatureP master_sig; + char *decider_name; + bool is_active; + bool read_only; + struct GNUNET_TIME_Timestamp last_change; + } aml_staff; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_Amount new_threshold; + enum TALER_AmlDecisionState new_status; + struct GNUNET_TIME_Timestamp decision_time; + char *justification; + char *kyc_requirements; /* NULL allowed! */ + uint64_t kyc_req_row; + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_AmlOfficerSignatureP decider_sig; + } aml_history; + + struct + { + struct TALER_PaytoHashP h_payto; + struct GNUNET_ShortHashCode kyc_prox; + char *provider; + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + void *encrypted_attributes; + size_t encrypted_attributes_size; + } kyc_attributes; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseContractSignatureP purse_sig; + } purse_deletion; + + struct + { + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + struct TALER_Amount amount_with_fee; + uint16_t max_age; + uint32_t noreveal_index; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint64_t num_coins; + uint64_t *denominations_serials; + void *h_blind_evs; + struct TALER_BlindedDenominationSignature denom_sigs; + } age_withdraw; + } details; }; @@ -442,7 +858,7 @@ struct TALER_EXCHANGEDB_DenominationKey /** * Signed public information about a denomination key. */ - struct TALER_EXCHANGEDB_DenominationKeyInformationP issue; + struct TALER_EXCHANGEDB_DenominationKeyInformation issue; }; @@ -467,7 +883,7 @@ struct TALER_EXCHANGEDB_BankTransfer * (This is the execution date of the exchange's database, * the execution date of the bank should be in @e wire). */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Detailed wire information about the sending account @@ -496,7 +912,7 @@ struct TALER_EXCHANGEDB_ClosingTransfer struct TALER_ReservePublicKeyP reserve_pub; /** - * Amount that was transferred to the exchange. + * Amount that was transferred from the exchange. */ struct TALER_Amount amount; @@ -508,7 +924,7 @@ struct TALER_EXCHANGEDB_ClosingTransfer /** * When did the exchange execute the transaction? */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Detailed wire information about the receiving account @@ -544,13 +960,13 @@ struct TALER_EXCHANGEDB_Reserve * The expiration date of this reserve; funds will be wired back * at this time. */ - struct GNUNET_TIME_Absolute expiry; + struct GNUNET_TIME_Timestamp expiry; /** * The legal expiration date of this reserve; we will forget about * it at this time. */ - struct GNUNET_TIME_Absolute gc; + struct GNUNET_TIME_Timestamp gc; }; @@ -560,9 +976,16 @@ struct TALER_EXCHANGEDB_Reserve struct TALER_EXCHANGEDB_DenominationKeyMetaData { /** - * Start time of the validity period for this key. - */ - struct GNUNET_TIME_Absolute start; + * Serial of the denomination key as in the DB. + * Can be used in calls to stored procedures in order to spare + * additional lookups. + */ + uint64_t serial; + + /** + * Start time of the validity period for this key. + */ + struct GNUNET_TIME_Timestamp start; /** * The exchange will sign fresh coins between @e start and this time. @@ -576,7 +999,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData * with the same value with overlapping validity periods, to address * issues such as clock skew. */ - struct GNUNET_TIME_Absolute expire_withdraw; + struct GNUNET_TIME_Timestamp expire_withdraw; /** * Coins signed with the denomination key must be spent or refreshed @@ -588,7 +1011,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData * significantly larger than @e expire_withdraw (by months or even * years). */ - struct GNUNET_TIME_Absolute expire_deposit; + struct GNUNET_TIME_Timestamp expire_deposit; /** * When do signatures with this denomination key become invalid? @@ -597,7 +1020,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData * of the evidence. @e expire_legal is expected to be significantly * larger than @e expire_deposit (by a year or more). */ - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp expire_legal; /** * The value of the coins signed with this denomination key. @@ -605,29 +1028,10 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData struct TALER_Amount value; /** - * The fee the exchange charges when a coin of this type is withdrawn. - * (can be zero). + * The fees the exchange charges for operations with + * coins of this denomination. */ - struct TALER_Amount fee_withdraw; - - /** - * The fee the exchange charges when a coin of this type is deposited. - * (can be zero). - */ - struct TALER_Amount fee_deposit; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_Amount fee_refresh; - - /** - * The fee the exchange charges when a coin of this type is refunded. - * (can be zero). Note that refund fees are charged to the customer; - * if a refund is given, the deposit fee is also refunded. - */ - struct TALER_Amount fee_refund; + struct TALER_DenomFeeSet fees; /** * Age restriction for the denomination. (can be zero). If not zero, the bits @@ -643,7 +1047,7 @@ struct TALER_EXCHANGEDB_DenominationKeyMetaData * A value of 0 means that the denomination does not support the extension for * age-restriction. */ - struct TALER_AgeMask age_restrictions; + struct TALER_AgeMask age_mask; }; @@ -663,7 +1067,7 @@ typedef void (*TALER_EXCHANGEDB_DenominationsCallback)( void *cls, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, const struct TALER_MasterSignatureP *master_sig, bool recoup_possible); @@ -687,6 +1091,39 @@ typedef void /** + * Function called on all KYC process names that the given + * account has already passed. + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + */ +typedef void +(*TALER_EXCHANGEDB_SatisfiedProviderCallback)( + void *cls, + const char *kyc_provider_section_name); + + +/** + * Function called on all legitimization operations + * we have performed for the given account so far + * (and that have not yet expired). + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + * @param provider_user_id UID at a provider (can be NULL) + * @param legi_id legitimization process ID (can be NULL) + */ +typedef void +(*TALER_EXCHANGEDB_LegitimizationProcessCallback)( + void *cls, + const char *kyc_provider_section_name, + const char *provider_user_id, + const char *legi_id); + + +/** * Function called with information about the exchange's auditors. * * @param cls closure with a `struct TEH_KeyStateHandle *` @@ -715,7 +1152,7 @@ typedef void (*TALER_EXCHANGEDB_AuditorDenominationsCallback)( void *cls, const struct TALER_AuditorPublicKeyP *auditor_pub, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_AuditorSignatureP *auditor_sig); @@ -735,7 +1172,7 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin /** * Hash of the denomination key (which coin was generated). */ - struct TALER_DenominationHash denom_pub_hash; + struct TALER_DenominationHashP denom_pub_hash; /** * Value of the coin being exchangeed (matching the denomination key) @@ -768,7 +1205,7 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin * Hash over the blinded message, needed to verify * the @e reserve_sig. */ - struct TALER_BlindedCoinHash h_coin_envelope; + struct TALER_BlindedCoinHashP h_coin_envelope; /** * Signature confirming the withdrawal, matching @e reserve_pub, @@ -779,6 +1216,79 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin /** + * @brief Information we keep for an age-withdraw request + * to reproduce the /age-withdraw operation if needed, and to have proof + * that a reserve was drained by this amount. + */ +struct TALER_EXCHANGEDB_AgeWithdraw +{ + /** + * Total amount (with fee) committed to withdraw + */ + struct TALER_Amount amount_with_fee; + + /** + * Maximum age (in years) that the coins are restricted to. + */ + uint16_t max_age; + + /** + * The hash of the commitment of all n*kappa coins + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not have + * revealed during cut and choose. This value applies to all n coins in the + * commitment. + */ + uint16_t noreveal_index; + + /** + * Public key of the reserve that was drained. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Signature confirming the age withdrawal commitment, matching @e + * reserve_pub, @e max_age and @e h_commitment and @e amount_with_fee. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Number of coins to be withdrawn. + */ + size_t num_coins; + + /** + * Array of @a num_coins blinded coins. These are the chosen coins + * (according to @a noreveal_index) from the request, which contained + * kappa*num_coins blinded coins. + */ + struct TALER_BlindedCoinHashP *h_coin_evs; + + /** + * Array of @a num_coins denomination signatures of the blinded coins @a + * h_coin_evs. + */ + struct TALER_BlindedDenominationSignature *denom_sigs; + + /** + * Array of @a num_coins serial id's of the denominations, corresponding to + * the coins in @a h_coin_evs. + */ + uint64_t *denom_serials; + + /** + * [out]-Array of @a num_coins hashes of the public keys of the denominations + * identified by @e denom_serials. This field is set when calling + * get_age_withdraw + */ + struct TALER_DenominationHashP *denom_pub_hashes; +}; + + +/** * Information the exchange records about a recoup request * in a reserve history. */ @@ -794,7 +1304,7 @@ struct TALER_EXCHANGEDB_Recoup * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -815,12 +1325,29 @@ struct TALER_EXCHANGEDB_Recoup /** * When did the recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; }; /** + * Public key to which a nonce is locked. + */ +union TALER_EXCHANGEDB_NonceLockTargetP +{ + /** + * Nonce is locked to this coin key. + */ + struct TALER_CoinSpendPublicKeyP coin; + + /** + * Nonce is locked to this reserve key. + */ + struct TALER_ReservePublicKeyP reserve; +}; + + +/** * Information the exchange records about a recoup request * in a coin history. */ @@ -831,7 +1358,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -842,7 +1369,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry /** * Hash of the public denomination key used to sign the coin. */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_DenominationHashP h_denom_pub; /** * Public key of the reserve the coin was paid back into. @@ -857,7 +1384,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry /** * When did the /recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; }; @@ -879,7 +1406,7 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry * Blinding factor supplied to prove to the exchange that * the coin came from this @e old_coin_pub. */ - union TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -900,7 +1427,174 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry /** * When did the recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; + +}; + + +/** + * Details about a purse merge operation. + */ +struct TALER_EXCHANGEDB_PurseMerge +{ + + /** + * Public key of the reserve the coin was merged into. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Amount in the purse, with fees. + */ + struct TALER_Amount amount_with_fee; + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * When was the purse set to expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * Minimum age required for depositing into the purse. + */ + uint32_t min_age; + + /** + * Flags of the purse. + */ + enum TALER_WalletAccountMergeFlags flags; + + /** + * true if the purse was actually successfully merged, + * false if the @e purse_fee was charged but the + * @e amount was not credited to the reserve. + */ + bool merged; +}; + + +/** + * Details about a (paid for) reserve history request. + */ +struct TALER_EXCHANGEDB_HistoryRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request. + */ + struct TALER_Amount history_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; +}; + + +/** + * Details about a (paid for) reserve open request. + */ +struct TALER_EXCHANGEDB_OpenRequest +{ + /** + * Public key of the reserve the open request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request from the reserve. + */ + struct TALER_Amount open_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * How long was the reserve supposed to be open. + */ + struct GNUNET_TIME_Timestamp reserve_expiration; + + /** + * Signature by the reserve approving the open request, + * with purpose #TALER_SIGNATURE_WALLET_RESERVE_OPEN. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * How many open purses should be included with the + * open reserve? + */ + uint32_t purse_limit; + +}; + + +/** + * Details about an (explicit) reserve close request. + */ +struct TALER_EXCHANGEDB_CloseRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; }; @@ -931,7 +1625,27 @@ enum TALER_EXCHANGEDB_ReserveOperation * customer's bank account. This happens when the exchange * closes a reserve with a non-zero amount left in it. */ - TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3 + TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3, + + /** + * Event where a purse was merged into a reserve. + */ + TALER_EXCHANGEDB_RO_PURSE_MERGE = 4, + + /** + * Event where a wallet paid for a full reserve history. + */ + TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5, + + /** + * Event where a wallet paid to open a reserve for longer. + */ + TALER_EXCHANGEDB_RO_OPEN_REQUEST = 6, + + /** + * Event where a wallet requested a reserve to be closed. + */ + TALER_EXCHANGEDB_RO_CLOSE_REQUEST = 7 }; @@ -982,12 +1696,156 @@ struct TALER_EXCHANGEDB_ReserveHistory */ struct TALER_EXCHANGEDB_ClosingTransfer *closing; + /** + * Details about a purse merge operation. + */ + struct TALER_EXCHANGEDB_PurseMerge *merge; + + /** + * Details about a (paid for) reserve history request. + */ + struct TALER_EXCHANGEDB_HistoryRequest *history; + + /** + * Details about a (paid for) open reserve request. + */ + struct TALER_EXCHANGEDB_OpenRequest *open_request; + + /** + * Details about an (explicit) reserve close request. + */ + struct TALER_EXCHANGEDB_CloseRequest *close_request; + } details; }; /** + * @brief Data about a coin for a deposit operation. + */ +struct TALER_EXCHANGEDB_CoinDepositInformation +{ + /** + * Information about the coin that is being deposited. + */ + struct TALER_CoinPublicInfo coin; + + /** + * ECDSA signature affirming that the customer intends + * this coin to be deposited at the merchant identified + * by @e h_wire in relation to the proposal data identified + * by @e h_contract_terms. + */ + struct TALER_CoinSpendSignatureP csig; + + /** + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount_with_fee; + +}; + + +/** + * @brief Data from a batch deposit operation. + */ +struct TALER_EXCHANGEDB_BatchDeposit +{ + + /** + * Public key of the merchant. Enables later identification + * of the merchant in case of a need to rollback transactions. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Hash over the proposal data between merchant and customer + * (remains unknown to the Exchange). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Hash over additional inputs by the wallet. + */ + struct GNUNET_HashCode wallet_data_hash; + + /** + * Unsalted hash over @e receiver_wire_account. + */ + struct TALER_PaytoHashP wire_target_h_payto; + + /** + * Salt used by the merchant to compute "h_wire". + */ + struct TALER_WireSaltP wire_salt; + + /** + * Time when this request was generated. Used, for example, to + * assess when (roughly) the income was achieved for tax purposes. + * Note that the Exchange will only check that the timestamp is not "too + * far" into the future (i.e. several days). The fact that the + * timestamp falls within the validity period of the coin's + * denomination key is irrelevant for the validity of the deposit + * request, as obviously the customer and merchant could conspire to + * set any timestamp. Also, the Exchange must accept very old deposit + * requests, as the merchant might have been unable to transmit the + * deposit request in a timely fashion (so back-dating is not + * prevented). + */ + struct GNUNET_TIME_Timestamp wallet_timestamp; + + /** + * How much time does the merchant have to issue a refund request? + * Zero if refunds are not allowed. After this time, the coin + * cannot be refunded. + */ + struct GNUNET_TIME_Timestamp refund_deadline; + + /** + * How much time does the merchant have to execute the wire transfer? + * This time is advisory for aggregating transactions, not a hard + * constraint (as the merchant can theoretically pick any time, + * including one in the past). + */ + struct GNUNET_TIME_Timestamp wire_deadline; + + /** + * Row ID of the policy details; 0 if no policy applies. + */ + uint64_t policy_details_serial_id; + + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + const char *receiver_wire_account; + + /** + * Array about the coins that are being deposited. + */ + const struct TALER_EXCHANGEDB_CoinDepositInformation *cdis; + + /** + * Length of the @e cdis array. + */ + unsigned int num_cdis; + + /** + * False if @e wallet_data_hash was provided + */ + bool no_wallet_data_hash; + + /** + * True if further processing is blocked by policy. + */ + bool policy_blocked; + +}; + + +/** * @brief Data from a deposit operation. The combination of * the coin's public key, the merchant's public key and the * transaction ID must be unique. While a coin can (theoretically) be @@ -1022,24 +1880,23 @@ struct TALER_EXCHANGEDB_Deposit * Hash over the proposal data between merchant and customer * (remains unknown to the Exchange). */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Salt used by the merchant to compute "h_wire". */ - struct TALER_WireSalt wire_salt; + struct TALER_WireSaltP wire_salt; /** - * Information about the receiver for executing the transaction. URI in - * payto://-format. + * Hash over inputs from the wallet to customize the contract. */ - char *receiver_wire_account; + struct GNUNET_HashCode wallet_data_hash; /** - * Additional details for extensions relevant for this - * deposit operation. + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature */ - json_t *extension_details; + struct TALER_ExtensionPolicyHashP h_policy; /** * Time when this request was generated. Used, for example, to @@ -1054,14 +1911,14 @@ struct TALER_EXCHANGEDB_Deposit * deposit request in a timely fashion (so back-dating is not * prevented). */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * How much time does the merchant have to issue a refund request? * Zero if refunds are not allowed. After this time, the coin * cannot be refunded. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct GNUNET_TIME_Timestamp refund_deadline; /** * How much time does the merchant have to execute the wire transfer? @@ -1069,7 +1926,7 @@ struct TALER_EXCHANGEDB_Deposit * constraint (as the merchant can theoretically pick any time, * including one in the past). */ - struct GNUNET_TIME_Absolute wire_deadline; + struct GNUNET_TIME_Timestamp wire_deadline; /** * Fraction of the coin's remaining value to be deposited, including @@ -1082,6 +1939,22 @@ struct TALER_EXCHANGEDB_Deposit */ struct TALER_Amount deposit_fee; + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + char *receiver_wire_account; + + /** + * True if @e policy_json was provided + */ + bool has_policy; + + /** + * True if @e wallet_data_hash is not in use. + */ + bool no_wallet_data_hash; + }; @@ -1110,23 +1983,45 @@ struct TALER_EXCHANGEDB_DepositListEntry * Hash over the proposa data between merchant and customer * (remains unknown to the Exchange). */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Hash over inputs from the wallet to customize the contract. + */ + struct GNUNET_HashCode wallet_data_hash; /** * Hash of the public denomination key used to sign the coin. */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_DenominationHashP h_denom_pub; /** - * Detailed information about the receiver for executing the transaction. - * URL in payto://-format. + * Age commitment hash, if applicable to the denomination. Should be all + * zeroes if age commitment is not applicable to the denonimation. */ - char *receiver_wire_account; + struct TALER_AgeCommitmentHash h_age_commitment; /** * Salt used to compute h_wire from the @e receiver_wire_account. */ - struct TALER_WireSalt wire_salt; + struct TALER_WireSaltP wire_salt; + + /** + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature + */ + struct TALER_ExtensionPolicyHashP h_policy; + + /** + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount_with_fee; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; /** * Time when this request was generated. Used, for example, to @@ -1141,14 +2036,14 @@ struct TALER_EXCHANGEDB_DepositListEntry * deposit request in a timely fashion (so back-dating is not * prevented). */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * How much time does the merchant have to issue a refund request? * Zero if refunds are not allowed. After this time, the coin * cannot be refunded. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct GNUNET_TIME_Timestamp refund_deadline; /** * How much time does the merchant have to execute the wire transfer? @@ -1156,18 +2051,28 @@ struct TALER_EXCHANGEDB_DepositListEntry * constraint (as the merchant can theoretically pick any time, * including one in the past). */ - struct GNUNET_TIME_Absolute wire_deadline; + struct GNUNET_TIME_Timestamp wire_deadline; /** - * Fraction of the coin's remaining value to be deposited, including - * depositing fee (if any). The coin is identified by @e coin_pub. + * Detailed information about the receiver for executing the transaction. + * URL in payto://-format. */ - struct TALER_Amount amount_with_fee; + char *receiver_wire_account; /** - * Depositing fee. + * true, if age commitment is not applicable */ - struct TALER_Amount deposit_fee; + bool no_age_commitment; + + /** + * true, if wallet data hash is not present + */ + bool no_wallet_data_hash; + + /** + * True if a policy was provided with the deposit request + */ + bool has_policy; /** * Has the deposit been wired? @@ -1197,7 +2102,7 @@ struct TALER_EXCHANGEDB_RefundListEntry * Hash over the proposal data between merchant and customer * (remains unknown to the Exchange). */ - struct TALER_PrivateContractHash h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Merchant-generated REFUND transaction ID to detect duplicate @@ -1303,7 +2208,19 @@ struct TALER_EXCHANGEDB_MeltListEntry /** * Hash of the public denomination key used to sign the coin. */ - struct TALER_DenominationHash h_denom_pub; + struct TALER_DenominationHashP h_denom_pub; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. May be all zeroes if no age restriction + * applies. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * true, if no h_age_commitment is applicable + */ + bool no_age_commitment; /** * How much value is being melted? This amount includes the fees, @@ -1330,6 +2247,158 @@ struct TALER_EXCHANGEDB_MeltListEntry /** + * Information about a /purses/$PID/deposit operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_PurseDepositListEntry +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if the coin was refunded. + */ + bool refunded; + + /** + * Set to true if there was no age commitment. + */ + bool no_age_commitment; + +}; + + +/** + * @brief Specification for a purse refund operation in a coin's transaction list. + */ +struct TALER_EXCHANGEDB_PurseRefundListEntry +{ + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Fraction of the original deposit's value to be refunded, including + * refund fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount refund_amount; + + /** + * Refund fee to be covered by the customer. + */ + struct TALER_Amount refund_fee; + +}; + + +/** + * Information about a /reserves/$RID/open operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_ReserveOpenListEntry +{ + + /** + * Signature of the reserve. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Contribution of the coin to the open fee, including + * deposit fee. + */ + struct TALER_Amount coin_contribution; + + /** + * Signature by the coin affirming the open deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + +}; + + +/** + * Information about a /purses/$PID/deposit operation. + */ +struct TALER_EXCHANGEDB_PurseDeposit +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Public key of the coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. May be all zeroes if no age restriction + * applies. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if @e h_age_commitment is not available. + */ + bool no_age_commitment; + +}; + +/** * Information about a melt operation. */ struct TALER_EXCHANGEDB_Melt @@ -1369,11 +2438,31 @@ struct TALER_EXCHANGEDB_LinkList struct TALER_BlindedDenominationSignature ev_sig; /** + * Exchange-provided values during the coin generation. + */ + struct TALER_ExchangeWithdrawValues alg_values; + + /** * Signature of the original coin being refreshed over the * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK */ struct TALER_CoinSpendSignatureP orig_coin_link_sig; + /** + * Session nonce, if cipher has one. + */ + union GNUNET_CRYPTO_BlindSessionNonce nonce; + + /** + * Offset that generated this coin in the refresh + * operation. + */ + uint32_t coin_refresh_offset; + + /** + * Set to true if @e nonce was initialized. + */ + bool have_nonce; }; @@ -1412,7 +2501,22 @@ enum TALER_EXCHANGEDB_TransactionType /** * Recoup-refresh operation (on the new coin, eliminating its value) */ - TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5 + TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5, + + /** + * Purse deposit operation. + */ + TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6, + + /** + * Purse deposit operation. + */ + TALER_EXCHANGEDB_TT_PURSE_REFUND = 7, + + /** + * Reserve open deposit operation. + */ + TALER_EXCHANGEDB_TT_RESERVE_OPEN = 8 }; @@ -1482,61 +2586,27 @@ struct TALER_EXCHANGEDB_TransactionList */ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup_refresh; - } details; - -}; + /** + * Coin was deposited into a purse. + * (#TALER_EXCHANGEDB_TT_PURSE_DEPOSIT) + */ + struct TALER_EXCHANGEDB_PurseDepositListEntry *purse_deposit; + /** + * Coin was refunded upon purse expiration + * (#TALER_EXCHANGEDB_TT_PURSE_REFUND) + */ + struct TALER_EXCHANGEDB_PurseRefundListEntry *purse_refund; -/** - * Function called with details about deposits that have been made, - * with the goal of executing the corresponding wire transaction. - * - * @param cls closure - * @param rowid unique ID for the deposit in our DB, used for marking - * it as 'tiny' or 'done' - * @param coin_pub public key of the coin - * @param amount_with_fee amount that was deposited including fee - * @param deposit_fee amount the exchange gets to keep as transaction fees - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate - */ -typedef enum GNUNET_DB_QueryStatus -(*TALER_EXCHANGEDB_MatchingDepositIterator)( - void *cls, - uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - const struct TALER_PrivateContractHash *h_contract_terms); + /** + * Coin was used to pay to open a reserve. + * (#TALER_EXCHANGEDB_TT_RESERVE_OPEN) + */ + struct TALER_EXCHANGEDB_ReserveOpenListEntry *reserve_open; + } details; -/** - * Function called with details about deposits that have been made, - * with the goal of executing the corresponding wire transaction. - * - * @param cls closure - * @param rowid unique ID for the deposit in our DB, used for marking - * it as 'tiny' or 'done' - * @param merchant_pub public key of the merchant - * @param coin_pub public key of the coin - * @param amount_with_fee amount that was deposited including fee - * @param deposit_fee amount the exchange gets to keep as transaction fees - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @param wire_target unique ID of the receiver account - * @param payto_uri how to pay the merchant, URI in payto://-format; - * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate - */ -typedef enum GNUNET_DB_QueryStatus -(*TALER_EXCHANGEDB_DepositIterator)( - void *cls, - uint64_t rowid, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - const struct TALER_PrivateContractHash *h_contract_terms, - uint64_t wire_target, - const char *payto_uri); +}; /** @@ -1557,6 +2627,28 @@ typedef void /** + * Callback with KYC attributes about a particular user. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param provider_section provider that must be checked + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + */ +typedef void +(*TALER_EXCHANGEDB_AttributeCallback)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + struct GNUNET_TIME_Timestamp collection_time, + struct GNUNET_TIME_Timestamp expiration_time, + size_t enc_attributes_size, + const void *enc_attributes); + + +/** * Function called with details about deposits that have been made, * with the goal of auditing the deposit's execution. * @@ -1572,19 +2664,173 @@ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_DepositCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute exchange_timestamp, + struct GNUNET_TIME_Timestamp exchange_timestamp, const struct TALER_EXCHANGEDB_Deposit *deposit, const struct TALER_DenominationPublicKey *denom_pub, bool done); /** + * Function called with details about purse deposits that have been made, with + * the goal of auditing the deposit's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param deposit deposit details + * @param reserve_pub which reserve is the purse merged into, NULL if unknown + * @param flags purse flags + * @param auditor_balance purse balance (according to the + * auditor during auditing) + * @param purse_total target amount the purse should reach + * @param denom_pub denomination public key of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDepositCallback)( + void *cls, + uint64_t rowid, + const struct TALER_EXCHANGEDB_PurseDeposit *deposit, + const struct TALER_ReservePublicKeyP *reserve_pub, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *auditor_balance, + const struct TALER_Amount *purse_total, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Function called with details about + * account merge requests that have been made, with + * the goal of auditing the account merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param reserve_pub reserve affected by the merge + * @param purse_pub purse being merged + * @param h_contract_terms hash over contract of the purse + * @param purse_expiration when would the purse expire + * @param amount total amount in the purse + * @param min_age minimum age of all coins deposited into the purse + * @param flags how was the purse created + * @param purse_fee if a purse fee was paid, how high is it + * @param merge_timestamp when was the merge approved + * @param reserve_sig signature by reserve approving the merge + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_AccountMergeCallback)( + void *cls, + uint64_t rowid, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Function called with details about purse + * merges that have been made, with + * the goal of auditing the purse merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param partner_base_url where is the reserve, NULL for this exchange + * @param amount total amount expected in the purse + * @param balance current balance in the purse (according to the auditor) + * @param flags purse flags + * @param merge_pub merge capability key + * @param reserve_pub reserve the merge affects + * @param merge_sig signature affirming the merge + * @param purse_pub purse key + * @param merge_timestamp when did the merge happen + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseMergeCallback)( + void *cls, + uint64_t rowid, + const char *partner_base_url, + const struct TALER_Amount *amount, + const struct TALER_Amount *balance, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_PurseMergePublicKeyP *merge_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp merge_timestamp); + + +/** + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param purse_pub public key of the purse + * @param reserve_pub public key of the target reserve, NULL if not known / refunded + * @param purse_value what is the (target) value of the purse + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *purse_value); + + +/** + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param purse_pub public key of the purse + * @param refunded true if decision was to refund + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_AllPurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + bool refunded); + + +/** + * Function called with details about purse refunds that have been made, with + * the goal of auditing the purse refund's execution. + * + * @param cls closure + * @param rowid row of the refund event + * @param amount_with_fee amount of the deposit into the purse + * @param coin_pub coin that is to be refunded the @a given amount_with_fee + * @param denom_pub denomination of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRefundCoinCallback)( + void *cls, + uint64_t rowid, + const struct TALER_Amount *amount_with_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** * Function called with details about coins that were melted, * with the goal of auditing the refresh's execution. * * @param cls closure * @param rowid unique serial ID for the refresh session in our DB * @param denom_pub denomination public key of @a coin_pub + * @param h_age_commitment age commitment that went into the signing of the coin, may be NULL * @param coin_pub public key of the coin * @param coin_sig signature from the coin * @param amount_with_fee amount that was deposited including fee @@ -1597,6 +2843,7 @@ typedef enum GNUNET_GenericReturnValue void *cls, uint64_t rowid, const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_Amount *amount_with_fee, @@ -1625,9 +2872,9 @@ typedef enum GNUNET_GenericReturnValue struct TALER_EXCHANGEDB_RefreshRevealedCoin { /** - * Public denomination key of the coin. + * Hash of the public denomination key of the coin. */ - struct TALER_DenominationPublicKey denom_pub; + struct TALER_DenominationHashP h_denom_pub; /** * Signature of the original coin being refreshed over the @@ -1636,62 +2883,53 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin struct TALER_CoinSpendSignatureP orig_coin_link_sig; /** - * Blinded message to be signed (in envelope), with @e coin_env_size bytes. + * Hash of the blinded new coin, that is @e coin_ev. */ - char *coin_ev; - - /** - * Number of bytes in @e coin_ev. - */ - size_t coin_ev_size; + struct TALER_BlindedCoinHashP coin_envelope_hash; /** * Signature generated by the exchange over the coin (in blinded format). */ struct TALER_BlindedDenominationSignature coin_sig; -}; - - -/** - * Types of operations that require KYC checks. - */ -enum TALER_EXCHANGEDB_KycType -{ /** - * It is unclear for which type of KYC operation - * this information is. + * Values contributed from the exchange to the + * coin generation (see /csr). */ - TALER_EXCHANGEDB_KYC_UNKNOWN = 0, + struct TALER_ExchangeWithdrawValues exchange_vals; /** - * KYC to be applied for simple withdraws without - * the involvement of wallet-to-wallet payments. - * Tied to the payto:// of the debited account. + * Blinded message to be signed (in envelope). */ - TALER_EXCHANGEDB_KYC_WITHDRAW = 1, + struct TALER_BlindedPlanchet blinded_planchet; + +}; + +/** + * Information per Clause-Schnorr (CS) fresh coin to + * be persisted for idempotency during refreshes-reveal. + */ +struct TALER_EXCHANGEDB_CsRevealFreshCoinData +{ /** - * KYC to be applied for simple deposits to a - * merchant's bank account. Tied to the payto:// - * of the credited account. + * Denomination of the fresh coin. */ - TALER_EXCHANGEDB_KYC_DEPOSIT = 2, + struct TALER_DenominationHashP new_denom_pub_hash; /** - * KYC that is self-applied by a wallet that is exceeding the amount - * threshold. Tied to the reserve-account public key that identifies the - * funds-holding wallet. + * Blind signature of the fresh coin (possibly updated + * in case if a replay!). */ - TALER_EXCHANGEDB_KYC_BALANCE = 3, + struct TALER_BlindedDenominationSignature bsig; /** - * KYC that is triggered upon wallet-to-wallet - * payments for the recipient of funds. Tied to the - * reserve public key that identifies the receiving - * wallet. + * Offset of the fresh coin in the reveal operation. + * (May not match the array offset as we may have + * a mixture of RSA and CS coins being created, and + * this request is only made for the CS subset). */ - TALER_EXCHANGEDB_KYC_W2W = 4 + uint32_t coin_off; }; @@ -1701,15 +2939,10 @@ enum TALER_EXCHANGEDB_KycType struct TALER_EXCHANGEDB_KycStatus { /** - * Number that identifies the KYC target the operation + * Number that identifies the KYC requirement the operation * was about. */ - uint64_t payment_target_uuid; - - /** - * What kind of KYC operation is this? - */ - enum TALER_EXCHANGEDB_KycType type; + uint64_t requirement_row; /** * True if the KYC status is "satisfied". @@ -1719,24 +2952,48 @@ struct TALER_EXCHANGEDB_KycStatus }; +struct TALER_EXCHANGEDB_ReserveInInfo +{ + const struct TALER_ReservePublicKeyP *reserve_pub; + const struct TALER_Amount *balance; + struct GNUNET_TIME_Timestamp execution_time; + const char *sender_account_details; + const char *exchange_account_name; + uint64_t wire_reference; +}; + + +/** + * Function called on each @a amount that was found to + * be relevant for a KYC check. + * + * @param cls closure to allow the KYC module to + * total up amounts and evaluate rules + * @param amount encountered transaction amount + * @param date when was the amount encountered + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to abort iteration + * #GNUNET_SYSERR on internal error (also abort itaration) + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_KycAmountCallback)( + void *cls, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute date); + + /** * Function called with information about a refresh order. * * @param cls closure * @param num_freshcoins size of the @a rrcs array * @param rrcs array of @a num_freshcoins information about coins to be created - * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 - * @param tprivs array of @e num_tprivs transfer private keys - * @param tp transfer public key information */ typedef void (*TALER_EXCHANGEDB_RefreshCallback)( void *cls, uint32_t num_freshcoins, - const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, - unsigned int num_tprivs, - const struct TALER_TransferPrivateKeyP *tprivs, - const struct TALER_TransferPublicKeyP *tp); + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs); /** @@ -1751,6 +3008,7 @@ typedef void * @param merchant_sig signature of the merchant * @param h_contract_terms hash of the proposal data known to merchant and customer * @param rtransaction_id refund transaction ID chosen by the merchant + * @param full_refund true if the refunds total up to the entire value of the deposit * @param amount_with_fee amount that was deposited including fee * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ @@ -1762,8 +3020,9 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_MerchantSignatureP *merchant_sig, - const struct TALER_PrivateContractHash *h_contract_terms, + const struct TALER_PrivateContractHashP *h_contract_terms, uint64_t rtransaction_id, + bool full_refund, const struct TALER_Amount *amount_with_fee); @@ -1787,7 +3046,7 @@ typedef enum GNUNET_GenericReturnValue const struct TALER_Amount *credit, const char *sender_account_details, uint64_t wire_reference, - struct GNUNET_TIME_Absolute execution_date); + struct GNUNET_TIME_Timestamp execution_date); /** @@ -1795,22 +3054,31 @@ typedef enum GNUNET_GenericReturnValue * * @param cls closure * @param payto_uri the exchange bank account URI + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account + * @param credit_restrictions JSON array with credit restrictions on the account * @param master_sig master key signature affirming that this is a bank * account of the exchange (of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS) + * @param bank_label label the wallet should use to display the account, can be NULL + * @param priority priority for ordering bank account labels */ typedef void (*TALER_EXCHANGEDB_WireAccountCallback)( void *cls, const char *payto_uri, - const struct TALER_MasterSignatureP *master_sig); + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); /** * Provide information about wire fees. * * @param cls closure - * @param wire_fee the wire fee we charge - * @param closing_fee the closing fee we charge + * @param fees the wire fees we charge * @param start_date from when are these fees valid (start date) * @param end_date until when are these fees valid (end date, exclusive) * @param master_sig master key signature affirming that this is the correct @@ -1819,10 +3087,34 @@ typedef void typedef void (*TALER_EXCHANGEDB_WireFeeCallback)( void *cls, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, - struct GNUNET_TIME_Absolute start_date, - struct GNUNET_TIME_Absolute end_date, + const struct TALER_WireFeeSet *fees, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Provide information about global fees. + * + * @param cls closure + * @param fees the global fees we charge + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account + * @param start_date from when are these fees valid (start date) + * @param end_date until when are these fees valid (end date, exclusive) + * @param master_sig master key signature affirming that this is the correct + * fee (of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES) + */ +typedef void +(*TALER_EXCHANGEDB_GlobalFeeCallback)( + void *cls, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, const struct TALER_MasterSignatureP *master_sig); @@ -1843,11 +3135,11 @@ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_WithdrawCallback)( void *cls, uint64_t rowid, - const struct TALER_BlindedCoinHash *h_blind_ev, + const struct TALER_BlindedCoinHashP *h_blind_ev, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const struct TALER_Amount *amount_with_fee); @@ -1873,8 +3165,8 @@ typedef void * @param cls closure * @param rowid which row in the table is the information from (for diagnostics) * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) - * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) * @param account_payto_uri which account did the transfer go to? + * @param h_payto hash over @a account_payto_uri as it is in the DB * @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls) * @param h_contract_terms which proposal was this payment about * @param denom_pub denomination of @a coin_pub @@ -1888,8 +3180,9 @@ typedef void uint64_t rowid, const struct TALER_MerchantPublicKeyP *merchant_pub, const char *account_payto_uri, - struct GNUNET_TIME_Absolute exec_time, - const struct TALER_PrivateContractHash *h_contract_terms, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp exec_time, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, @@ -1912,13 +3205,33 @@ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_WireTransferOutCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute date, + struct GNUNET_TIME_Timestamp date, const struct TALER_WireTransferIdentifierRawP *wtid, const char *payto_uri, const struct TALER_Amount *amount); /** + * Function called on transient aggregations matching + * a particular hash of a payto URI. + * + * @param cls + * @param payto_uri corresponding payto URI + * @param wtid wire transfer identifier of transient aggregation + * @param merchant_pub public key of the merchant + * @param total amount aggregated so far + * @return true to continue iterating + */ +typedef bool +(*TALER_EXCHANGEDB_TransientAggregationCallback)( + void *cls, + const char *payto_uri, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_Amount *total); + + +/** * Callback with data about a prepared wire transfer. * * @param cls closure @@ -1956,13 +3269,13 @@ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RecoupCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); /** @@ -1985,14 +3298,41 @@ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RecoupRefreshCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct TALER_Amount *amount, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, - const struct TALER_DenominationHash *old_denom_pub_hash, + const struct TALER_DenominationHashP *old_denom_pub_hash, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); + + +/** + * Function called about reserve opening operations. + * + * @param cls closure + * @param rowid row identifier used to uniquely identify the reserve closing operation + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_pub public key of the reserve + * @param reserve_sig signature affirming the operation + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_ReserveOpenCallback)( + void *cls, + uint64_t rowid, + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); /** @@ -2007,18 +3347,21 @@ typedef enum GNUNET_GenericReturnValue * @param reserve_pub public key of the reserve * @param receiver_account where did we send the funds, in payto://-format * @param wtid identifier used for the wire transfer + * @param close_request_row row with the responsible close + * request, 0 if regular expiration triggered close * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveClosedCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *closing_fee, const struct TALER_ReservePublicKeyP *reserve_pub, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid); + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t close_request_row); /** @@ -2041,15 +3384,20 @@ typedef void * @param left amount left in the reserve * @param account_details information about the reserve's bank account, in payto://-format * @param expiration_date when did the reserve expire - * @return transaction status code to pass on + * @param close_request_row row that caused the reserve + * to be closed, 0 if it expired without request + * @return #GNUNET_OK on success, + * #GNUNET_NO to retry + * #GNUNET_SYSERR on hard failures (exit) */ -typedef enum GNUNET_DB_QueryStatus +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveExpiredCallback)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *left, const char *account_details, - struct GNUNET_TIME_Absolute expiration_date); + struct GNUNET_TIME_Timestamp expiration_date, + uint64_t close_request_row); /** @@ -2070,34 +3418,72 @@ typedef void uint64_t rowid, const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_BlindedCoinHash *h_blinded_ev, + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind, + const struct TALER_BlindedCoinHashP *h_blinded_ev, const struct TALER_Amount *amount); /** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. + * Function called on (batch) deposits will need a wire + * transfer. * * @param cls closure - * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin - * @param amount value of the deposit, including fee - * @param payto_uri where should the funds be wired; URI in payto://-format - * @param deadline what was the requested wire transfer deadline - * @param tiny did the exchange defer this transfer because it is too small? - * @param done did the exchange claim that it made a transfer? + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline */ typedef void (*TALER_EXCHANGEDB_WireMissingCallback)( void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline); + + +/** + * Function called on aggregations that were done for + * a (batch) deposit. + * + * @param cls closure + * @param tracking_serial_id where in the table are we + * @param batch_deposit_serial_id which batch deposit was aggregated + */ +typedef void +(*TALER_EXCHANGEDB_AggregationCallback)( + void *cls, + uint64_t tracking_serial_id, + uint64_t batch_deposit_serial_id); + + +/** + * Function called on purse requests. + * + * @param cls closure + * @param rowid purse request table row of the purse + * @param purse_pub public key of the purse + * @param merge_pub public key representing the merge capability + * @param purse_creation when was the purse created? + * @param purse_expiration when would an unmerged purse expire + * @param h_contract_terms contract associated with the purse + * @param age_limit the age limit for deposits into the purse + * @param target_amount amount to be put into the purse + * @param purse_sig signature of the purse over the initialization data + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRequestCallback)( + void *cls, uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const char *payto_uri, - struct GNUNET_TIME_Absolute deadline, - bool tiny, - bool done); + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_creation, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + const struct TALER_Amount *target_amount, + const struct TALER_PurseContractSignatureP *purse_sig); /** @@ -2113,7 +3499,47 @@ typedef void (*TALER_EXCHANGEDB_DenominationCallback)( void *cls, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); + + +/** + * Return AML status. + * + * @param cls closure + * @param row_id current row in AML status table + * @param h_payto account for which the attribute data is stored + * @param threshold currently monthly threshold that would trigger an AML check + * @param status what is the current AML decision + */ +typedef void +(*TALER_EXCHANGEDB_AmlStatusCallback)( + void *cls, + uint64_t row_id, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold, + enum TALER_AmlDecisionState status); + + +/** + * Return historic AML decision. + * + * @param cls closure + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + */ +typedef void +(*TALER_EXCHANGEDB_AmlHistoryCallback)( + void *cls, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig); /** @@ -2144,15 +3570,20 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_GenericReturnValue (*drop_tables)(void *cls); - /** * Create the necessary tables if they are not present * * @param cls the @e cls of this struct with the plugin-specific state + * @param support_partitions true to enable partitioning support (disables foreign key constraints) + * @param num_partitions number of partitions to create, + * (0 to not actually use partitions, 1 to only + * setup a default partition, >1 for real partitions) * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ enum GNUNET_GenericReturnValue - (*create_tables)(void *cls); + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); /** @@ -2180,6 +3611,18 @@ struct TALER_EXCHANGEDB_Plugin (*start_read_committed)(void *cls, const char *name); + /** + * Start a READ ONLY serializable transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param name unique name identifying the transaction (for debugging) + * must point to a constant + * @return #GNUNET_OK on success + */ + enum GNUNET_GenericReturnValue + (*start_read_only)(void *cls, + const char *name); + /** * Commit a transaction. @@ -2272,7 +3715,7 @@ struct TALER_EXCHANGEDB_Plugin (*insert_denomination_info)( void *cls, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); /** @@ -2286,8 +3729,8 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_denomination_info)( void *cls, - const struct TALER_DenominationHash *denom_pub_hash, - struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); /** @@ -2377,180 +3820,448 @@ struct TALER_EXCHANGEDB_Plugin * @param[in,out] 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. - * @param[out] kyc set to the KYC status of the reserve * @return transaction status */ enum GNUNET_DB_QueryStatus (*reserves_get)(void *cls, - struct TALER_EXCHANGEDB_Reserve *reserve, - struct TALER_EXCHANGEDB_KycStatus *kyc); + struct TALER_EXCHANGEDB_Reserve *reserve); /** - * Set the KYC status to "OK" for a bank account. + * Get the origin of funds of a reserve. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param payment_target_uuid which account has been checked - * @param id ID data to persist + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] h_payto set to hash of the wire source payto://-URI * @return transaction status */ enum GNUNET_DB_QueryStatus - (*set_kyc_ok)(void *cls, - uint64_t payment_target_uuid, - const char *id); + (*reserves_get_origin)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_PaytoHashP *h_payto); /** - * Get the KYC status for a bank account. + * Extract next KYC alert. Deletes the alert. * * @param cls the @e cls of this struct with the plugin-specific state - * @param payto_uri payto:// URI that identifies the bank account - * @param[out] kyc set to the KYC status of the reserve + * @param trigger_type which type of alert to drain + * @param[out] h_payto set to hash of payto-URI where KYC status changed * @return transaction status */ enum GNUNET_DB_QueryStatus - (*get_kyc_status)(void *cls, - const char *payto_uri, - struct TALER_EXCHANGEDB_KycStatus *kyc); + (*drain_kyc_alert)(void *cls, + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto); /** - * Get the @a kyc status and @a h_payto by UUID. + * Insert a batch of incoming transaction into reserves. New reserves are + * also created through this function. * * @param cls the @e cls of this struct with the plugin-specific state - * @param payment_target_uuid which account to get the KYC status for - * @param[out] h_payto set to the hash of the account's payto URI (unsalted) - * @param[out] kyc set to the KYC status of the account - * @return transaction status + * @param reserves + * @param reserves_length length of the @a reserves array + * @param[out] results array of transaction status codes of length @a reserves_length, + * set to the status of the */ enum GNUNET_DB_QueryStatus - (*select_kyc_status)(void *cls, - uint64_t payment_target_uuid, - struct TALER_PaytoHash *h_payto, - struct TALER_EXCHANGEDB_KycStatus *kyc); + (*reserves_in_insert)( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results); /** - * Get the KYC status for a wallet. If the status is unknown, - * inserts a new status record (hence INsertSELECT). + * Locate a nonce for use with a particular public key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the wallet - * @param[out] kyc set to the KYC status of the wallet - * @return transaction status + * @param nonce the nonce to be locked + * @param denom_pub_hash hash of the public key of the denomination + * @param target public key the nonce is to be locked to + * @return statement execution status */ enum GNUNET_DB_QueryStatus - (*inselect_wallet_kyc_status)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_EXCHANGEDB_KycStatus *kyc); + (*lock_nonce)(void *cls, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + const struct TALER_DenominationHashP *denom_pub_hash, + const union TALER_EXCHANGEDB_NonceLockTargetP *target); /** - * Insert a incoming transaction into reserves. New reserves are - * also created through this function. + * Locate the response for a withdraw request under a hash that uniquely + * identifies the withdraw operation. Used to ensure idempotency of the + * request. * * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param balance the amount that has to be added to the reserve - * @param execution_time when was the amount added - * @param sender_account_details information about the sender's bank account, in payto://-format - * @param wire_reference unique reference identifying the wire transfer - * @return transaction status code + * @param bch hash that uniquely identifies the withdraw operation + * @param[out] collectable corresponding collectable coin (blind signature) + * if a coin is found + * @return statement execution status */ enum GNUNET_DB_QueryStatus - (*reserves_in_insert)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *balance, - struct GNUNET_TIME_Absolute execution_time, - const char *sender_account_details, - const char *exchange_account_name, - uint64_t wire_reference); + (*get_withdraw_info)(void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_EXCHANGEDB_CollectableBlindcoin * + collectable); /** - * Obtain the most recent @a wire_reference that was inserted via @e reserves_in_insert. - * Used by the wirewatch process when resuming. + * FIXME: merge do_batch_withdraw and do_batch_withdraw_insert into one API, + * which takes as input (among others) + * - denom_serial[] + * - blinded_coin_evs[] + * - denom_sigs[] + * The implementation should persist the data as _arrays_ in the DB. + */ + + /** + * Perform reserve update as part of a batch withdraw operation, checking + * for sufficient balance. Persisting the withdrawal details is done + * separately! * - * @param cls the @e cls of this struct with the plugin-specific state - * @param exchange_account_name name of the section in the exchange's configuration - * for the account that we are tracking here - * @param[out] wire_reference set to unique reference identifying the wire transfer - * @return transaction status code + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param now current time (rounded) + * @param reserve_pub public key of the reserve to debit + * @param amount total amount to withdraw + * @param do_age_check if set, the batch-withdrawal can only succeed when the reserve has no age restriction (birthday) set. + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if no age requirements were defined on the reserve or @e do_age_check was false + * @param[out] allowed_maximum_age when @e age_ok is false, set to the allowed maximum age for withdrawal from the reserve. The client MUST then use the age-withdraw endpoint + * @param[out] ruuid set to the reserve's UUID (reserves table row) + * @return query execution status */ enum GNUNET_DB_QueryStatus - (*get_latest_reserve_in_reference)(void *cls, - const char *exchange_account_name, - uint64_t *wire_reference); + (*do_batch_withdraw)( + void *cls, + struct GNUNET_TIME_Timestamp now, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + bool do_age_check, + bool *found, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, + uint64_t *ruuid); /** - * Locate the response for a withdraw request under the - * key of the hash of the blinded message. Used to ensure - * idempotency of the request. + * Perform insert as part of a batch withdraw operation, and persisting the + * withdrawal details. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param h_blind hash of the blinded coin to be signed (will match - * `h_coin_envelope` in the @a collectable to be returned) + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param nonce client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals * @param collectable corresponding collectable coin (blind signature) - * if a coin is found + * @param now current time (rounded) + * @param ruuid reserve UUID + * @param[out] denom_unknown set if the denomination is unknown in the DB + * @param[out] conflict if the envelope was already in the DB + * @param[out] nonce_reuse if @a nonce was non-NULL and reused + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_batch_withdraw_insert)( + void *cls, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, + struct GNUNET_TIME_Timestamp now, + uint64_t ruuid, + bool *denom_unknown, + bool *conflict, + bool *nonce_reuse); + + /** + * Locate the response for a age-withdraw request under a hash of the + * commitment and reserve_pub that uniquely identifies the age-withdraw + * operation. Used to ensure idempotency of the request. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the reserve for which the age-withdraw request is made + * @param ach hash that uniquely identifies the age-withdraw operation + * @param[out] aw corresponding details of the previous age-withdraw request if an entry was found * @return statement execution status */ enum GNUNET_DB_QueryStatus - (*get_withdraw_info)(void *cls, - const struct TALER_BlindedCoinHash *h_blind, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + (*get_age_withdraw)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AgeWithdrawCommitmentHashP *ach, + struct TALER_EXCHANGEDB_AgeWithdraw *aw); + /** + * Perform an age-withdraw operation, checking for sufficient balance and + * fulfillment of age requirements and possibly persisting the withdrawal + * details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param commitment corresponding commitment for the age-withdraw + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if age requirements were met + * @param[out] allowed_maximum_age if @e age_ok is FALSE, this is set to the allowed maximum age + * @param[out] reserve_birthday if @e age_ok is FALSE, this is set to the reserve's birthday + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_age_withdraw)( + void *cls, + const struct TALER_EXCHANGEDB_AgeWithdraw *commitment, + struct GNUNET_TIME_Timestamp now, + bool *found, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, + uint32_t *reserve_birthday, + bool *conflict); + + /** + * Retrieve the details to a policy given by its hash_code + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param hc Hash code that identifies the policy + * @param[out] detail retrieved policy details + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*get_policy_details)( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *detail); /** - * Store collectable coin under the corresponding hash of the blinded - * message. + * Persist the policy details that extends a deposit. The particular policy + * - referenced by details->hash_code - might already exist in the table, in + * which case the call will update the contents of the record with @e details * - * @param cls the @e cls of this struct with the plugin-specific state - * @param collectable corresponding collectable coin (blind signature) - * if a coin is found - * @return statement execution status + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param details The parsed `struct TALER_PolicyDetails` according to the responsible policy extension. + * @param[out] policy_details_serial_id The ID of the entry in the policy_details table + * @param[out] accumulated_total The total amount accumulated in that policy + * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. + * @return query execution status */ enum GNUNET_DB_QueryStatus - (*insert_withdraw_info)( + (*persist_policy_details)( void *cls, - const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state); /** - * Get all of the transaction history associated with the specified - * reserve. + * Perform deposit operation, checking for sufficient balance + * of the coin and possibly persisting the deposit details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param bd batch deposit operation details + * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient, + * only used if @a balance_ok is set to false. + * @param[out] ctr_conflict set to true if the same contract terms hash was previously submitted with other meta data (deadlines, wallet_data_hash, wire data etc.) + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_deposit)( + void *cls, + const struct TALER_EXCHANGEDB_BatchDeposit *bd, + struct GNUNET_TIME_Timestamp *exchange_timestamp, + bool *balance_ok, + uint32_t *bad_balance_index, + bool *ctr_conflict); + + + /** + * Perform melt operation, checking for sufficient balance + * of the coin and possibly persisting the melt details. + * + * @param cls the plugin-specific state + * @param rms client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals + * @param[in,out] refresh refresh operation details; the noreveal_index + * is set in case the coin was already melted before + * @param known_coin_id row of the coin in the known_coins table + * @param[in,out] zombie_required true if the melt must only succeed if the coin is a zombie, set to false if the requirement was satisfied + * @param[out] balance_ok set to true if the balance was sufficient + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_melt)( + void *cls, + const struct TALER_RefreshMasterSecretP *rms, + struct TALER_EXCHANGEDB_Refresh *refresh, + uint64_t known_coin_id, + bool *zombie_required, + bool *balance_ok); + + + /** + * Add a proof of fulfillment of an policy + * + * @param cls the plugin-specific state + * @param[in,out] fulfillment The proof of fulfillment and serial_ids of the policy_details along with their new state and potential new amounts. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*add_policy_fulfillment_proof)( + void *cls, + struct TALER_PolicyFulfillmentTransactionData *fulfillment); + + + /** + * Check if the given @a nonce was properly locked to the given @a old_coin_pub. If so, check if we already + * created CS signatures for the given @a nonce and @a new_denom_pub_hashes, + * and if so, return them in @a s_scalars. Otherwise, persist the + * signatures from @a s_scalars in the database. + * + * @param cls the plugin-specific state + * @param nonce the client-provided nonce where we must prevent reuse + * @param old_coin_pub public key the nonce was locked to + * @param num_fresh_coins array length, number of fresh coins revealed + * @param[in,out] crfcds array of data about the fresh coins, of length @a num_fresh_coins + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*cs_refreshes_reveal)( + void *cls, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + unsigned int num_fresh_coins, + struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds); + + + /** + * Perform refund operation, checking for sufficient deposits + * of the coin and possibly persisting the refund details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param refund refund operation details + * @param deposit_fee deposit fee applicable for the coin, possibly refunded + * @param known_coin_id row of the coin in the known_coins table + * @param[out] not_found set if the deposit was not found + * @param[out] refund_ok set if the refund succeeded (below deposit amount) + * @param[out] gone if the merchant was already paid + * @param[out] conflict set if the refund ID was re-used + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_refund)( + void *cls, + const struct TALER_EXCHANGEDB_Refund *refund, + const struct TALER_Amount *deposit_fee, + uint64_t known_coin_id, + bool *not_found, + bool *refund_ok, + bool *gone, + bool *conflict); + + + /** + * Perform recoup operation, checking for sufficient deposits + * of the coin and possibly persisting the recoup details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve to credit + * @param reserve_out_serial_id row in the reserves_out table justifying the recoup + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_recoup)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t reserve_out_serial_id, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); + + + /** + * Perform recoup-refresh operation, checking for sufficient deposits of the + * coin and possibly persisting the recoup-refresh details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param old_coin_pub public key of the old coin to credit + * @param rrc_serial row in the refresh_revealed_coins table justifying the recoup-refresh + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup-refresh succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_recoup_refresh)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t rrc_serial, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); + + + /** + * Compile a list of (historic) transactions performed with the given reserve + * (withdraw, incoming wire, open, close operations). Should return 0 if the @a + * reserve_pub is unknown, otherwise determine @a etag_out and if it is past @a + * etag_in return the history after @a start_off. @a etag_out should be set + * to the last row ID of the given @a reserve_pub in the reserve history table. * * @param cls the @e cls of this struct with the plugin-specific state * @param reserve_pub public key of the reserve + * @param start_off maximum starting offset in history to exclude from returning + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub + * @param[out] balance set to the reserve balance * @param[out] rhp set to known transaction history (NULL if reserve is unknown) * @return transaction status */ enum GNUNET_DB_QueryStatus (*get_reserve_history)(void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, struct TALER_EXCHANGEDB_ReserveHistory **rhp); /** - * Find out all of the amounts that have been withdrawn - * so far from the same bank account that created the - * given reserve. + * The current reserve balance of the specified reserve. * - * @param cls closure - * @param reserve_pub reserve to select withdrawals by - * @param duration how far back should we select withdrawals - * @param cb function to call on each amount withdrawn - * @param cb_cls closure for @a cb + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] balance set to the reserve balance * @return transaction status */ enum GNUNET_DB_QueryStatus - (*select_withdraw_amounts_by_account)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Relative duration, - TALER_EXCHANGEDB_WithdrawHistoryCallback cb, - void *cb_cls); + (*get_reserve_balance)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance); /** @@ -2573,7 +4284,7 @@ struct TALER_EXCHANGEDB_Plugin */ long long (*count_known_coins) (void *cls, - const struct TALER_DenominationHash *denom_pub_hash); + const struct TALER_DenominationHashP *denom_pub_hash); /** @@ -2581,6 +4292,9 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls database connection plugin state * @param coin the coin that must be made known + * @param[out] known_coin_id set to the unique row of the coin + * @param[out] denom_pub_hash set to the conflicting denomination hash on conflict + * @param[out] age_hash set to the conflicting age hash on conflict * @return database transaction status, non-negative on success */ enum TALER_EXCHANGEDB_CoinKnownStatus @@ -2608,17 +4322,56 @@ struct TALER_EXCHANGEDB_Plugin /** * Conflicting coin (different denomination key) already in database. */ - TALER_EXCHANGEDB_CKS_CONFLICT = -3, + TALER_EXCHANGEDB_CKS_DENOM_CONFLICT = -3, + + /** + * Conflicting coin (expected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL = -4, + + /** + * Conflicting coin (unexpected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL = -5, + + /** + * Conflicting coin (different age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS = -6, + } (*ensure_coin_known)(void *cls, - const struct TALER_CoinPublicInfo *coin); + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_AgeCommitmentHash *age_hash); + + + /** + * Make sure the array of given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin array of coins that must be made known + * @param[out] result array where to store information about each coin + * @param coin_length length of the @a coin and @a result arraysf + * @param batch_size desired (maximum) batch size + * @return database transaction status, non-negative on success + */ + enum GNUNET_DB_QueryStatus + (*batch_ensure_coin_known)( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); /** * Retrieve information about the given @a coin from the database. * * @param cls database connection plugin state - * @param coin the coin that must be made known + * @param coin_pub the coin that must be made known + * @param[out] coin_info detailed information about the coin * @return database transaction status, non-negative on success */ enum GNUNET_DB_QueryStatus @@ -2626,37 +4379,55 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinPublicInfo *coin_info); + /** + * Retrieve the signature and corresponding denomination for a given @a coin + * from the database + * + * @param cls database connection plugin state + * @param coin_pub the public key of the coin we search for + * @param[out] denom_pub the public key of the denomination that the coin was signed with + * @param[out] denom_sig the signature with the denomination's private key over the coin_pub + */ + enum GNUNET_DB_QueryStatus + (*get_signature_for_known_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationSignature *denom_sig); /** * Retrieve the denomination of a known coin. * * @param cls the plugin closure * @param coin_pub the public key of the coin to search for + * @param[out] known_coin_id set to the ID of the coin in the known_coins table * @param[out] denom_hash where to store the hash of the coins denomination * @return transaction status code */ enum GNUNET_DB_QueryStatus (*get_coin_denomination)(void *cls, const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_DenominationHash *denom_hash); + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash); /** - * Check if we have the specified deposit already in the database. + * Try to retrieve the salted hash of the merchant's bank account to a + * deposit contract. Used in case of conflicts for a given (merchant_pub, + * h_contract_terms) to provide the client the necessary input to retrieve + * more details about the conflict. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param deposit deposit to search for - * @param[out] deposit_fee set to the deposit fee the exchange charged - * @param[out] exchange_timestamp set to the time when the exchange received the deposit - * @return 1 if we know this operation, - * 0 if this exact deposit is unknown to us, - * otherwise transaction error status + * @param cls the plugin closure + * @param merchant_pub public key of the merchant + * @param h_contract_terms contract to check for + * @param[out] h_wire hash of the wire details */ enum GNUNET_DB_QueryStatus - (*have_deposit)(void *cls, - const struct TALER_EXCHANGEDB_Deposit *deposit, - struct TALER_Amount *deposit_fee, - struct GNUNET_TIME_Absolute *exchange_timestamp); + (*get_wire_hash_for_contract)( + void *cls, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct TALER_MerchantWireHashP *h_wire); /** @@ -2674,34 +4445,22 @@ struct TALER_EXCHANGEDB_Plugin * 0 if this exact deposit is unknown to us, * otherwise transaction error status */ + // FIXME: rename! enum GNUNET_DB_QueryStatus (*have_deposit2)( void *cls, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_MerchantWireHash *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant, - struct GNUNET_TIME_Absolute refund_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, struct TALER_Amount *deposit_fee, - struct GNUNET_TIME_Absolute *exchange_timestamp); - - - /** - * Insert information about deposited coin into the database. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param exchange_timestamp time the exchange received the deposit request - * @param deposit deposit information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_deposit)(void *cls, - struct GNUNET_TIME_Absolute exchange_timestamp, - const struct TALER_EXCHANGEDB_Deposit *deposit); + struct GNUNET_TIME_Timestamp *exchange_timestamp); /** * Insert information about refunded coin into the database. + * Used in tests and for benchmarking. * * @param cls the @e cls of this struct with the plugin-specific state * @param refund refund information to store @@ -2724,144 +4483,169 @@ struct TALER_EXCHANGEDB_Plugin * @return query result status */ enum GNUNET_DB_QueryStatus - (*select_refunds_by_coin)(void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_PrivateContractHash *h_contract, - TALER_EXCHANGEDB_RefundCoinCallback cb, - void *cb_cls); + (*select_refunds_by_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls); /** - * Mark a deposit as tiny, thereby declaring that it cannot be executed by - * itself (only included in a larger aggregation) and should no longer be - * returned by @e iterate_ready_deposits() + * Obtain information about deposits that are ready to be executed. + * Such deposits must not be marked as "done", and the + * execution time, the refund deadlines must both be in the past and + * the KYC status must be 'ok'. * * @param cls the @e cls of this struct with the plugin-specific state - * @param deposit_rowid identifies the deposit row to modify - * @return query result status + * @param start_shard_row minimum shard row to select + * @param end_shard_row maximum shard row to select (inclusive) + * @param[out] merchant_pub set to the public key of a merchant with a ready deposit + * @param[out] payto_uri set to the account of the merchant, to be freed by caller + * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*mark_deposit_tiny)(void *cls, - uint64_t rowid); + (*get_ready_deposit)(void *cls, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP *merchant_pub, + char **payto_uri); /** - * Mark a deposit as done, thereby declaring that it cannot be - * executed at all anymore, and should no longer be returned by - * @e iterate_ready_deposits() or @e iterate_matching_deposits(). + * Aggregate all matching deposits for @a h_payto and + * @a merchant_pub, returning the total amounts. * * @param cls the @e cls of this struct with the plugin-specific state - * @param deposit_rowid identifies the deposit row to modify - * @return query result status + * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant + * @param wtid wire transfer ID to set for the aggregate + * @param[out] total set to the sum of the total deposits minus applicable deposit fees and refunds + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*mark_deposit_done)(void *cls, - uint64_t rowid); + (*aggregate)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); /** - * Obtain information about deposits that are ready to be executed. - * Such deposits must not be marked as "tiny" or "done", and the - * execution time, the refund deadlines must both be in the past and - * the KYC status must be 'ok'. + * Create a new entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param start_shard_row minimum shard row to select - * @param end_shard_row maximum shard row to select (inclusive) - * @param kyc_off true if we should not check the KYC status because - * this exchange does not need/support KYC checks. - * @param deposit_cb function to call for ONE such deposit - * @param deposit_cb_cls closure for @a deposit_cb - * @return transaction status code + * @param h_payto destination of the wire transfer + * @param exchange_account_section exchange account to use + * @param merchant_pub public key of the merchant + * @param wtid the raw wire transfer identifier to be used + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total amount to be wired in the future + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*get_ready_deposit)(void *cls, - uint64_t start_shard_row, - uint64_t end_shard_row, - bool kyc_off, - TALER_EXCHANGEDB_DepositIterator deposit_cb, - void *deposit_cb_cls); - + (*create_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); -/** - * Maximum number of results we return from iterate_matching_deposits(). - * - * Limit on the number of transactions we aggregate at once. Note - * that the limit must be big enough to ensure that when transactions - * of the smallest possible unit are aggregated, they do surpass the - * "tiny" threshold beyond which we never trigger a wire transaction! - */ -#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000 /** - * Obtain information about other pending deposits for the same - * destination. Those deposits must not already be "done". + * Select existing entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param h_wire destination of the wire transfer + * @param h_payto destination of the wire transfer * @param merchant_pub public key of the merchant - * @param deposit_cb function to call for each deposit - * @param deposit_cb_cls closure for @a deposit_cb - * @param limit maximum number of matching deposits to return; should - * be #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT, larger values - * are not supported, smaller values would be inefficient. - * @return number of rows processed, 0 if none exist, - * transaction status code on error + * @param exchange_account_section exchange account to use + * @param[out] wtid set to the raw wire transfer identifier to be used + * @param[out] total existing amount to be wired in the future + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*iterate_matching_deposits)( + (*select_aggregation_transient)( void *cls, - uint64_t wire_target, + const struct TALER_PaytoHashP *h_payto, const struct TALER_MerchantPublicKeyP *merchant_pub, - TALER_EXCHANGEDB_MatchingDepositIterator deposit_cb, - void *deposit_cb_cls, - uint32_t limit); + const char *exchange_account_section, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); /** - * Store new melt commitment data. + * Find existing entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param refresh_session operational data to store - * @return query status for the transaction + * @param h_payto destination of the wire transfer + * @param cb function to call on each matching entry + * @param cb_cls closure for @a cb + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_melt)(void *cls, - const struct TALER_EXCHANGEDB_Refresh *refresh_session); + (*find_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_TransientAggregationCallback cb, + void *cb_cls); /** - * Lookup melt commitment data under the given @a rc. + * Update existing entry in the transient aggregation table. + * @a h_payto is only needed for query performance. * * @param cls the @e cls of this struct with the plugin-specific state - * @param rc commitment to use for the lookup - * @param[out] melt where to store the result; note that - * melt->session.coin.denom_sig will be set to NULL - * and is not fetched by this routine (as it is not needed by the client) + * @param h_payto destination of the wire transfer + * @param wtid the raw wire transfer identifier to update + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total new total amount to be wired in the future * @return transaction status */ enum GNUNET_DB_QueryStatus - (*get_melt)(void *cls, - const struct TALER_RefreshCommitmentP *rc, - struct TALER_EXCHANGEDB_Melt *melt); + (*update_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); /** - * Lookup noreveal index of a previous melt operation under the given - * @a rc. + * Delete existing entry in the transient aggregation table. + * @a h_payto is only needed for query performance. * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param rc commitment hash to use to locate the operation - * @param[out] noreveal_index returns the "gamma" value selected by the - * exchange which is the index of the transfer key that is - * not to be revealed to the exchange + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param wtid the raw wire transfer identifier to update * @return transaction status */ enum GNUNET_DB_QueryStatus - (*get_melt_index)(void *cls, - const struct TALER_RefreshCommitmentP *rc, - uint32_t *noreveal_index); + (*delete_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid); + + + /** + * Lookup melt commitment data under the given @a rc. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param rc commitment to use for the lookup + * @param[out] melt where to store the result; note that + * melt->session.coin.denom_sig will be set to NULL + * and is not fetched by this routine (as it is not needed by the client) + * @param[out] melt_serial_id set to the row ID of @a rc in the refresh_commitments table + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_melt)(void *cls, + const struct TALER_RefreshCommitmentP *rc, + struct TALER_EXCHANGEDB_Melt *melt, + uint64_t *melt_serial_id); /** @@ -2870,7 +4654,7 @@ struct TALER_EXCHANGEDB_Plugin * we learned or created in the reveal step. * * @param cls the @e cls of this struct with the plugin-specific state - * @param rc identify commitment and thus refresh operation + * @param melt_serial_id row ID of the commitment / melt operation in refresh_commitments * @param num_rrcs number of coins to generate, size of the @a rrcs array * @param rrcs information about the new coins * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 @@ -2881,7 +4665,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_refresh_reveal)( void *cls, - const struct TALER_RefreshCommitmentP *rc, + uint64_t melt_serial_id, uint32_t num_rrcs, const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, unsigned int num_tprivs, @@ -2890,7 +4674,7 @@ struct TALER_EXCHANGEDB_Plugin /** - * Lookup in the database for the @a num_freshcoins coins that we + * Lookup in the database for the fresh coins that we * created in the given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state @@ -2926,20 +4710,35 @@ struct TALER_EXCHANGEDB_Plugin /** - * Compile a list of all (historic) transactions performed - * with the given coin (melt, refund, recoup and deposit operations). + * Compile a list of (historic) transactions performed with the given coin + * (melt, refund, recoup and deposit operations). Should return 0 if the @a + * coin_pub is unknown, otherwise determine @a etag_out and if it is past @a + * etag_in return the history after @a start_off. @a etag_out should be set + * to the last row ID of the given @a coin_pub in the coin history table. * * @param cls the @e cls of this struct with the plugin-specific state * @param coin_pub coin to investigate - * @param include_recoup include recoup transactions of the coin? - * @param[out] tlp set to list of transactions, NULL if coin is fresh + * @param start_off starting offset from which on to return entries + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub + * @param[out] balance set to current balance of the coin + * @param[out] h_denom_pub set to denomination public key of the coin + * @param[out] tlp set to list of transactions, set to NULL if coin has no + * transaction history past @a start_off or if @a etag_in is equal + * to the value written to @a etag_out. * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*get_coin_transactions)(void *cls, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - int include_recoup, - struct TALER_EXCHANGEDB_TransactionList **tlp); + (*get_coin_transactions)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_TransactionList **tlp); /** @@ -2988,58 +4787,68 @@ struct TALER_EXCHANGEDB_Plugin * @param[out] execution_time when was the transaction done, or * when we expect it to be done (if @a pending is false) * @param[out] kyc set to the kyc status of the receiver (if @a pending) + * @param[out] aml_decision set to the current AML status for the target account * @return transaction status code */ enum GNUNET_DB_QueryStatus (*lookup_transfer_by_deposit)( void *cls, - const struct TALER_PrivateContractHash *h_contract_terms, - const struct TALER_MerchantWireHash *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, bool *pending, struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Absolute *exec_time, + struct GNUNET_TIME_Timestamp *exec_time, struct TALER_Amount *amount_with_fee, struct TALER_Amount *deposit_fee, - struct TALER_EXCHANGEDB_KycStatus *kyc); + struct TALER_EXCHANGEDB_KycStatus *kyc, + enum TALER_AmlDecisionState *aml_decision); /** - * Function called to insert aggregation information into the DB. + * Insert wire transfer fee into database. * * @param cls closure - * @param wtid the raw wire transfer identifier we used - * @param deposit_serial_id row in the deposits table for which this is aggregation data + * @param wire_method which wire method is the fee about? + * @param start_date when does the fee go into effect + * @param end_date when does the fee end being valid + * @param fees how high is are the wire fees + * @param master_sig signature over the above by the exchange master key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_aggregation_tracking)( - void *cls, - const struct TALER_WireTransferIdentifierRawP *wtid, - unsigned long long deposit_serial_id); + (*insert_wire_fee)(void *cls, + const char *wire_method, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig); /** - * Insert wire transfer fee into database. + * Insert global fee set into database. * * @param cls closure - * @param wire_method which wire method is the fee about? - * @param start_date when does the fee go into effect - * @param end_date when does the fee end being valid - * @param wire_fee how high is the wire transfer fee - * @param closing_fee how high is the closing fee + * @param start_date when does the fees go into effect + * @param end_date when does the fees end being valid + * @param fees how high is are the global fees + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account * @param master_sig signature over the above by the exchange master key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_fee)(void *cls, - const char *wire_method, - struct GNUNET_TIME_Absolute start_date, - struct GNUNET_TIME_Absolute end_date, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, - const struct TALER_MasterSignatureP *master_sig); + (*insert_global_fee)(void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + + const struct TALER_MasterSignatureP *master_sig); /** @@ -3050,23 +4859,47 @@ struct TALER_EXCHANGEDB_Plugin * @param date for which date do we want the fee? * @param[out] start_date when does the fee go into effect * @param[out] end_date when does the fee end being valid - * @param[out] wire_fee how high is the wire transfer fee - * @param[out] closing_fee how high is the closing fee + * @param[out] fees how high are the wire fees * @param[out] master_sig signature over the above by the exchange master key * @return query status of the transaction */ enum GNUNET_DB_QueryStatus (*get_wire_fee)(void *cls, const char *type, - struct GNUNET_TIME_Absolute date, - struct GNUNET_TIME_Absolute *start_date, - struct GNUNET_TIME_Absolute *end_date, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, struct TALER_MasterSignatureP *master_sig); /** + * Obtain global fees from database. + * + * @param cls closure + * @param date for which date do we want the fee? + * @param[out] start_date when does the fee go into effect + * @param[out] end_date when does the fee end being valid + * @param[out] fees how high are the global fees + * @param[out] purse_timeout when do purses time out + * @param[out] history_expiration how long are account histories preserved + * @param[out] purse_account_limit how many purses are free per account + * @param[out] master_sig signature over the above by the exchange master key + * @return query status of the transaction + */ + enum GNUNET_DB_QueryStatus + (*get_global_fee)(void *cls, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig); + + + /** * Obtain information about expired reserves and their * remaining balances. * @@ -3078,12 +4911,158 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*get_expired_reserves)(void *cls, - struct GNUNET_TIME_Absolute now, + struct GNUNET_TIME_Timestamp now, TALER_EXCHANGEDB_ReserveExpiredCallback rec, void *rec_cls); /** + * Obtain information about force-closed reserves + * where the close was not yet done (and their remaining + * balances). Updates the returned reserve's close + * status to "done". + * + * @param cls closure of the plugin + * @param rec function to call on (to be) closed reserves + * @param rec_cls closure for @a rec + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_unfinished_close_requests)( + void *cls, + TALER_EXCHANGEDB_ReserveExpiredCallback rec, + void *rec_cls); + + + /** + * Insert reserve open coin deposit data into database. + * Subtracts the @a coin_total from the coin's balance. + * + * @param cls closure + * @param cpi public information about the coin + * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT + * @param known_coin_id ID of the coin in the known_coins table + * @param coin_total amount to be spent of the coin (including deposit fee) + * @param reserve_sig signature by the reserve affirming the open operation + * @param reserve_pub public key of the reserve being opened + * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false + * @return transaction status code, 0 if operation is already in the DB + */ + enum GNUNET_DB_QueryStatus + (*insert_reserve_open_deposit)( + void *cls, + const struct TALER_CoinPublicInfo *cpi, + const struct TALER_CoinSpendSignatureP *coin_sig, + uint64_t known_coin_id, + const struct TALER_Amount *coin_total, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *insufficient_funds); + + + /** + * Insert reserve close operation into database. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param total_paid total amount paid (coins and reserve) + * @param reserve_payment amount to be paid from the reserve + * @param min_purse_limit minimum number of purses we should be able to open + * @param reserve_sig signature by the reserve for the operation + * @param desired_expiration when should the reserve expire (earliest time) + * @param now when did we the client initiate the action + * @param open_fee annual fee to be charged for the open operation by the exchange + * @param[out] no_funds set to true if reserve balance is insufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] open_cost set to the actual cost + * @param[out] final_expiration when will the reserve expire now + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_reserve_open)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, + uint32_t min_purse_limit, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp desired_expiration, + struct GNUNET_TIME_Timestamp now, + const struct TALER_Amount *open_fee, + bool *no_funds, + struct TALER_Amount *reserve_balance, + struct TALER_Amount *open_cost, + struct GNUNET_TIME_Timestamp *final_expiration); + + + /** + * Select information needed to see if we can close + * a reserve. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param[out] balance current reserve balance + * @param[out] payto_uri set to URL of account that + * originally funded the reserve; + * could be set to NULL if not known + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance, + char **payto_uri); + + + /** + * Select information about reserve close requests. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param rowid row ID of the close request + * @param[out] reserve_sig reserve signature affirming + * @param[out] request_timestamp when was the request made + * @param[out] close_balance reserve balance at close time + * @param[out] close_fee closing fee to be charged + * @param[out] payto_uri set to URL of account that + * should receive the money; + * could be set to NULL for origin + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_request_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t rowid, + struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *close_balance, + struct TALER_Amount *close_fee, + char **payto_uri); + + + /** + * Select information needed for KYC checks on reserve close: historic + * reserve closures going to the same account. + * + * @param cls closure + * @param h_payto which target account is this about? + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*iterate_reserve_close_info)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** * Insert reserve close operation into database. * * @param cls closure @@ -3093,16 +5072,19 @@ struct TALER_EXCHANGEDB_Plugin * @param wtid identifier for the wire transfer * @param amount_with_fee amount we charged to the reserve * @param closing_fee how high is the closing fee + * @param close_request_row identifies explicit close request, 0 for none * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_reserve_closed)(void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid, + const struct + TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *closing_fee); + const struct TALER_Amount *closing_fee, + uint64_t close_request_row); /** @@ -3181,7 +5163,7 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param date time of the wire transfer - * @param wtid subject of the wire transfer + * @param h_payto identifies the receiver account of the wire transfer * @param wire_account details about the receiver account of the wire transfer, * including 'url' in payto://-format * @param amount amount that was transmitted @@ -3192,9 +5174,9 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*store_wire_transfer_out)( void *cls, - struct GNUNET_TIME_Absolute date, + struct GNUNET_TIME_Timestamp date, const struct TALER_WireTransferIdentifierRawP *wtid, - uint64_t wire_target, + const struct TALER_PaytoHashP *h_payto, const char *exchange_account_section, const struct TALER_Amount *amount); @@ -3222,10 +5204,138 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_deposits_above_serial_id)(void *cls, - uint64_t serial_id, - TALER_EXCHANGEDB_DepositCallback cb, - void *cb_cls); + (*select_coin_deposits_above_serial_id)(void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls); + + + /** + * Function called to return meta data about a purses + * above a certain serial ID. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param serial_id number to select requests by + * @param cb function to call on each request + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_requests_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseRequestCallback cb, + void *cb_cls); + + + /** + * Select purse deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseDepositCallback cb, + void *cb_cls); + + + /** + * Select account merges above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_account_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AccountMergeCallback cb, + void *cb_cls); + + + /** + * Select purse merges deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseMergeCallback cb, + void *cb_cls); + + + /** + * Select purse refunds above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param refunded which refund status to select for + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select all purse refunds above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_all_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AllPurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select coins deposited into a purse. + * + * @param cls closure + * @param purse_pub public key of the purse + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_by_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls); + /** * Select refresh sessions above @a serial_id in monotonically increasing @@ -3330,7 +5440,8 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_wire_out_above_serial_id)(void *cls, uint64_t serial_id, - TALER_EXCHANGEDB_WireTransferOutCallback cb, + TALER_EXCHANGEDB_WireTransferOutCallback + cb, void *cb_cls); /** @@ -3389,8 +5500,8 @@ struct TALER_EXCHANGEDB_Plugin /** - * Function called to select reserve close operations the aggregator - * triggered, ordered by serial ID (monotonically increasing). + * Function called to select reserve open operations, ordered by serial ID + * (monotonically increasing). * * @param cls closure * @param serial_id lowest serial ID to include (select larger or equal) @@ -3399,63 +5510,29 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_reserve_closed_above_serial_id)( + (*select_reserve_open_above_serial_id)( void *cls, uint64_t serial_id, - TALER_EXCHANGEDB_ReserveClosedCallback cb, + TALER_EXCHANGEDB_ReserveOpenCallback cb, void *cb_cls); /** - * Function called to add a request for an emergency recoup for a - * coin. The funds are to be added back to the reserve. - * - * @param cls closure - * @param reserve_pub public key of the reserve that is being refunded - * @param coin public information about a coin - * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP - * @param coin_blind blinding key of the coin - * @param h_blind_ev blinded envelope, as calculated by the exchange - * @param amount total amount to be paid back - * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) - * @param timestamp the timestamp to store - * @return transaction result status - */ - enum GNUNET_DB_QueryStatus - (*insert_recoup_request)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_Amount *amount, - const struct TALER_BlindedCoinHash *h_blind_ev, - struct GNUNET_TIME_Absolute timestamp); - - - /** - * Function called to add a request for an emergency recoup for a - * refreshed coin. The funds are to be added back to the original coin. - * - * @param cls closure - * @param coin public information about the refreshed coin - * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP - * @param coin_blind blinding key of the coin - * @param h_blind_ev blinded envelope, as calculated by the exchange - * @param amount total amount to be paid back - * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) - * @param timestamp a timestamp to store - * @return transaction result status - */ + * Function called to select reserve close operations the aggregator + * triggered, ordered by serial ID (monotonically increasing). + * + * @param cls closure + * @param serial_id lowest serial ID to include (select larger or equal) + * @param cb function to call + * @param cb_cls closure for @a cb + * @return transaction status code + */ enum GNUNET_DB_QueryStatus - (*insert_recoup_refresh_request)( + (*select_reserve_closed_above_serial_id)( void *cls, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_Amount *amount, - const struct TALER_BlindedCoinHash *h_blind_ev, - struct GNUNET_TIME_Absolute timestamp); + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveClosedCallback cb, + void *cb_cls); /** @@ -3463,14 +5540,17 @@ struct TALER_EXCHANGEDB_Plugin * from given the hash of the blinded coin. * * @param cls closure - * @param h_blind_ev hash of the blinded coin + * @param bch hash identifying the withdraw operation * @param[out] reserve_pub set to information about the reserve (on success only) + * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_by_h_blind)(void *cls, - const struct TALER_BlindedCoinHash *h_blind_ev, - struct TALER_ReservePublicKeyP *reserve_pub); + (*get_reserve_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id); /** @@ -3480,12 +5560,15 @@ struct TALER_EXCHANGEDB_Plugin * @param cls closure * @param h_blind_ev hash of the blinded coin * @param[out] old_coin_pub set to information about the old coin (on success only) + * @param[out] rrc_serial set to the row of the @a h_blind_ev in the refresh_revealed_coins table * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_old_coin_by_h_blind)(void *cls, - const struct TALER_BlindedCoinHash *h_blind_ev, - struct TALER_CoinSpendPublicKeyP *old_coin_pub); + (*get_old_coin_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *rrc_serial); /** @@ -3500,7 +5583,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_denomination_revocation)( void *cls, - const struct TALER_DenominationHash *denom_pub_hash, + const struct TALER_DenominationHashP *denom_pub_hash, const struct TALER_MasterSignatureP *master_sig); @@ -3515,31 +5598,71 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_denomination_revocation)(void *cls, - const struct - TALER_DenominationHash *denom_pub_hash, - struct TALER_MasterSignatureP *master_sig, - uint64_t *rowid); + (*get_denomination_revocation)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_MasterSignatureP *master_sig, + uint64_t *rowid); /** - * Select all of those deposits in the database for which we do - * not have a wire transfer (or a refund) and which should have - * been deposited between @a start_date and @a end_date. + * Select all (batch) deposits in the database + * above a given @a min_batch_deposit_serial_id. * * @param cls closure - * @param start_date lower bound on the requested wire execution date - * @param end_date upper bound on the requested wire execution date + * @param min_batch_deposit_serial_id only return entries strictly above this row (and in order) * @param cb function to call on all such deposits * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_deposits_missing_wire)(void *cls, - struct GNUNET_TIME_Absolute start_date, - struct GNUNET_TIME_Absolute end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls); + (*select_batch_deposits_missing_wire)( + void *cls, + uint64_t min_batch_deposit_serial_id, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls); + + + /** + * Select all aggregation tracking IDs in the database + * above a given @a min_tracking_serial_id. + * + * @param cls closure + * @param min_tracking_serial_id only return entries strictly above this row (and in order) + * @param cb function to call on all such aggregations + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_aggregations_above_serial)( + void *cls, + uint64_t min_tracking_serial_id, + TALER_EXCHANGEDB_AggregationCallback cb, + void *cb_cls); + + + /** + * Return any applicable justification as to why + * a wire transfer might have been held. Used + * by the auditor to determine if a wire transfer + * is legitimately stalled. + * + * @param cls closure + * @param wire_target_h_payto effected target account + * @param[out] payto_uri target account URI, set to NULL if unknown + * @param[out] kyc_pending set to string describing missing KYC data + * @param[out] status set to AML status + * @param[out] aml_limit set to AML limit, or invalid amount for none + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_justification_for_missing_wire)( + void *cls, + const struct TALER_PaytoHashP *wire_target_h_payto, + char **payto_uri, + char **kyc_pending, + enum TALER_AmlDecisionState *status, + struct TALER_Amount *aml_limit); /** @@ -3551,9 +5674,10 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*lookup_auditor_timestamp)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - struct GNUNET_TIME_Absolute *last_date); + (*lookup_auditor_timestamp)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date); /** @@ -3567,10 +5691,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*lookup_auditor_status)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - char **auditor_url, - bool *enabled); + (*lookup_auditor_status)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled); /** @@ -3585,11 +5710,12 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Absolute start_date); + (*insert_auditor)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp start_date); /** @@ -3605,12 +5731,13 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_auditor)(void *cls, - const struct TALER_AuditorPublicKeyP *auditor_pub, - const char *auditor_url, - const char *auditor_name, - struct GNUNET_TIME_Absolute change_date, - bool enabled); + (*update_auditor)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp change_date, + bool enabled); /** @@ -3624,7 +5751,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*lookup_wire_timestamp)(void *cls, const char *payto_uri, - struct GNUNET_TIME_Absolute *last_date); + struct GNUNET_TIME_Timestamp *last_date); /** @@ -3632,17 +5759,27 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param payto_uri wire account of the exchange + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account + * @param credit_restrictions JSON array with credit restrictions on the account * @param start_date date when the account was added by the offline system * (only to be used for replay detection) * @param master_sig public signature affirming the existence of the account, * must be of purpose #TALER_SIGNATURE_MASTER_WIRE_DETAILS + * @param bank_label label to show this entry under in the UI, can be NULL + * @param priority determines order in which entries are shown in the UI * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_wire)(void *cls, const char *payto_uri, - struct GNUNET_TIME_Absolute start_date, - const struct TALER_MasterSignatureP *master_sig); + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); /** @@ -3650,15 +5787,27 @@ struct TALER_EXCHANGEDB_Plugin * * @param cls closure * @param payto_uri account the update is about + * @param conversion_url URL of a conversion service, NULL if there is no conversion + * @param debit_restrictions JSON array with debit restrictions on the account; NULL allowed if not @a enabled + * @param credit_restrictions JSON array with credit restrictions on the account; NULL allowed if not @a enabled * @param change_date date when the account status was last changed * (only to be used for replay detection) + * @param master_sig master signature to store, can be NULL (if @a enabled is false) + * @param bank_label label to show this entry under in the UI, can be NULL + * @param priority determines order in which entries are shown in the UI * @param enabled true to enable, false to disable (the actual change) * @return transaction status code */ enum GNUNET_DB_QueryStatus (*update_wire)(void *cls, const char *payto_uri, - struct GNUNET_TIME_Absolute change_date, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + struct GNUNET_TIME_Timestamp change_date, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority, bool enabled); @@ -3694,6 +5843,20 @@ struct TALER_EXCHANGEDB_Plugin /** + * Obtain information about the global fee structure of the exchange. + * + * @param cls closure + * @param cb function to call on each fee entry + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_global_fees)(void *cls, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls); + + + /** * Store information about a revoked online signing key. * * @param cls closure @@ -3734,7 +5897,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*lookup_denomination_key)( void *cls, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta); @@ -3751,7 +5914,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*add_denomination_key)( void *cls, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, const struct TALER_MasterSignatureP *master_sig); @@ -3802,7 +5965,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_auditor_denom_sig)( void *cls, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_AuditorPublicKeyP *auditor_pub, const struct TALER_AuditorSignatureP *auditor_sig); @@ -3819,7 +5982,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_auditor_denom_sig)( void *cls, - const struct TALER_DenominationHash *h_denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, const struct TALER_AuditorPublicKeyP *auditor_pub, struct TALER_AuditorSignatureP *auditor_sig); @@ -3831,10 +5994,7 @@ struct TALER_EXCHANGEDB_Plugin * @param wire_method the wire method to lookup fees for * @param start_time starting time of fee * @param end_time end time of fee - * @param[out] wire_fee wire fee for that time period; if - * different wire fee exists within this time - * period, an 'invalid' amount is returned. - * @param[out] closing_fee wire fee for that time period; if + * @param[out] fees set to wire fees for that time period; if * different wire fee exists within this time * period, an 'invalid' amount is returned. * @return transaction status code @@ -3843,10 +6003,34 @@ struct TALER_EXCHANGEDB_Plugin (*lookup_wire_fee_by_time)( void *cls, const char *wire_method, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee); + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_WireFeeSet *fees); + + + /** + * Lookup information about known global fees. + * + * @param cls closure + * @param start_time starting time of fee + * @param end_time end time of fee + * @param[out] fees set to wire fees for that time period; if + * different global fee exists within this time + * period, an 'invalid' amount is returned. + * @param[out] purse_timeout set to when unmerged purses expire + * @param[out] history_expiration set to when we expire reserve histories + * @param[out] purse_account_limit set to number of free purses + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_global_fee_by_time)( + void *cls, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit); /** @@ -3888,6 +6072,7 @@ struct TALER_EXCHANGEDB_Plugin * Insert record set into @a table. Used in exchange-auditor database * replication. * + memset (&awc, 0, sizeof (awc)); * @param cls closure * @param tb table data to insert * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if @@ -3918,6 +6103,20 @@ struct TALER_EXCHANGEDB_Plugin uint64_t *start_row, uint64_t *end_row); + /** + * Function called to abort work on a shard. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to abort a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*abort_shard)(void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row); /** * Function called to persist that work on a shard was completed. @@ -3979,12 +6178,1067 @@ struct TALER_EXCHANGEDB_Plugin * changed. * * @param cls the @e cls of this struct with the plugin-specific state + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on failure + */ + enum GNUNET_GenericReturnValue + (*delete_shard_locks)(void *cls); + + + /** + * Function called to save the manifest of an extension + * (age-restriction, policy-extension, ...) + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param extension_name the name of the extension + * @param manifest JSON object of the Manifest as string, maybe NULL (== disabled extension) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*set_extension_manifest)(void *cls, + const char *extension_name, + const char *manifest); + + + /** + * Function called to retrieve the manifest of an extension + * (age-restriction, policy-extension, ...) + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param extension_name the name of the extension + * @param[out] manifest Manifest of the extension in JSON encoding, maybe NULL (== disabled extension) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_extension_manifest)(void *cls, + const char *extension_name, + char **manifest); + + + /** + * Function called to store configuration data about a partner + * exchange that we are federated with. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param master_pub public offline signing key of the partner exchange + * @param start_date when does the following data start to be valid + * @param end_date when does the validity end (exclusive) + * @param wad_frequency how often do we do exchange-to-exchange settlements? + * @param wad_fee how much do we charge for transfers to the partner + * @param partner_base_url base URL of the partner exchange + * @param master_sig signature with our offline signing key affirming the above + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_partner)(void *cls, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Function called to persist an encrypted contract associated with a reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param econtract the encrypted contract + * @param[out] econtract_sig set to the signature over the encrypted contract + * @param[out] in_conflict set to true if @a econtract + * conflicts with an existing contract; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_contract)(void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_EncryptedContract *econtract, + bool *in_conflict); + + + /** + * Function called to retrieve an encrypted contract. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pub_ckey set to the ephemeral DH used to encrypt the contract, key used to lookup the contract by + * @param[out] purse_pub public key of the purse of the contract + * @param[out] econtract_sig set to the signature over the encrypted contract + * @param[out] econtract_size set to the number of bytes in @a econtract + * @param[out] econtract set to the encrypted contract on success, to be freed by the caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_contract)( + void *cls, + const struct TALER_ContractDiffiePublicP *pub_ckey, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseContractSignatureP *econtract_sig, + size_t *econtract_size, + void **econtract); + + + /** + * Function called to retrieve an encrypted contract. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub key to lookup the contract by + * @param[out] econtract set to the encrypted contract on success, to be freed by the caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_contract_by_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_EncryptedContract *econtract); + + + /** + * Function called to create a new purse with certain meta data. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the new purse + * @param merge_pub public key providing the merge capability + * @param purse_expiration time when the purse will expire + * @param h_contract_terms hash of the contract for the purse + * @param age_limit age limit to enforce for payments into the purse + * @param flags flags for the operation + * @param purse_fee fee we are allowed to charge to the reserve (depending on @a flags) + * @param amount target amount (with fees) to be put into the purse + * @param purse_sig signature with @a purse_pub's private key affirming the above + * @param[out] in_conflict set to true if the meta data + * conflicts with an existing purse; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_purse_request)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + const struct TALER_Amount *amount, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *in_conflict); + + + /** + * Function called to clean up one expired purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param start_time select purse expired after this time + * @param end_time select purse expired before this time + * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no purse expired in the given time interval). + */ + enum GNUNET_DB_QueryStatus + (*expire_purse)( + void *cls, + struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Absolute end_time); + + + /** + * Function called to obtain information about a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the new purse + * @param[out] purse_creation set to time when the purse was created + * @param[out] purse_expiration set to time when the purse will expire + * @param[out] amount set to target amount (with fees) to be put into the purse + * @param[out] deposited set to actual amount put into the purse so far + * @param[out] h_contract_terms set to hash of the contract for the purse + * @param[out] merge_timestamp set to time when the purse was merged, or NEVER if not + * @param[out] purse_deleted set to true if purse was deleted + * @param[out] purse_refunded set to true if purse was refunded (after expiration) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_creation, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_Amount *amount, + struct TALER_Amount *deposited, + struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp *merge_timestamp, + bool *purse_deleted, + bool *purse_refunded); + + + /** + * Function called to return meta data about a purse by the + * purse public key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the purse + * @param[out] merge_pub public key representing the merge capability + * @param[out] purse_expiration when would an unmerged purse expire + * @param[out] h_contract_terms contract associated with the purse + * @param[out] age_limit the age limit for deposits into the purse + * @param[out] target_amount amount to be put into the purse + * @param[out] balance amount put so far into the purse + * @param[out] purse_sig signature of the purse over the initialization data + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_purse_request)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig); + + + /** + * Function called to return meta data about a purse by the + * merge capability key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param merge_pub public key representing the merge capability + * @param[out] purse_pub public key of the purse + * @param[out] purse_expiration when would an unmerged purse expire + * @param[out] h_contract_terms contract associated with the purse + * @param[out] age_limit the age limit for deposits into the purse + * @param[out] target_amount amount to be put into the purse + * @param[out] balance amount put so far into the purse + * @param[out] purse_sig signature of the purse over the initialization data + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_by_merge_pub)( + void *cls, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig); + + + /** + * Function called to execute a transaction crediting + * a purse with @a amount from @a coin_pub. Reduces the + * value of @a coin_pub and increase the balance of + * the @a purse_pub purse. If the balance reaches the + * target amount and the purse has been merged, triggers + * the updates of the reserve/account balance. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to credit + * @param coin_pub coin to deposit (debit) + * @param amount fraction of the coin's value to deposit + * @param coin_sig signature affirming the operation + * @param amount_minus_fee amount to add to the purse + * @param[out] balance_ok set to false if the coin's + * remaining balance is below @a amount; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @param[out] too_late it is too late to deposit into this purse + * @param[out] conflict the same coin was deposited into + * this purse with a different amount already + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_deposit)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *amount, + const struct TALER_CoinSpendSignatureP *coin_sig, + const struct TALER_Amount *amount_minus_fee, + bool *balance_ok, + bool *too_late, + bool *conflict); + + + /** + * Function called to explicitly delete a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to delete + * @param purse_sig signature affirming the deletion + * @param[out] decided set to true if the purse was + * already decided and thus could not be deleted + * @param[out] found set to true if the purse was found + * (if false, purse could not be deleted) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_delete)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *decided, + bool *found); + + + /** + * Set the current @a balance in the purse + * identified by @a purse_pub. Used by the auditor + * to update the balance as calculated by the auditor. + * + * @param cls closure + * @param purse_pub public key of a purse + * @param balance new balance to store under the purse + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*set_purse_balance)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); + + + /** + * Function called to obtain a coin deposit data from + * depositing the coin into a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to credit + * @param coin_pub coin to deposit (debit) + * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] h_denom_pub set to hash of denomination of the coin + * @param[out] phac set to hash of age restriction on the coin + * @param[out] coin_sig set to signature affirming the operation + * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_purse_deposit)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, + struct TALER_CoinSpendSignatureP *coin_sig, + char **partner_url); + + + /** + * Function called to approve merging a purse into a + * reserve by the respective purse merge key. The purse + * must not have been merged into a different reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to merge + * @param merge_sig signature affirming the merge + * @param merge_timestamp time of the merge + * @param reserve_sig signature of the reserve affirming the merge + * @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us + * @param reserve_pub public key of the reserve to credit + * @param[out] no_partner set to true if @a partner_url is unknown + * @param[out] no_balance set to true if the @a purse_pub is not paid up yet + * @param[out] no_reserve set to true if the @a reserve_pub is not known + * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_merge)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const char *partner_url, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *no_partner, + bool *no_balance, + bool *in_conflict); + + + /** + * Function called insert request to merge a purse into a reserve by the + * respective purse merge key. The purse must not have been merged into a + * different reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to merge + * @param merge_sig signature affirming the merge + * @param merge_timestamp time of the merge + * @param reserve_sig signature of the reserve affirming the merge + * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota + * @param reserve_pub public key of the reserve to credit + * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve + * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_reserve_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_Amount *purse_fee, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *in_conflict, + bool *no_reserve, + bool *insufficient_funds); + + + /** + * Function called to approve merging of a purse with + * an account, made by the receiving account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the purse + * @param[out] merge_sig set to the signature confirming the merge + * @param[out] merge_timestamp set to the time of the merge + * @param[out] partner_url set to the URL of the target exchange, or NULL if the target exchange is us. To be freed by the caller. + * @param[out] reserve_pub set to the public key of the reserve/account being credited + * @param[out] refunded set to true if purse was refunded + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_merge)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergeSignatureP *merge_sig, + struct GNUNET_TIME_Timestamp *merge_timestamp, + char **partner_url, + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded); + + + /** + * Function called to initiate closure of an account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the account to close + * @param payto_uri where to wire the funds + * @param reserve_sig signature affiming that the account is to be closed + * @param request_timestamp timestamp of the close request + * @param balance balance at the time of closing + * @param closing_fee closing fee to charge + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_close_request)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *payto_uri, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *balance, + const struct TALER_Amount *closing_fee); + + + /** + * Function called to persist a request to drain profits. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wtid wire transfer ID to use + * @param account_section account to drain + * @param payto_uri account to wire funds to + * @param request_timestamp time of the signature + * @param amount amount to wire + * @param master_sig signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + const char *account_section, + const char *payto_uri, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *amount, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Function called to get information about a profit drain event. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wtid wire transfer ID to look up drain event for + * @param[out] serial set to serial ID of the entry + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t *serial, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); + + + /** + * Get profit drain operation ready to execute. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param[out] serial set to serial ID of the entry + * @param[out] wtid set set to wire transfer ID to use + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*delete_revolving_shards)(void *cls); + (*profit_drains_get_pending)( + void *cls, + uint64_t *serial, + struct TALER_WireTransferIdentifierRawP *wtid, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); + /** + * Set profit drain operation to finished. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param serial serial ID of the entry to mark finished + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*profit_drains_set_finished)( + void *cls, + uint64_t serial); + + + /** + * Insert KYC requirement for @a h_payto account into table. + * + * @param cls closure + * @param requirements requirements that must be checked + * @param h_payto account that must be KYC'ed + * @param reserve_pub if account is a reserve, its public key, NULL otherwise + * @param[out] requirement_row set to legitimization requirement row for this check + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_requirement_for_account)( + void *cls, + const char *requirements, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *requirement_row); + + + /** + * Begin KYC requirement process. + * + * @param cls closure + * @param h_payto account that must be KYC'ed + * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param[out] process_row row the process is stored under + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id, + uint64_t *process_row); + + + /** + * Fetch information about pending KYC requirement process. + * + * @param cls closure + * @param h_payto account that must be KYC'ed + * @param provider_section provider that must be checked + * @param[out] redirect_url set to redirect URL for the process + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_pending_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + char **redirect_url); + + + /** + * Update KYC process with updated provider-linkage and/or + * expiration data. + * + * @param cls closure + * @param process_row row to select by + * @param provider_section provider that must be checked (technically redundant) + * @param h_payto account that must be KYC'ed (helps access by shard, otherwise also redundant) + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param redirect_url where the user should be redirected to start the KYC process + * @param expiration how long is this KYC check set to be valid (in the past if invalid) + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*update_kyc_process_by_row)( + void *cls, + uint64_t process_row, + const char *provider_section, + const struct TALER_PaytoHashP *h_payto, + const char *provider_account_id, + const char *provider_legitimization_id, + const char *redirect_url, + struct GNUNET_TIME_Absolute expiration); + + + /** + * Lookup KYC requirement. + * + * @param cls closure + * @param legi_row identifies requirement to look up + * @param[out] requirements space-separated list of requirements + * @param[out] aml_status set to the AML status of the account + * @param[out] h_payto account that must be KYC'ed + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_kyc_requirement_by_row)( + void *cls, + uint64_t requirement_row, + char **requirements, + enum TALER_AmlDecisionState *aml_status, + struct TALER_PaytoHashP *h_payto); + + + /** + * Lookup KYC process meta data. + * + * @param cls closure + * @param provider_section provider that must be checked + * @param h_payto account that must be KYC'ed + * @param[out] process_row set to row with the legitimization data + * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) + * @param[out] provider_account_id provider account ID + * @param[out] provider_legitimization_id provider legitimization ID + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_kyc_process_by_account)( + void *cls, + const char *provider_section, + const struct TALER_PaytoHashP *h_payto, + uint64_t *process_row, + struct GNUNET_TIME_Absolute *expiration, + char **provider_account_id, + char **provider_legitimization_id); + + + /** + * Lookup an + * @a h_payto by @a provider_legitimization_id. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @param[out] process_row identifies the legitimization process on our end + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*kyc_provider_account_lookup)( + void *cls, + const char *provider_section, + const char *provider_legitimization_id, + struct TALER_PaytoHashP *h_payto, + uint64_t *process_row); + + + /** + * Call us on KYC processes satisfied for the given + * account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_satisfied_kyc_processes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_SatisfiedProviderCallback spc, + void *spc_cls); + + + /** + * Call us on KYC legitimization processes satisfied and not expired for the + * given account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param lpc function to call for each satisfied KYC legitimization process + * @param lpc_cls closure for @a lpc + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_kyc_reference)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_LegitimizationProcessCallback lpc, + void *lpc_cls); + + + /** + * Call @a kac on withdrawn amounts after @a time_limit which are relevant + * for a KYC trigger for a the (debited) account identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_withdraw_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on aggregated amounts after @a time_limit which are relevant for a + * KYC trigger for a the (credited) account identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_aggregation_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on merged reserve amounts after @a time_limit which are relevant for a + * KYC trigger for a the wallet identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_merge_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Store KYC attribute data, update KYC process status and + * AML status for the given account. + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param kyc_prox key for similarity search + * @param provider_section provider that must be checked + * @param num_checks how many checks do these attributes satisfy + * @param satisfied_checks array of checks satisfied by these attributes + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + * @param require_aml true to trigger AML + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_attributes)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const struct GNUNET_ShortHashCode *kyc_prox, + const char *provider_section, + unsigned int num_checks, + const char *satisfied_checks[static num_checks], + uint32_t birthday, + struct GNUNET_TIME_Timestamp collection_time, + const char *provider_account_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration_time, + size_t enc_attributes_size, + const void *enc_attributes, + bool require_aml); + + + /** + * Lookup similar KYC attribute data. + * + * @param cls closure + * @param kyc_prox key for similarity search + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_similar_kyc_attributes)( + void *cls, + const struct GNUNET_ShortHashCode *kyc_prox, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Lookup KYC attribute data for a specific account. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_kyc_attributes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Insert AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param master_sig offline signature affirming the AML officer + * @param decider_name full name of the staff member + * @param is_active true to enable, false to set as inactive + * @param read_only true to set read-only access + * @param last_change when was the change made effective + * @param[out] previous_change when was the previous change made + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_MasterSignatureP *master_sig, + const char *decider_name, + bool is_active, + bool read_only, + struct GNUNET_TIME_Timestamp last_change, + struct GNUNET_TIME_Timestamp *previous_change); + + + /** + * Test if the given AML staff member is active + * (at least read-only). + * + * @param cls closure + * @param decider_pub public key of the staff member + * @return database transaction status, if member is unknown or not active, 1 if member is active + */ + enum GNUNET_DB_QueryStatus + (*test_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub); + + + /** + * Fetch AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param[out] master_sig offline signature affirming the AML officer + * @param[out] decider_name full name of the staff member + * @param[out] is_active true to enable, false to set as inactive + * @param[out] read_only true to set read-only access + * @param[out] last_change when was the change made effective + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + struct TALER_MasterSignatureP *master_sig, + char **decider_name, + bool *is_active, + bool *read_only, + struct GNUNET_TIME_Absolute *last_change); + + + /** + * Obtain the current AML threshold set for an account. + * + * @param cls closure + * @param h_payto account for which the AML threshold is stored + * @param[out] decision set to current AML decision + * @param[out] threshold set to the existing threshold + * @return database transaction status, 0 if no threshold was set + */ + enum GNUNET_DB_QueryStatus + (*select_aml_threshold)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState *decision, + struct TALER_EXCHANGEDB_KycStatus *kyc, + struct TALER_Amount *threshold); + + + /** + * Trigger AML process, an account has crossed the threshold. Inserts or + * updates the AML status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param threshold_crossed existing threshold that was crossed + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*trigger_aml_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold_crossed); + + + /** + * Lookup AML decisions that have a particular state. + * + * @param cls closure + * @param decision which decision states to filter by + * @param row_off offset to start from + * @param forward true to go forward in time, false to go backwards + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_process)( + void *cls, + enum TALER_AmlDecisionState decision, + uint64_t row_off, + uint64_t limit, + bool forward, + TALER_EXCHANGEDB_AmlStatusCallback cb, + void *cb_cls); + + + /** + * Lookup AML decision history for a particular account. + * + * @param cls closure + * @param h_payto which account should we return the AML decision history for + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_history)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlHistoryCallback cb, + void *cb_cls); + + + /** + * Insert an AML decision. Inserts into AML history and insert or updates AML + * status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param kyc_requirements specific KYC requirements being imposed + * @param requirements_row row in the KYC table for this process, 0 for none + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] last_date set to the previous decision time; + * the INSERT is not performed if @a last_date is not before @a decision_time + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_decision)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const json_t *kyc_requirements, + uint64_t requirements_row, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig, + bool *invalid_officer, + struct GNUNET_TIME_Timestamp *last_date); + + + /** + * Update KYC process status to finished (and failed). + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_failure)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id); + + /** + * Function called to inject auditor triggers into the + * database, triggering the real-time auditor upon + * relevant INSERTs. + * + * @param cls closure + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on DB errors + */ + enum GNUNET_GenericReturnValue + (*inject_auditor_triggers)(void *cls); + }; #endif /* _TALER_EXCHANGE_DB_H */ diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h index c4e9d1f5a..1eb567f72 100644 --- a/src/include/taler_extensions.h +++ b/src/include/taler_extensions.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -22,51 +22,365 @@ #define TALER_EXTENSIONS_H #include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" +#include "taler_extensions_policy.h" #define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-" -enum TALER_EXTENSION_ReturnValue +enum TALER_Extension_Type { - TALER_EXTENSION_OK = 0, - TALER_EXTENSION_ERROR_PARSING = 1, - TALER_EXTENSION_ERROR_INVALID = 2, - TALER_EXTENSION_ERROR_SYS = 3 + TALER_Extension_PolicyNull = 0, + + TALER_Extension_AgeRestriction = 1, + TALER_Extension_PolicyMerchantRefund = 2, + TALER_Extension_PolicyBrandtVickeryAuction = 3, + TALER_Extension_PolicyEscrowedPayment = 4, + + TALER_Extension_MaxPredefined = 5 // Must be last of the predefined }; +/* Forward declarations */ +enum TALER_PolicyFulfillmentState; +struct TALER_PolicyFulfillmentOutcome; + +/* + * @brief Represents the implementation of an extension. + * + * An "Extension" is an optional feature for the Exchange. + * There are only two types of extensions: + * + * a) Age restriction: This is a special feature that directly interacts with + * denominations and coins, but is not define policies during deposits, see b). + * The implementation of this extension doesn't have to implement any of the + * http- or depost-handlers in the struct. + * + * b) Policies for deposits: These are extensions that define policies (such + * as refund, escrow or auctions) for deposit requests. These extensions have + * to implement at least the deposit- and post-http-handler in the struct to be + * functional. + * + * In addition to the handlers defined in this struct, an extension must also + * be a plugin in the GNUNET_Plugin sense. That is, it must implement the + * functions + * 1: (void *ext)libtaler_extension_<name>_init(void *cfg) + * and + * 2: (void *)libtaler_extension_<name>_done(void *) + * + * In 1:, the input will be the GNUNET_CONFIGURATION_Handle to the TALER + * configuration and the output must be the struct TALER_Extension * on + * success, NULL otherwise. + * + * In 2:, no arguments are passed and NULL is expected to be returned. + */ +struct TALER_Extension +{ + /** + * Type of the extension. Only one extension of a type can be loaded + * at any time. + */ + enum TALER_Extension_Type type; + + /** + * The name of the extension, must be unique among all loaded extensions. It + * is used in URLs for /extension/$NAME as well. + */ + char *name; + + /** + * Criticality of the extension. It has the same semantics as "critical" has + * for extensions in X.509: + * - if "true", the client must "understand" the extension before proceeding, + * - if "false", clients can safely skip extensions they do not understand. + * (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2) + */ + bool critical; + + /** + * Version of the extension must be provided in Taler's protocol version ranges notation, see + * https://docs.taler.net/core/api-common.html#protocol-version-ranges + */ + char *version; + + /** + * If the extension is marked as enabled, it will be listed in the + * "extensions" field in the "/keys" response. + */ + bool enabled; + + /** + * Opaque (public) configuration object, set by the extension. + */ + void *config; + + + /** + * @brief Handler to to disable the extension. + * + * @param ext The current extension object + */ + void (*disable)(struct TALER_Extension *ext); + + /** + * @brief Handler to read an extension-specific configuration in JSON + * encoding and enable the extension. Must be implemented by the extension. + * + * @param[in] ext The extension object. If NULL, the configuration will only be checked. + * @param[in,out] config A JSON blob + * @return GNUNET_OK if the json was a valid configuration for the extension. + */ + enum GNUNET_GenericReturnValue (*load_config)( + const json_t *config, + struct TALER_Extension *ext); + + /** + * @brief Handler to return the manifest of the extension in JSON encoding. + * + * See + * https://docs.taler.net/design-documents/006-extensions.html#tsref-type-Extension + * for the definition. + * + * @param ext The extension object + * @return The JSON encoding of the extension, if enabled, NULL otherwise. + */ + json_t *(*manifest)( + const struct TALER_Extension *ext); + + /* ========================= + * Policy related handlers + * ========================= + */ + + /** + * @brief Handler to check an incoming policy and create a + * TALER_PolicyDetails. Can be NULL; + * + * When a deposit request refers to this extension in its policy + * (see https://docs.taler.net/core/api-exchange.html#deposit), this handler + * will be called before the deposit transaction. + * + * @param[in] currency Currency used in the exchange + * @param[in] policy_json Details about the policy, provided by the client + * during a deposit request. + * @param[out] details On success, will contain the details to the policy, + * evaluated by the corresponding policy handler. + * @param[out] error_hint On error, will contain a hint + * @return GNUNET_OK if the data was accepted by the extension. + */ + enum GNUNET_GenericReturnValue (*create_policy_details)( + const char *currency, + const json_t *policy_json, + struct TALER_PolicyDetails *details, + const char **error_hint); + + /** + * @brief Handler for POST-requests to the /extensions/$name endpoint. Can be NULL. + * + * @param[in] root The JSON body from the request + * @param[in] args Additional query parameters of the request. + * @param[in,out] details List of policy details related to the incoming fulfillment proof + * @param[in] details_len Size of the list @e details + * @param[out] output JSON output to return to the client + * @return GNUNET_OK on success. + */ + enum GNUNET_GenericReturnValue (*policy_post_handler)( + const json_t *root, + const char *const args[], + struct TALER_PolicyDetails *details, + size_t details_len, + json_t **output); + + /** + * @brief Handler for GET-requests to the /extensions/$name endpoint. Can be NULL. + * + * @param connection The current connection + * @param root The JSON body from the request + * @param args Additional query parameters of the request. + * @return MDH result + */ + MHD_RESULT (*policy_get_handler)( + struct MHD_Connection *connection, + const char *const args[]); +}; + + +/* + * @brief simply linked list of extensions + */ + +struct TALER_Extensions +{ + struct TALER_Extensions *next; + const struct TALER_Extension *extension; +}; + +/** + * Generic functions for extensions + */ + +/** + * @brief Loads the extensions as shared libraries, as specified in the given + * TALER configuration. + * + * @param cfg Handle to the TALER configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were found + * or any particular configuration couldn't be parsed. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_init ( + const struct GNUNET_CONFIGURATION_Handle *cfg); + +/* + * @brief Parses a given JSON object as an extension manifest. + * + * @param[in] obj JSON object to parse as an extension manifest + * @param{out] critical will be set to 1 if the extension is critical according to obj + * @param[out] version will be set to the version of the extension according to obj + * @param[out] config will be set to the configuration of the extension according to obj + * @return OK on success, Error otherwise + */ +enum GNUNET_GenericReturnValue +TALER_extensions_parse_manifest ( + json_t *obj, + int *critical, + const char **version, + json_t **config); + +/* + * @brief Loads extensions according to the manifests. + * + * The JSON object must be of type ExtensionsManifestsResponse as described + * in https://docs.taler.net/design-documents/006-extensions.html#exchange + * + * @param cfg JSON object containing the manifests for all extensions + * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were + * found or any particular configuration couldn't be parsed. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_load_manifests ( + const json_t *manifests); + /* - * TALER Age Restriction Extensions + * @brief Returns the head of the linked list of extensions. + */ +const struct TALER_Extensions * +TALER_extensions_get_head (void); + +/** + * @brief Finds and returns a supported extension by a given type. + * + * @param type of the extension to lookup + * @return extension found, or NULL (should not happen!) + */ +const struct TALER_Extension * +TALER_extensions_get_by_type ( + enum TALER_Extension_Type type); + + +/** + * @brief Finds and returns a supported extension by a given name. + * + * @param name name of the extension to lookup + * @return the extension, if found, NULL otherwise + */ +const struct TALER_Extension * +TALER_extensions_get_by_name ( + const char *name); + +/** + * @brief Check if a given type of an extension is enabled + * + * @param type type of to check + * @return true enabled, false if not enabled, will assert if type is not found. + */ +bool +TALER_extensions_is_enabled_type ( + enum TALER_Extension_Type type); + +/** + * @brief Check if an extension is enabled + * + * @param extension The extension handler. + * @return true enabled, false if not enabled, will assert if type is not found. + */ +bool +TALER_extensions_is_enabled ( + const struct TALER_Extension *extension); + +/* + * Verify the signature of a given JSON object for extensions with the master + * key of the exchange. + * + * The JSON object must be of type ExtensionsManifestsResponse as described in + * https://docs.taler.net/design-documents/006-extensions.html#exchange + * + * @param extensions JSON object with the extension configuration + * @param extensions_sig signature of the hash of the JSON object + * @param master_pub public key to verify the signature + * @return GNUNET_OK on success, GNUNET_SYSERR when hashing of the JSON fails + * and GNUNET_NO if the signature couldn't be verified. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_verify_manifests_signature ( + const json_t *manifests, + struct TALER_MasterSignatureP *extensions_sig, + struct TALER_MasterPublicKeyP *master_pub); + + +/* + * TALER Age Restriction Extension + * + * This extension is special insofar as it directly interacts with coins and + * denominations. + * + * At the same time, it doesn't implement and http- or deposit-handlers. */ #define TALER_EXTENSION_SECTION_AGE_RESTRICTION (TALER_EXTENSION_SECTION_PREFIX \ - "agerestriction") + "age_restriction") /** * The default age mask represents the age groups * 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-20, 21-... */ -#define TALER_EXTENSION_DEFAULT_AGE_MASK (1 | 1 << 8 | 1 << 10 | 1 << 12 | 1 << \ - 14 | 1 << 16 | 1 << 18 | 1 << 21) +#define TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS "8:10:12:14:16:18:21" + + +/* + * @brief Configuration for Age Restriction + */ +struct TALER_AgeRestrictionConfig +{ + struct TALER_AgeMask mask; + uint8_t num_groups; +}; + /** - * @param groups String representation of age groups, like: "8:10:12:14:16:18:21" - * @param[out] mask Mask representation for age restriction. - * @return Error, if age groups were invalid, OK otherwise. + * @brief Retrieve the age restriction configuration + * + * @return age restriction configuration if present, otherwise NULL. + */ +const struct TALER_AgeRestrictionConfig * +TALER_extensions_get_age_restriction_config (void); + +/** + * @brief Check if age restriction is enabled + * + * @return true, if age restriction is loaded, configured and enabled; otherwise false. */ -enum TALER_EXTENSION_ReturnValue -TALER_parse_age_group_string (char *groups, - struct TALER_AgeMask *mask); +bool +TALER_extensions_is_age_restriction_enabled (void); /** + * @brief Return the age mask for age restriction * - * @param cfg - * @param[out] mask for age restriction, will be set to 0 if age restriction is disabled. - * @return Error if extension for age restriction was set but age groups were - * invalid, OK otherwise. + * @return configured age mask, if age restriction is loaded, configured and enabled; otherwise zero mask. */ -enum TALER_EXTENSION_ReturnValue -TALER_get_age_mask (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct TALER_AgeMask *mask); +struct TALER_AgeMask +TALER_extensions_get_age_restriction_mask (void); #endif diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h new file mode 100644 index 000000000..b10c0d8a2 --- /dev/null +++ b/src/include/taler_extensions_policy.h @@ -0,0 +1,205 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file include/taler_extensions_policy.h + * @brief Interface for policy extensions + * @author Özgür Kesim + */ +#ifndef TALER_EXTENSIONS_POLICY_H +#define TALER_EXTENSIONS_POLICY_H + +#include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" + +/* + * @brief Describes the states of fulfillment of a policy bound to a deposit + * NOTE: These values must be in sync with their use in stored procedures, f.e. + * exchange_do_insert_or_update_policy_details. + */ +enum TALER_PolicyFulfillmentState +{ + /* Initial state of an fulfillment, before any other state. */ + TALER_PolicyFulfillmentInitial = 0, + + /* General error state of an fulfillment. */ + TALER_PolicyFulfillmentFailure = 1, + + /* The policy is not yet ready due to insufficient funding. More deposits are + * necessary for it to become ready . */ + TALER_PolicyFulfillmentInsufficient = 2, + + /* The policy is funded and ready, pending */ + TALER_PolicyFulfillmentReady = 3, + + /* Policy is provably fulfilled. */ + TALER_PolicyFulfillmentSuccess = 4, + + /* Policy fulfillment has timed out */ + TALER_PolicyFulfillmentTimeout = 5, + + TALER_PolicyFulfillmentStateCount = TALER_PolicyFulfillmentTimeout + 1 +}; + + +/* + * @brief Returns a string representation of the state of a policy fulfillment + */ +const char * +TALER_policy_fulfillment_state_str (enum TALER_PolicyFulfillmentState state); + + +/* @brief Details of a policy for a deposit request */ +struct TALER_PolicyDetails +{ + /* Hash code that should be used for the .policy_hash_code field when + * this policy is saved in the policy_details table. */ + struct GNUNET_HashCode hash_code; + + /* Content of the policy in its original JSON form */ + json_t *policy_json; + + /* When the deadline is met and the policy is still in "Ready" state, + * a timeout-handler will transfer the amount + * (total_amount - policy_fee - refreshable_amount) + * to the payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins */ + struct GNUNET_TIME_Timestamp deadline; + + /* The amount to which this policy commits to. It must be at least as + * large as @e policy_fee. */ + struct TALER_Amount commitment; + + /* The total sum of contributions from coins so far to fund this + * policy. It must be at least as large as @commitment in order to be + * sufficiently funded. */ + struct TALER_Amount accumulated_total; + + /* The fee from the exchange for handling the policy. It is due when + * the state changes to Timeout or Success. */ + struct TALER_Amount policy_fee; + + /* The amount that will be transferred to the payto-URIs from the + * corresponding deposits when the fulfillment state changes to Timeout + * or Success. Note that a fulfillment handler can alter this upon + * arrival of a proof of fulfillment. The remaining amount + * (accumulated_amount - policy_amount - transferable_amount) */ + struct TALER_Amount transferable_amount; + + /* The state of fulfillment of a policy. + * - If the state is Insufficient, the client is required to call + * /deposit -maybe multiple times- with enough coins and the same + * policy details in order to reach the required amount. The state is + * then changed to Ready. + * - If the state changes to Timeout or Success, a handler will transfer + * the amount (total_amount - policy_fee - refreshable_amount) to the + * payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins. */ + enum TALER_PolicyFulfillmentState fulfillment_state; + + /* If there is a proof of fulfillment, the row ID from the + * policy_fulfillment table */ + uint64_t policy_fulfillment_id; + bool no_policy_fulfillment_id; +}; + +/* + * @brief All information required for the database transaction when handling a + * proof of fulfillment request. + */ +struct TALER_PolicyFulfillmentTransactionData +{ + /* The incoming proof, provided by a client */ + const json_t *proof; + + /* The Hash of the proof */ + struct GNUNET_HashCode h_proof; + + /* The timestamp of retrieval of the proof */ + struct GNUNET_TIME_Timestamp timestamp; + + /* The ID of the proof in the policy_fulfillment table. Will be set + * during the transaction. Needed to fill the table + * policy_details_fulfillments. */ + uint64_t fulfillment_id; + + /* The list of policy details. Will be updated by the policy handler */ + struct TALER_PolicyDetails *details; + size_t details_count; +}; + + +/* + * @brief Extracts policy details from the deposit's policy options and the policy extensions + * + * @param[in] currency Currency used in the exchange + * @param[in] policy_options JSON of the policy options from a deposit request + * @param[out] details On GNUNET_OK, the parsed details + * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed + * @return GNUNET_OK on success, GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was + * invalid, with *error_hint maybe non-NULL. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_create_policy_details ( + const char *currency, + const json_t *policy_options, + struct TALER_PolicyDetails *details, + const char **error_hint); + + +/* + * ================================ + * Merchant refund policy + * ================================ + */ +struct TALER_ExtensionPolicyMerchantRefundPolicyConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +/* + * ================================ + * Brandt-Vickrey Auctions policy + * ================================ + */ +/* + * @brief Configuration for Brandt-Vickrey auctions policy + */ +struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig +{ + uint16_t max_bidders; + uint16_t max_prices; + struct TALER_Amount auction_fee; +}; + + +/* + * ================================ + * Escrowed Payments policy + * ================================ + */ +/* + * @brief Configuration for escrowed payments policy + */ +struct TALER_ExtensionPolicyEscrowedPaymentsConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +#endif diff --git a/src/include/taler_fakebank_lib.h b/src/include/taler_fakebank_lib.h index 16135a4d7..6b34f4730 100644 --- a/src/include/taler_fakebank_lib.h +++ b/src/include/taler_fakebank_lib.h @@ -76,6 +76,35 @@ TALER_FAKEBANK_start2 (uint16_t port, /** + * Start the fake bank. The fake bank will, like the normal bank, listen for + * requests for /admin/add/incoming and /transfer. However, instead of + * executing or storing those requests, it will simply allow querying whether + * such a request has been made via #TALER_FAKEBANK_check_debit() and + * #TALER_FAKEBANK_check_credit() as well as the history API. + * + * This is useful for writing testcases to check whether the exchange + * would have issued the correct wire transfer orders. + * + * @param hostname hostname to use in URLs and URIs. + * @param port port to listen to + * @param exchange_url suggested exchange base URL + * @param currency which currency should the bank offer + * @param ram_limit how much memory do we use at most + * @param num_threads size of the thread pool, 0 to use the GNUnet scheduler + * @param signup_bonus how much to credit new users + * @return NULL on error + */ +struct TALER_FAKEBANK_Handle * +TALER_FAKEBANK_start3 (const char *hostname, + uint16_t port, + const char *exchange_url, + const char *currency, + uint64_t ram_limit, + unsigned int num_threads, + const struct TALER_Amount *signup_bonus); + + +/** * Check that no wire transfers were ordered (or at least none * that have not been taken care of via #TALER_FAKEBANK_check_debit() * or #TALER_FAKEBANK_check_credit()). diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 73d0c418f..98e565f0c 100644 --- a/src/include/taler_json_lib.h +++ b/src/include/taler_json_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016, 2021 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,6 +29,40 @@ #include "taler_error_codes.h" /** + * Version of this API, for compatibility tests. + */ +#define TALER_JSON_LIB_VERSION 0x00020000 + +/** + * Details about an encrypted contract. + */ +struct TALER_EncryptedContract +{ + + /** + * Signature of the client affiming this encrypted contract. + */ + struct TALER_PurseContractSignatureP econtract_sig; + + /** + * Contract decryption key for the purse. + */ + struct TALER_ContractDiffiePublicP contract_pub; + + /** + * Encrypted contract, can be NULL. + */ + void *econtract; + + /** + * Number of bytes in @e econtract. + */ + size_t econtract_size; + +}; + + +/** * Print JSON parsing related error information * @deprecated */ @@ -40,20 +74,6 @@ /** * Generate packer instruction for a JSON field of type - * absolute time. - * The absolute time value is expected to be already rounded. - * - * @param name name of the field to add to the object - * @param at absolute time to pack - * @return json pack specification - */ -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_abs (const char *name, - struct GNUNET_TIME_Absolute at); - - -/** - * Generate packer instruction for a JSON field of type * absolute time creating a human-readable timestamp. * * @param name name of the field to add to the object @@ -66,20 +86,6 @@ TALER_JSON_pack_time_abs_human (const char *name, /** - * Generate packer instruction for a JSON field of type - * absolute time in network byte order. - * The absolute time value is expected to be already rounded. - * - * @param name name of the field to add to the object - * @param at absolute time to pack - * @return json pack specification - */ -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_abs_nbo (const char *name, - struct GNUNET_TIME_AbsoluteNBO at); - - -/** * Put an error code into a JSON reply, including * both the numeric value and the hint. * @@ -89,88 +95,76 @@ TALER_JSON_pack_time_abs_nbo (const char *name, GNUNET_JSON_pack_string ("hint", TALER_ErrorCode_get_hint (ec)), \ GNUNET_JSON_pack_uint64 ("code", ec) -/** - * Generate packer instruction for a JSON field of type - * absolute time creating a human-readable timestamp. - * - * @param name name of the field to add to the object - * @param at absolute time to pack - * @return json pack specification - */ -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_abs_nbo_human (const char *name, - struct GNUNET_TIME_AbsoluteNBO at); - /** * Generate packer instruction for a JSON field of type - * relative time. - * The relative time value is expected to be already rounded. + * denomination public key. * * @param name name of the field to add to the object - * @param rt relative time to pack + * @param pk public key * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_rel (const char *name, - struct GNUNET_TIME_Relative rt); +TALER_JSON_pack_denom_pub ( + const char *name, + const struct TALER_DenominationPublicKey *pk); /** * Generate packer instruction for a JSON field of type - * relative time in network byte order. - * The relative time value is expected to be already rounded. + * denomination signature. * * @param name name of the field to add to the object - * @param rt relative time to pack + * @param sig signature * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_time_rel_nbo (const char *name, - struct GNUNET_TIME_RelativeNBO rt); +TALER_JSON_pack_denom_sig ( + const char *name, + const struct TALER_DenominationSignature *sig); /** * Generate packer instruction for a JSON field of type - * denomination public key. + * blinded denomination signature (that needs to be + * unblinded before it becomes valid). * * @param name name of the field to add to the object - * @param pk public key + * @param sig signature * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_denom_pub ( +TALER_JSON_pack_blinded_denom_sig ( const char *name, - const struct TALER_DenominationPublicKey *pk); + const struct TALER_BlindedDenominationSignature *sig); /** * Generate packer instruction for a JSON field of type - * denomination signature. + * blinded planchet. * * @param name name of the field to add to the object - * @param sig signature + * @param blinded_planchet blinded planchet * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_denom_sig ( +TALER_JSON_pack_blinded_planchet ( const char *name, - const struct TALER_DenominationSignature *sig); + const struct TALER_BlindedPlanchet *blinded_planchet); /** * Generate packer instruction for a JSON field of type - * blinded denomination signature (that needs to be - * unblinded before it becomes valid). + * exchange withdraw values (/csr). * * @param name name of the field to add to the object - * @param sig signature + * @param ewv values to transmit * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_blinded_denom_sig ( +TALER_JSON_pack_exchange_withdraw_values ( const char *name, - const struct TALER_BlindedDenominationSignature *sig); + const struct TALER_ExchangeWithdrawValues *ewv); /** @@ -188,25 +182,28 @@ TALER_JSON_pack_amount (const char *name, /** * Generate packer instruction for a JSON field of type - * amount. + * encrypted contract. * * @param name name of the field to add to the object - * @param amount valid amount to pack + * @param econtract the encrypted contract * @return json pack specification */ struct GNUNET_JSON_PackSpec -TALER_JSON_pack_amount_nbo (const char *name, - const struct TALER_AmountNBO *amount); - +TALER_JSON_pack_econtract ( + const char *name, + const struct TALER_EncryptedContract *econtract); /** - * Convert a TALER amount to a JSON object. + * Generate packer instruction for a JSON field of type age_commitment * - * @param amount the amount - * @return a json object describing the amount + * @param name name of the field to add to the object + * @param age_commitment age commitment to add + * @return json pack specification */ -json_t * -TALER_JSON_from_amount (const struct TALER_Amount *amount); +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_age_commitment ( + const char *name, + const struct TALER_AgeCommitment *age_commitment); /** @@ -216,7 +213,7 @@ TALER_JSON_from_amount (const struct TALER_Amount *amount); * @return a json object describing the amount */ json_t * -TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO *amount); +TALER_JSON_from_amount (const struct TALER_Amount *amount); /** @@ -236,20 +233,19 @@ TALER_JSON_spec_amount (const char *name, /** - * Provide specification to parse given JSON object to an amount - * in network byte order. - * The @a currency must be a valid pointer while the - * parsing is done, a copy is not made. + * Provide specification to parse given JSON object to + * a currency specification. * * @param name name of the amount field in the JSON - * @param currency the currency the amount must be in - * @param[out] r_amount where the amount has to be written + * @param currency_code currency code to parse + * @param[out] r_cspec where the currency spec has to be written * @return spec for parsing an amount */ struct GNUNET_JSON_Specification -TALER_JSON_spec_amount_nbo (const char *name, - const char *currency, - struct TALER_AmountNBO *r_amount); +TALER_JSON_spec_currency_specification ( + const char *name, + const char *currency_code, + struct TALER_CurrencySpecification *r_cspec); /** @@ -266,57 +262,120 @@ TALER_JSON_spec_amount_any (const char *name, /** - * Provide specification to parse given JSON object to an amount - * in any currency in network byte order. + * Provide specification to parse given JSON object to an encrypted contract. * * @param name name of the amount field in the JSON - * @param[out] r_amount where the amount has to be written + * @param[out] econtract where to store the encrypted contract * @return spec for parsing an amount */ struct GNUNET_JSON_Specification -TALER_JSON_spec_amount_any_nbo (const char *name, - struct TALER_AmountNBO *r_amount); +TALER_JSON_spec_econtract (const char *name, + struct TALER_EncryptedContract *econtract); /** - * Provide specification to parse given JSON object to an absolute time. - * The absolute time value is expected to be already rounded. + * Provide specification to parse a given JSON object to an age commitment. * - * @param name name of the time field in the JSON - * @param[out] r_time where the time has to be written - * @return spec for parsing an absolute time + * @param name name of the age commitment field in the JSON + * @param[out] age_commitment where to store the age commitment + * @return spec for parsing an age commitment */ struct GNUNET_JSON_Specification -TALER_JSON_spec_absolute_time (const char *name, - struct GNUNET_TIME_Absolute *r_time); +TALER_JSON_spec_age_commitment (const char *name, + struct TALER_AgeCommitment *age_commitment); /** - * Provide specification to parse given JSON object to an absolute time - * in network byte order. - * The absolute time value is expected to be already rounded. + * Provide specification to parse an OTP key. + * An OTP key must be an RFC 3548 base32-encoded + * value (so NOT our usual Crockford-base32 encoding!). * - * @param name name of the time field in the JSON - * @param[out] r_time where the time has to be written - * @return spec for parsing an absolute time + * @param name name of the OTP key field in the JSON + * @param[out] otp_key where to store the OTP key + * @return spec for parsing an age commitment */ struct GNUNET_JSON_Specification -TALER_JSON_spec_absolute_time_nbo (const char *name, - struct GNUNET_TIME_AbsoluteNBO *r_time); +TALER_JSON_spec_otp_key (const char *name, + const char **otp_key); /** - * Provide specification to parse given JSON object to a relative time. - * The absolute time value is expected to be already rounded. + * Provide specification to parse an OTP method type. + * The value could be provided as an integer or + * as a descriptive string. * - * @param name name of the time field in the JSON - * @param[out] r_time where the time has to be written - * @return spec for parsing a relative time + * @param name name of the OTP method type in the JSON + * @param[out] mca where to store the method type + * @return spec for parsing an age commitment */ struct GNUNET_JSON_Specification -TALER_JSON_spec_relative_time (const char *name, - struct GNUNET_TIME_Relative *r_time); +TALER_JSON_spec_otp_type (const char *name, + enum TALER_MerchantConfirmationAlgorithm *mca); + + +/** + * Generate specification to parse all fees for + * a denomination under a prefix @a pfx. + * + * @param pfx string prefix to use + * @param currency which currency to expect + * @param[out] dfs a `struct TALER_DenomFeeSet` to initialize + */ +#define TALER_JSON_SPEC_DENOM_FEES(pfx,currency,dfs) \ + TALER_JSON_spec_amount (pfx "_withdraw", (currency), &(dfs)->withdraw), \ + TALER_JSON_spec_amount (pfx "_deposit", (currency), &(dfs)->deposit), \ + TALER_JSON_spec_amount (pfx "_refresh", (currency), &(dfs)->refresh), \ + TALER_JSON_spec_amount (pfx "_refund", (currency), &(dfs)->refund) + + +/** + * Macro to pack all of a denominations' fees under + * a given @a pfx. + * + * @param pfx string prefix to use + * @param dfs a `struct TALER_DenomFeeSet` to pack + */ +#define TALER_JSON_PACK_DENOM_FEES(pfx, dfs) \ + TALER_JSON_pack_amount (pfx "_withdraw", &(dfs)->withdraw), \ + TALER_JSON_pack_amount (pfx "_deposit", &(dfs)->deposit), \ + TALER_JSON_pack_amount (pfx "_refresh", &(dfs)->refresh), \ + TALER_JSON_pack_amount (pfx "_refund", &(dfs)->refund) + + +/** + * Generate specification to parse all global fees. + * + * @param currency which currency to expect + * @param[out] gfs a `struct TALER_GlobalFeeSet` to initialize + */ +#define TALER_JSON_SPEC_GLOBAL_FEES(currency,gfs) \ + TALER_JSON_spec_amount ("history_fee", (currency), &(gfs)->history), \ + TALER_JSON_spec_amount ("account_fee", (currency), &(gfs)->account), \ + TALER_JSON_spec_amount ("purse_fee", (currency), &(gfs)->purse) + +/** + * Macro to pack all of the global fees. + * + * @param gfs a `struct TALER_GlobalFeeSet` to pack + */ +#define TALER_JSON_PACK_GLOBAL_FEES(gfs) \ + TALER_JSON_pack_amount ("history_fee", &(gfs)->history), \ + TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \ + TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse) + +/** + * Generate a parser for a group of denominations. + * + * @param[in] field name of the field, maybe NULL + * @param[in] currency name of the currency + * @param[out] group denomination group information + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_group (const char *field, + const char *currency, + struct TALER_DenominationGroup *group); /** * Generate line in parser specification for denomination public key. @@ -331,10 +390,116 @@ TALER_JSON_spec_denom_pub (const char *field, /** + * Generate line in parser specification for error codes. + * + * @param field name of the field + * @param[out] ec error code to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_ec (const char *field, + enum TALER_ErrorCode *ec); + + +/** + * Generate line in parser specification for + * HTTP/HTTPS URLs. + * + * @param field name of the field + * @param[out] url web URL to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_web_url (const char *field, + const char **url); + + +/** + * Generate line in parser specification for + * "payto://" URIs. + * + * @param field name of the field + * @param[out] payto_uri RFC 8905 URI to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_payto_uri (const char *field, + const char **payto_uri); + + +/** + * Generate line in parser specification for AML decision states. + * + * @param field name of the field + * @param[out] aml_state AML state to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_aml_decision (const char *field, + enum TALER_AmlDecisionState *aml_state); + + +/** + * Representation of a protocol version. + */ +struct TALER_JSON_ProtocolVersion +{ + /** + * Current version of the protocol. + */ + unsigned int current; + + /** + * Implementation revision for the @e current + * version. + */ + unsigned int revision; + + /** + * Number of protocol versions this @e revision is + * backwards-compatible with. Subtract this number + * from @e current to get the minimum protocol version + * required from the client. + */ + unsigned int age; +}; + + +/** + * Generate line in parser specification for protocol + * versions (``/config``). The field must be a string + * encoding the version as "$CURRENT:$REVISION:$AGE". + * + * @param field name of the field (usually "version") + * @param[out] ver protocol versions to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_version (const char *field, + struct TALER_JSON_ProtocolVersion *ver); + + +/** + * Generate a parser specification for a denomination public key of a given + * cipher. + * + * @param field name of the field + * @param cipher which cipher type to parse for + * @param[out] pk key to fill + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denom_pub_cipher ( + const char *field, + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, + struct TALER_DenominationPublicKey *pk); + + +/** * Generate line in parser specification for denomination signature. * * @param field name of the field - * @param sig the signature to initialize + * @param[out] sig the signature to initialize * @return corresponding field spec */ struct GNUNET_JSON_Specification @@ -347,7 +512,7 @@ TALER_JSON_spec_denom_sig (const char *field, * blinded denomination signature. * * @param field name of the field - * @param sig the blinded signature to initialize + * @param[out] sig the blinded signature to initialize * @return corresponding field spec */ struct GNUNET_JSON_Specification @@ -357,6 +522,33 @@ TALER_JSON_spec_blinded_denom_sig ( /** + * Generate line in parser specification for + * exchange withdraw values (/csr). + * + * @param field name of the field + * @param[out] ewv the exchange withdraw values to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_exchange_withdraw_values ( + const char *field, + struct TALER_ExchangeWithdrawValues *ewv); + + +/** + * Generate line in parser specification for a + * blinded planchet. + * + * @param field name of the field + * @param[out] blinded_planchet the blinded planchet to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_planchet (const char *field, + struct TALER_BlindedPlanchet *blinded_planchet); + + +/** * The expected field stores a possibly internationalized string. * Internationalization means that there is another field "$name_i18n" * which is an object where the keys are languages. If this is @@ -412,20 +604,22 @@ TALER_JSON_spec_i18n_str (const char *name, */ enum GNUNET_GenericReturnValue TALER_JSON_contract_hash (const json_t *json, - struct TALER_PrivateContractHash *hc); + struct TALER_PrivateContractHashP *hc); /** - * Take a given contract with "forgettable" fields marked - * but with 'True' instead of a real salt. Replaces all - * 'True' values with proper random salts. Fails if any - * forgettable markers are neither 'True' nor valid salts. + * Take a given @a contract with "forgettable" fields marked in the @a spec + * with 'True' instead of a real salt. Replaces all 'True' values with proper + * random salts in the actual @a contract. Fails if any forgettable markers + * are neither 'True' nor valid salts. * - * @param[in,out] json JSON to transform + * @param spec specification with forgettable fields + * @param[in,out] contract JSON contract to transform * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -TALER_JSON_contract_seed_forgettable (json_t *json); +TALER_JSON_contract_seed_forgettable (const json_t *spec, + json_t *contract); /** @@ -534,34 +728,7 @@ TALER_JSON_get_error_code2 (const void *data, */ enum GNUNET_GenericReturnValue TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s, - struct TALER_MerchantWireHash *hc); - - -/** - * Check the signature in @a wire_s. Also performs rudimentary - * checks on the account data *if* supported. - * - * @param wire_s signed wire information of an exchange - * @param master_pub master public key of the exchange - * @return #GNUNET_OK if signature is valid - */ -enum GNUNET_GenericReturnValue -TALER_JSON_exchange_wire_signature_check ( - const json_t *wire_s, - const struct TALER_MasterPublicKeyP *master_pub); - - -/** - * Create a signed wire statement for the given account. - * - * @param payto_uri account specification - * @param master_priv private key to sign with - * @return NULL if @a payto_uri is malformed - */ -json_t * -TALER_JSON_exchange_wire_signature_make ( - const char *payto_uri, - const struct TALER_MasterPrivateKeyP *master_priv); + struct TALER_MerchantWireHashP *hc); /** @@ -628,15 +795,31 @@ TALER_JSON_wire_to_payto (const json_t *wire_s); /** - * Hash @a extensions. + * Hash @a policy extensions in deposits. * - * @param extensions contract extensions to hash - * @param[out] ech where to write the extension hash + * @param policy contract policy extension to hash + * @param[out] ech where to write the policy hash */ void -TALER_deposit_extension_hash (const json_t *extensions, - struct TALER_ExtensionContractHash *ech); +TALER_deposit_policy_hash (const json_t *policy, + struct TALER_ExtensionPolicyHashP *ech); +/** + * Hash the @a manifests of extensions, given as JSON + * + * @param manifests Manifests of the extensions + * @param[out] eh where to write the hash + * @return GNUNET_OK on success, GNUNET_SYSERR on failure + */ +enum GNUNET_GenericReturnValue +TALER_JSON_extensions_manifests_hash (const json_t *manifests, + struct TALER_ExtensionManifestsHashP *eh); + +/** + * Canonicalize a JSON input to a string according to RFC 8785. + */ +char * +TALER_JSON_canonicalize (const json_t *input); #endif /* TALER_JSON_LIB_H_ */ diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h new file mode 100644 index 000000000..4d0c18fa4 --- /dev/null +++ b/src/include/taler_kyclogic_lib.h @@ -0,0 +1,374 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler_kyclogic_lib.h + * @brief server-side KYC API + * @author Christian Grothoff + */ +#ifndef TALER_KYCLOGIC_LIB_H +#define TALER_KYCLOGIC_LIB_H + +#include <microhttpd.h> +#include "taler_exchangedb_plugin.h" +#include "taler_kyclogic_plugin.h" + + +/** + * Enumeration for our KYC user types. + */ +enum TALER_KYCLOGIC_KycUserType +{ + /** + * KYC rule is for an individual. + */ + TALER_KYCLOGIC_KYC_UT_INDIVIDUAL = 0, + + /** + * KYC rule is for a business. + */ + TALER_KYCLOGIC_KYC_UT_BUSINESS = 1 +}; + + +/** + * Enumeration of possible events that may trigger + * KYC requirements. + */ +enum TALER_KYCLOGIC_KycTriggerEvent +{ + + /** + * Customer withdraws coins. + */ + TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW = 0, + + /** + * Merchant deposits coins. + */ + TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT = 1, + + /** + * Wallet receives P2P payment. + */ + TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE = 2, + + /** + * Wallet balance exceeds threshold. + */ + TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE = 3, + + /** + * Reserve is being closed by force. + */ + TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 4, + + /** + * Customer withdraws coins via age-withdraw. + */ + TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW = 5, +}; + + +/** + * Parse KYC trigger string value from a string + * into enumeration value. + * + * @param trigger_s string to parse + * @param[out] trigger set to the value found + * @return #GNUNET_OK on success, #GNUNET_NO if option + * does not exist, #GNUNET_SYSERR if option is + * malformed + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_trigger_from_string ( + const char *trigger_s, + enum TALER_KYCLOGIC_KycTriggerEvent *trigger); + + +/** + * Convert KYC trigger value to human-readable string. + * + * @param trigger value to convert + * @return human-readable representation of the @a trigger + */ +const char * +TALER_KYCLOGIC_kyc_trigger2s (enum TALER_KYCLOGIC_KycTriggerEvent trigger); + + +/** + * Parse user type string into enumeration value. + * + * @param ut_s string to parse + * @param[out] ut set to the value found + * @return #GNUNET_OK on success, #GNUNET_NO if option + * does not exist, #GNUNET_SYSERR if option is + * malformed + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_user_type_from_string (const char *ut_s, + enum TALER_KYCLOGIC_KycUserType *ut); + + +/** + * Convert KYC user type to human-readable string. + * + * @param ut value to convert + * @return human-readable representation of the @a ut + */ +const char * +TALER_KYCLOGIC_kyc_user_type2s (enum TALER_KYCLOGIC_KycUserType ut); + + +/** + * Initialize KYC subsystem. Loads the KYC configuration. + * + * @param cfg configuration to parse + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_init (const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Shut down the KYC subsystem. + */ +void +TALER_KYCLOGIC_kyc_done (void); + + +/** + * Function called to iterate over KYC-relevant + * transaction amounts for a particular time range. + * Called within a database transaction, so must + * not start a new one. + * + * @param cls closure, identifies the event type and + * account to iterate over events for + * @param limit maximum time-range for which events + * should be fetched (timestamp in the past) + * @param cb function to call on each event found, + * events must be returned in reverse chronological + * order + * @param cb_cls closure for @a cb + */ +typedef void +(*TALER_KYCLOGIC_KycAmountIterator)(void *cls, + struct GNUNET_TIME_Absolute limit, + TALER_EXCHANGEDB_KycAmountCallback cb, + void *cb_cls); + + +/** + * Function called to iterate over KYC-relevant + * transaction thresholds amounts. + * + * @param cls closure, identifies the event type and + * account to iterate over events for + * @param threshold a relevant threshold amount + */ +typedef void +(*TALER_KYCLOGIC_KycThresholdIterator)(void *cls, + const struct TALER_Amount *threshold); + + +/** + * Call us on KYC processes satisfied for the given + * account. Must match the ``select_satisfied_kyc_processes`` of the exchange database plugin. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc + * @return transaction status code + */ +typedef enum GNUNET_DB_QueryStatus +(*TALER_KYCLOGIC_KycSatisfiedIterator)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_SatisfiedProviderCallback spc, + void *spc_cls); + + +/** + * Check if KYC is provided for a particular operation. Returns the set of checks that still need to be satisfied. + * + * Called within a database transaction, so must + * not start a new one. + * + * @param event what type of operation is triggering the + * test if KYC is required + * @param h_payto account the event is about + * @param ki callback that returns list of already + * satisfied KYC checks, implemented by ``select_satisfied_kyc_processes`` of the exchangedb + * @param ki_cls closure for @a ki + * @param ai callback offered to inquire about historic + * amounts involved in this type of operation + * at the given account + * @param ai_cls closure for @a ai + * @param[out] required set to NULL if no check is needed, + * otherwise space-separated list of required checks + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, + const struct TALER_PaytoHashP *h_payto, + TALER_KYCLOGIC_KycSatisfiedIterator ki, + void *ki_cls, + TALER_KYCLOGIC_KycAmountIterator ai, + void *ai_cls, + char **required); + + +/** + * Check if the @a requirements are now satsified for + * @a h_payto account. + * + * @param[in,out] requirements space-spearated list of requirements, + * already satisfied requirements are removed from the list + * @param h_payto hash over the account + * @param[out] kyc_details if satisfied, set to what kind of + * KYC information was collected + * @param ki iterator over satisfied providers + * @param ki_cls closure for @a ki + * @param[out] satisfied set to true if the KYC check was satisfied + * @return transaction status (from @a ki) + */ +enum GNUNET_DB_QueryStatus +TALER_KYCLOGIC_check_satisfied (char **requirements, + const struct TALER_PaytoHashP *h_payto, + json_t **kyc_details, + TALER_KYCLOGIC_KycSatisfiedIterator ki, + void *ki_cls, + bool *satisfied); + + +/** + * Iterate over all thresholds that are applicable + * to a particular type of @a event + * + * @param event thresholds to look up + * @param it function to call on each + * @param it_cls closure for @a it + */ +void +TALER_KYCLOGIC_kyc_iterate_thresholds ( + enum TALER_KYCLOGIC_KycTriggerEvent event, + TALER_KYCLOGIC_KycThresholdIterator it, + void *it_cls); + + +/** + * Function called with the provider details and + * associated plugin closures for matching logics. + * + * @param cls closure + * @param pd provider details of a matching logic + * @param plugin_cls closure of the plugin + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_KYCLOGIC_DetailsCallback)( + void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + void *plugin_cls); + + +/** + * Call @a cb for all logics with name @a logic_name, + * providing the plugin closure and the @a pd configurations. + * + * @param logic_name name of the logic to match + * @param cb function to call on matching results + * @param cb_cls closure for @a cb + */ +void +TALER_KYCLOGIC_kyc_get_details ( + const char *logic_name, + TALER_KYCLOGIC_DetailsCallback cb, + void *cb_cls); + + +/** + * Check if a given @a check_name is a legal name (properly + * configured) and can be satisfied in principle. + * + * @param check_name name of the check to see if it is configured + * @return #GNUNET_OK if the check can be satisfied, + * #GNUNET_NO if the check can never be satisfied, + * #GNUNET_SYSERR if the type of the check is unknown + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_check_satisfiable ( + const char *check_name); + + +/** + * Return list of all KYC checks that are possible. + * + * @return JSON array of strings with the allowed KYC checks + */ +json_t * +TALER_KYCLOGIC_get_satisfiable (void); + + +/** + * Obtain the provider logic for a given set of @a requirements. + * + * @param requirements space-separated list of required checks + * @param ut type of the entity performing the check + * @param[out] plugin set to the KYC logic API + * @param[out] pd set to the specific operation context + * @param[out] configuration_section set to the name of the KYC logic configuration section * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_requirements_to_logic (const char *requirements, + enum TALER_KYCLOGIC_KycUserType ut, + struct TALER_KYCLOGIC_Plugin **plugin, + struct TALER_KYCLOGIC_ProviderDetails **pd, + const char **configuration_section); + + +/** + * Obtain the provider logic for a given @a name. + * + * @param name name of the logic or provider section + * @param[out] plugin set to the KYC logic API + * @param[out] pd set to the specific operation context + * @param[out] configuration_section set to the name of the KYC logic configuration section + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_lookup_logic (const char *name, + struct TALER_KYCLOGIC_Plugin **plugin, + struct TALER_KYCLOGIC_ProviderDetails **pd, + const char **configuration_section); + + +/** + * Obtain array of KYC checks provided by the provider + * configured in @a section_name. + * + * @param section_name configuration section name + * @param[out] num_checks set to the length of the array + * @param[out] provided_checks set to an array with the + * names of the checks provided by this KYC provider + */ +void +TALER_KYCLOGIC_lookup_checks (const char *section_name, + unsigned int *num_checks, + char ***provided_checks); + +#endif diff --git a/src/include/taler_kyclogic_plugin.h b/src/include/taler_kyclogic_plugin.h new file mode 100644 index 000000000..a9a4dd97a --- /dev/null +++ b/src/include/taler_kyclogic_plugin.h @@ -0,0 +1,384 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file include/taler_kyclogic_plugin.h + * @brief KYC API specific logic C interface + * @author Christian Grothoff + */ +#ifndef TALER_KYCLOGIC_PLUGIN_H +#define TALER_KYCLOGIC_PLUGIN_H + +#include <jansson.h> +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_db_lib.h> +#include "taler_util.h" + + +/** + * Possible states of a KYC check. + */ +enum TALER_KYCLOGIC_KycStatus +{ + + /** + * The provider has passed the customer. + */ + TALER_KYCLOGIC_STATUS_SUCCESS = 0, + + /** + * Something to do with the user (bit!). + */ + TALER_KYCLOGIC_STATUS_USER = 1, + + /** + * Something to do with the provider (bit!). + */ + TALER_KYCLOGIC_STATUS_PROVIDER = 2, + + /** + * The interaction ended in definitive failure. + * (kind of with both parties). + */ + TALER_KYCLOGIC_STATUS_FAILED + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_PROVIDER, + + /** + * The interaction is still ongoing. + */ + TALER_KYCLOGIC_STATUS_PENDING = 4, + + /** + * One of the parties hat a temporary failure. + */ + TALER_KYCLOGIC_STATUS_ABORTED = 8, + + /** + * The interaction with the user is ongoing. + */ + TALER_KYCLOGIC_STATUS_USER_PENDING + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_PENDING, + + /** + * The provider is still checking. + */ + TALER_KYCLOGIC_STATUS_PROVIDER_PENDING + = TALER_KYCLOGIC_STATUS_PROVIDER + | TALER_KYCLOGIC_STATUS_PENDING, + + /** + * The user aborted the check (possibly recoverable) + * or made some other type of (recoverable) mistake. + */ + TALER_KYCLOGIC_STATUS_USER_ABORTED + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_ABORTED, + + /** + * The provider had an (internal) failure. + */ + TALER_KYCLOGIC_STATUS_PROVIDER_FAILED + = TALER_KYCLOGIC_STATUS_PROVIDER + | TALER_KYCLOGIC_STATUS_ABORTED, + + /** + * Return code set to not update the KYC status + * at all. + */ + TALER_KYCLOGIC_STATUS_KEEP = 16, + + /** + * We had an internal logic failure. + */ + TALER_KYCLOGIC_STATUS_INTERNAL_ERROR = 32 + +}; + + +/** + * Plugin-internal specification of the configuration + * of the plugin for a given KYC provider. + */ +struct TALER_KYCLOGIC_ProviderDetails; + +/** + * Handle for an initiation operation. + */ +struct TALER_KYCLOGIC_InitiateHandle; + +/** + * Handle for an KYC proof operation. + */ +struct TALER_KYCLOGIC_ProofHandle; + +/** + * Handle for an KYC Web hook operation. + */ +struct TALER_KYCLOGIC_WebhookHandle; + + +/** + * Function called with the result of a KYC initiation + * operation. + * + * @param cls closure + * @param ec #TALER_EC_NONE on success + * @param redirect_url set to where to redirect the user on success, NULL on failure + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param error_msg_hint set to additional details to return to user, NULL on success + */ +typedef void +(*TALER_KYCLOGIC_InitiateCallback)( + void *cls, + enum TALER_ErrorCode ec, + const char *redirect_url, + const char *provider_user_id, + const char *provider_legitimization_id, + const char *error_msg_hint); + + +/** + * Function called with the result of a proof check operation. + * + * Note that the "decref" for the @a response + * will be done by the callee and MUST NOT be done by the plugin. + * + * @param cls closure + * @param status KYC status + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param attributes user attributes returned by the provider + * @param expiration until when is the KYC check valid + * @param http_status HTTP status code of @a response + * @param[in] response to return to the HTTP client + */ +typedef void +(*TALER_KYCLOGIC_ProofCallback)( + void *cls, + enum TALER_KYCLOGIC_KycStatus status, + const char *provider_user_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, + unsigned int http_status, + struct MHD_Response *response); + + +/** + * Function called with the result of a webhook operation. + * + * Note that the "decref" for the @a response will be done by the callee and + * MUST NOT be done by the plugin! + * + * @param cls closure + * @param process_row legitimization process the webhook was about + * @param account_id account the webhook was about + * @param provider_section name of the configuration section of the logic that was run + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param status KYC status + * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider + * @param http_status HTTP status code of @a response + * @param[in] response to return to the HTTP client + */ +typedef void +(*TALER_KYCLOGIC_WebhookCallback)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *account_id, + const char *provider_section, + const char *provider_user_id, + const char *provider_legitimization_id, + enum TALER_KYCLOGIC_KycStatus status, + struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, + unsigned int http_status, + struct MHD_Response *response); + + +/** + * Function the plugin can use to lookup an @a h_payto by @a + * provider_legitimization_id. Must match the `kyc_provider_account_lookup` + * of the exchange's database plugin. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @param[out] process_row where to write the row of the entry + * @return database transaction status + */ +typedef enum GNUNET_DB_QueryStatus +(*TALER_KYCLOGIC_ProviderLookupCallback)( + void *cls, + const char *provider_section, + const char *provider_legitimization_id, + struct TALER_PaytoHashP *h_payto, + uint64_t *process_row); + + +/** + * @brief The plugin API, returned from the plugin's "init" function. + * The argument given to "init" is simply a configuration handle. + */ +struct TALER_KYCLOGIC_Plugin +{ + + /** + * Closure for all callbacks. + */ + void *cls; + + /** + * Name of the library which generated this plugin. Set by the + * plugin loader. + */ + char *library_name; + + /** + * Name of the logic, for webhook matching. Set by the + * plugin loader. + */ + char *name; + + /** + * Load the configuration of the KYC provider. + * + * @param cls closure + * @param provider_section_name configuration section to parse + * @return NULL if configuration is invalid + */ + struct TALER_KYCLOGIC_ProviderDetails * + (*load_configuration)(void *cls, + const char *provider_section_name); + + /** + * Release configuration resources previously loaded + * + * @param[in] pd configuration to release + */ + void + (*unload_configuration)(struct TALER_KYCLOGIC_ProviderDetails *pd); + + + /** + * Initiate KYC check. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param account_id which account to trigger process for + * @param process_row unique ID for the legitimization process + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_InitiateHandle * + (*initiate)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + const struct TALER_PaytoHashP *account_id, + uint64_t process_row, + TALER_KYCLOGIC_InitiateCallback cb, + void *cb_cls); + + + /** + * Cancel KYC check initiation. + * + * @param[in] ih handle of operation to cancel + */ + void + (*initiate_cancel) (struct TALER_KYCLOGIC_InitiateHandle *ih); + + + /** + * Check KYC status and return status to human. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param connection MHD connection object (for HTTP headers) + * @param account_id which account to trigger process for + * @param process_row row in the legitimization processes table the legitimization is for + * @param provider_user_id user ID (or NULL) the proof is for + * @param provider_legitimization_id legitimization ID the proof is for + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_ProofHandle * + (*proof)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + struct MHD_Connection *connection, + const struct TALER_PaytoHashP *account_id, + uint64_t process_row, + const char *provider_user_id, + const char *provider_legitimization_id, + TALER_KYCLOGIC_ProofCallback cb, + void *cb_cls); + + + /** + * Cancel KYC proof. + * + * @param[in] ph handle of operation to cancel + */ + void + (*proof_cancel) (struct TALER_KYCLOGIC_ProofHandle *ph); + + + /** + * Check KYC status and return result for Webhook. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param plc callback to lookup accounts with + * @param plc_cls closure for @a plc + * @param http_method HTTP method used for the webhook + * @param url_path rest of the URL after `/kyc-webhook/$LOGIC/` + * @param connection MHD connection object (for HTTP headers) + * @param body_size number of bytes in @a body + * @param body HTTP request body + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_WebhookHandle * + (*webhook)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + TALER_KYCLOGIC_ProviderLookupCallback plc, + void *plc_cls, + const char *http_method, + const char *const url_path[], + struct MHD_Connection *connection, + const json_t *upload, + TALER_KYCLOGIC_WebhookCallback cb, + void *cb_cls); + + + /** + * Cancel KYC webhook execution. + * + * @param[in] wh handle of operation to cancel + */ + void + (*webhook_cancel) (struct TALER_KYCLOGIC_WebhookHandle *wh); + +}; + + +#endif /* _TALER_KYCLOGIC_PLUGIN_H */ diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index ba5a072c4..57d041758 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -27,10 +27,17 @@ #include <jansson.h> #include <microhttpd.h> #include "taler_error_codes.h" +#include "taler_util.h" #include <gnunet/gnunet_mhd_compat.h> /** + * Maximum POST request size. + */ +#define TALER_MHD_REQUEST_BUFFER_MAX (1024 * 1024 * 16) + + +/** * Global options for response generation. */ enum TALER_MHD_GlobalOptions @@ -166,8 +173,8 @@ TALER_MHD_reply_json_pack (struct MHD_Connection *connection, * @return MHD result code */ #define TALER_MHD_REPLY_JSON_PACK(connection,response_code,...) \ - TALER_MHD_reply_json_steal (connection, GNUNET_JSON_PACK (__VA_ARGS__), \ - response_code) + TALER_MHD_reply_json_steal (connection, GNUNET_JSON_PACK (__VA_ARGS__), \ + response_code) /** @@ -202,6 +209,18 @@ TALER_MHD_reply_with_ec (struct MHD_Connection *connection, /** + * Produce HTTP "Date:" header. + * + * @param at time to write to @a date + * @param[out] date where to write the header, with + * at least 128 bytes available space. + */ +void +TALER_MHD_get_date_string (struct GNUNET_TIME_Absolute at, + char date[128]); + + +/** * Make JSON response object. * * @param json the json object @@ -240,10 +259,21 @@ TALER_MHD_make_json_pack (const char *fmt, * @return MHD response object */ #define TALER_MHD_MAKE_JSON_PACK(...) \ - TALER_MHD_make_json_steal (GNUNET_JSON_PACK (__VA_ARGS__)) + TALER_MHD_make_json_steal (GNUNET_JSON_PACK (__VA_ARGS__)) /** + * Pack Taler error code @a ec and associated hint into a + * JSON object. + * + * @param ec error code to pack + * @return packer array entries (two!) + */ +#define TALER_MHD_PACK_EC(ec) \ + GNUNET_JSON_pack_uint64 ("code", ec), \ + GNUNET_JSON_pack_string ("hint", TALER_ErrorCode_get_hint (ec)) + +/** * Create a response indicating an internal error. * * @param ec error code to return @@ -408,7 +438,201 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection, /** - * Extract fixed-size base32crockford encoded data from request. + * Extract optional "timeout_ms" argument from request. + * + * @param connection the MHD connection + * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout, + * the current time plus the value given under "timeout_ms" otherwise + * @return #GNUNET_OK on success, #GNUNET_NO if an + * error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_timeout (struct MHD_Connection *connection, + struct GNUNET_TIME_Absolute *expiration); + + +/** + * Extract optional "timeout_ms" argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the "timeout_ms" + * argument existed but failed to parse. + * + * @param connection the MHD connection + * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout, + * the current time plus the value given under "timeout_ms" otherwise + */ +#define TALER_MHD_parse_request_timeout(connection,expiration) \ + do { \ + switch (TALER_MHD_parse_request_arg_timeout (connection, \ + expiration)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional numeric limit argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] off set to the offset, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_number (struct MHD_Connection *connection, + const char *name, + uint64_t *off); + + +/** + * Extract optional numeric argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] off set to the given numeric value, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_number(connection,name,off) \ + do { \ + switch (TALER_MHD_parse_request_arg_number (connection, \ + name, \ + off)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional signed numeric limit argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] val set to the signed value, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_snumber (struct MHD_Connection *connection, + const char *name, + int64_t *val); + + +/** + * Extract optional numeric argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] val set to the given numeric value, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_snumber(connection,name,val) \ + do { \ + switch (TALER_MHD_parse_request_arg_snumber (connection, \ + name, \ + val)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional amount argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] val set to the amount, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_amount (struct MHD_Connection *connection, + const char *name, + struct TALER_Amount *val); + + +/** + * Extract optional amount argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] val set to the given amount, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_amount(connection,name,val) \ + do { \ + switch (TALER_MHD_parse_request_arg_amount (connection, \ + name, \ + val)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Determines which of the given choices is preferred + * by the client. Parses an HTTP header such as + * "Accept:" or "Language:" to find entries matching + * the list of strings given in the variadic argument + * list. Returns the index of the preferred choice. + * + * @param connection HTTP request handle + * @param header type of HTTP header to evaluate + * @param ... NULL-terminated list of choices to + * check for in the header + * @return -1 if none of the given choices is in + * the header, -2 if the header is missing, + * otherwise index of preferred choice in + * the varargs list + */ +int +TALER_MHD_check_accept (struct MHD_Connection *connection, + const char *header, + ...); + + +/** + * Extract fixed-size base32crockford encoded data from request argument. * * Queues an error response to the connection if the parameter is missing or * invalid. @@ -417,16 +641,195 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection, * @param param_name the name of the parameter with the key * @param[out] out_data pointer to store the result * @param out_size expected size of @a out_data + * @param[out] present set to true if argument was found * @return * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_NO if the argument is malformed * #GNUNET_SYSERR on internal error (error response could not be sent) */ enum GNUNET_GenericReturnValue TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, const char *param_name, void *out_data, - size_t out_size); + size_t out_size, + bool *present); + + +/** + * Extract fixed-size base32crockford encoded data from request header. + * + * Queues an error response to the connection if the parameter is missing or + * invalid. + * + * @param connection the MHD connection + * @param header_name the name of the HTTP header with the value + * @param[out] out_data pointer to store the result + * @param out_size expected size of @a out_data + * @param[out] present set to true if argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_header_data (struct MHD_Connection *connection, + const char *header_name, + void *out_data, + size_t out_size, + bool *present); + +/** + * Extract fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the parameter with the key + * @param[out] val pointer to store the result, type must determine size + * @param[in,out] required pass true to require presence of this argument; if 'false' + * set to true if the argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_arg_auto(connection,name,val,required) \ + do { \ + bool p; \ + switch (TALER_MHD_parse_request_arg_data (connection, name, \ + val, sizeof (*val), &p)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + if (required & (! p)) \ + return TALER_MHD_reply_with_error ( \ + connection, \ + MHD_HTTP_BAD_REQUEST, \ + TALER_EC_GENERIC_PARAMETER_MISSING, \ + name); \ + required = p; \ + break; \ + } \ + } while (0) + + +/** + * Extract required fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the parameter with the key + * @param[out] val pointer to store the result, type must determine size + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_arg_auto_t(connection,name,val) \ + do { \ + bool b = true; \ + TALER_MHD_parse_request_arg_auto (connection,name,val,b); \ + } while (0) + +/** + * Extract fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the header with the key + * @param[out] val pointer to store the result, type must determine size + * @param[in,out] required pass true to require presence of this argument; if 'false' + * set to true if the argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_header_auto(connection,name,val,required) \ + do { \ + bool p; \ + switch (TALER_MHD_parse_request_header_data (connection, name, \ + val, sizeof (*val), &p)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + if (required & (! p)) \ + return TALER_MHD_reply_with_error ( \ + connection, \ + MHD_HTTP_BAD_REQUEST, \ + TALER_EC_GENERIC_PARAMETER_MISSING, \ + name); \ + required = p; \ + break; \ + } \ + } while (0) + + +/** + * Extract required fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the header with the key + * @param[out] val pointer to store the result, type must determine size + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_header_auto_t(connection,name,val) \ + do { \ + bool b = true; \ + TALER_MHD_parse_request_header_auto (connection,name,val,b); \ + } while (0) + + +/** + * Check that the 'Content-Length' header is giving + * a length below @a max_len. If not, return an + * appropriate error response and return the + * correct #MHD_YES/#MHD_NO value from this function. + * + * @param connection the MHD connection + * @param max_len maximum allowed content length + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_check_content_length_ (struct MHD_Connection *connection, + unsigned long long max_len); + + +/** + * Check that the 'Content-Length' header is giving + * a length below @a max_len. If not, return an + * appropriate error response and return the + * correct #MHD_YES/#MHD_NO value from this function. + * + * @param connection the MHD connection + * @param max_len maximum allowed content length + */ +#define TALER_MHD_check_content_length(connection,max_len) \ + do { \ + switch (TALER_MHD_check_content_length_ (connection, max_len)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) /** @@ -530,7 +933,7 @@ struct TALER_MHD_Legal; /** * Load set of legal documents as specified in @a cfg in section @a section - * where the Etag is given under the @param tagoption and the directory under + * where the Etag is given under the @a tagoption and the directory under * the @a diroption. * * @param cfg configuration to use diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 6e69cdf6d..f45de61d9 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016 Taler Systems SA + Copyright (C) 2014-2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,37 +19,50 @@ * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_PQ_LIB_H_ #define TALER_PQ_LIB_H_ #include <libpq-fe.h> #include <jansson.h> +#include <gnunet/gnunet_common.h> #include <gnunet/gnunet_pq_lib.h> #include "taler_util.h" /** - * Generate query parameter for a currency, consisting of the three - * components "value", "fraction" and "currency" in this order. The - * types must be a 64-bit integer, 32-bit integer and a - * #TALER_CURRENCY_LEN-sized BLOB/VARCHAR respectively. + * API version. Bump on every change. + */ +#define TALER_PQ_VERSION 0x09040000 + +/** + * Generate query parameter (as record tuple) for an amount, consisting + * of the two components "value" and "fraction" in this order. The + * types must be a 64-bit integer and a 32-bit integer + * respectively. The currency is dropped. * - * @param x pointer to the query parameter to pass + * @param db The database context for OID lookup + * @param amount pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x); +TALER_PQ_query_param_amount ( + const struct GNUNET_PQ_Context *db, + const struct TALER_Amount *amount); /** - * Generate query parameter for an amount, consisting of the two - * components "value" and "fraction" in this order. The - * types must be a 64-bit integer and a 32-bit integer - * respectively. The currency is dropped. + * Generate query parameter (as record tuple) for an amount, consisting of the + * three components "value", "fraction" and "currency" in this order. The + * types must be a 64-bit integer, a 32-bit integer and a TEXT field of 12 + * characters respectively. * - * @param x pointer to the query parameter to pass + * @param db The database context for OID lookup + * @param amount pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_amount (const struct TALER_Amount *x); +TALER_PQ_query_param_amount_with_currency ( + const struct GNUNET_PQ_Context *db, + const struct TALER_Amount *amount); /** @@ -58,7 +71,7 @@ TALER_PQ_query_param_amount (const struct TALER_Amount *x); * public key will be serialized into on variable-size * BLOB. * - * @param x pointer to the query parameter to pass + * @param denom_pub pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam TALER_PQ_query_param_denom_pub ( @@ -70,7 +83,7 @@ TALER_PQ_query_param_denom_pub ( * various attributes of the signature will be serialized into on * variable-size BLOB. * - * @param x pointer to the query parameter to pass + * @param denom_sig pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam TALER_PQ_query_param_denom_sig ( @@ -78,11 +91,24 @@ TALER_PQ_query_param_denom_sig ( /** + * Generate query parameter for a blinded planchet. + * Internally, various attributes of the blinded + * planchet will be serialized into on + * variable-size BLOB. + * + * @param bp pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_blinded_planchet ( + const struct TALER_BlindedPlanchet *bp); + + +/** * Generate query parameter for a blinded denomination signature. Internally, * the various attributes of the signature will be serialized into on * variable-size BLOB. * - * @param x pointer to the query parameter to pass + * @param denom_sig pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam TALER_PQ_query_param_blinded_denom_sig ( @@ -90,6 +116,18 @@ TALER_PQ_query_param_blinded_denom_sig ( /** + * Generate query parameter for the exchange's contribution during a + * withdraw. Internally, the various attributes of the @a alg_values will be + * serialized into on variable-size BLOB. + * + * @param alg_values pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_exchange_withdraw_values ( + const struct TALER_ExchangeWithdrawValues *alg_values); + + +/** * Generate query parameter for a JSON object (stored as a string * in the DB). Note that @a x must really be a JSON object or array, * passing just a value (string, integer) is not supported and will @@ -102,48 +140,115 @@ TALER_PQ_query_param_json (const json_t *x); /** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_PQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. + * Generate query parameter for an array of blinded denomination signatures + * + * @param num number of elements in @e denom_sigs + * @param denom_sigs array of blinded denomination signatures + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_blinded_denom_sig ( + size_t num, + const struct TALER_BlindedDenominationSignature *denom_sigs, + struct GNUNET_PQ_Context *db + ); + + +/** + * Generate query parameter for an array of blinded hashes of coin envelopes + * + * @param num number of elements in @e denom_sigs + * @param coin_evs array of blinded hashes of coin envelopes + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_blinded_coin_hash ( + size_t num, + const struct TALER_BlindedCoinHashP *coin_evs, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of GNUNET_HashCode + * + * @param num number of elements in @e hash_codes + * @param hashes array of GNUNET_HashCode + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_hash_code ( + size_t num, + const struct GNUNET_HashCode *hashes, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of amounts + * + * @param num of elements in @e amounts + * @param amounts continuous array of amounts + * @param db context for db-connection, needed for OID-lookup + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_amount ( + size_t num, + const struct TALER_Amount *amounts, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of amounts + * + * @param num of elements in @e amounts + * @param amounts continuous array of amounts + * @param db context for db-connection, needed for OID-lookup + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_amount_with_currency ( + size_t num, + const struct TALER_Amount *amounts, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for a blind sign public key of variable size. * - * @param x pointer to the query parameter to pass + * @param public_key pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x); +TALER_PQ_query_param_blind_sign_pub ( + const struct GNUNET_CRYPTO_BlindSignPublicKey *public_key); /** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_PQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. + * Generate query parameter for a blind sign private key of variable size. * - * @param x pointer to the query parameter to pass + * @param private_key pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_absolute_time_nbo (const struct - GNUNET_TIME_AbsoluteNBO *x); +TALER_PQ_query_param_blind_sign_priv ( + const struct GNUNET_CRYPTO_BlindSignPrivateKey *private_key); /** - * Currency amount expected. + * Currency amount expected, from a record-field of (DB) + * taler_amount_with_currency type. The currency must be stored in the + * database when using this function. * * @param name name of the field in the table - * @param currency currency to use for @a amount * @param[out] amount where to store the result * @return array entry for the result specification to use */ struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_amount_nbo (const char *name, - const char *currency, - struct TALER_AmountNBO *amount); +TALER_PQ_result_spec_amount_with_currency ( + const char *name, + struct TALER_Amount *amount); /** - * Currency amount expected. + * Currency amount expected, from a record-field of (DB) taler_amount type. + * The currency is NOT stored in the database when using this function, but + * instead passed as the @a currency argument. * * @param name name of the field in the table * @param currency currency to use for @a amount @@ -194,6 +299,32 @@ TALER_PQ_result_spec_blinded_denom_sig ( /** + * Exchange withdraw values expected. + * + * @param name name of the field in the table + * @param[out] ewv where to store the exchange values + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_exchange_withdraw_values ( + const char *name, + struct TALER_ExchangeWithdrawValues *ewv); + + +/** + * Blinded planchet expected. + * + * @param name name of the field in the table + * @param[out] bp where to store the blinded planchet + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blinded_planchet ( + const char *name, + struct TALER_BlindedPlanchet *bp); + + +/** * json_t expected. * * @param name name of the field in the table @@ -206,33 +337,89 @@ TALER_PQ_result_spec_json (const char *name, /** - * Rounded absolute time expected. - * In contrast to #GNUNET_PQ_query_param_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. + * Array of blinded denomination signature expected * + * @param db context of the database connection * @param name name of the field in the table - * @param[out] at where to store the result + * @param[out] num number of elements in @e denom_sigs + * @param[out] denom_sigs where to store the result * @return array entry for the result specification to use */ struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_absolute_time (const char *name, - struct GNUNET_TIME_Absolute *at); +TALER_PQ_result_spec_array_blinded_denom_sig ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct TALER_BlindedDenominationSignature **denom_sigs); /** - * Rounded absolute time expected. - * In contrast to #GNUNET_PQ_result_spec_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. + * Array of blinded hashes of coin envelopes * + * @param db context of the database connection * @param name name of the field in the table - * @param[out] at where to store the result + * @param[out] num number of elements in @e denom_sigs + * @param[out] h_coin_evs where to store the result * @return array entry for the result specification to use */ struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_absolute_time_nbo (const char *name, - struct GNUNET_TIME_AbsoluteNBO *at); +TALER_PQ_result_spec_array_blinded_coin_hash ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct TALER_BlindedCoinHashP **h_coin_evs); + + +/** + * Array of hashes of denominations + * + * @param db context of the database connection + * @param name name of the field in the table + * @param[out] num number of elements in @e denom_sigs + * @param[out] denom_hs where to store the result + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_array_denom_hash ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct TALER_DenominationHashP **denom_hs); + + +/** + * Array of GNUNET_HashCode + * + * @param db context of the database connection + * @param name name of the field in the table + * @param[out] num number of elements in @e denom_sigs + * @param[out] hashes where to store the result + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_array_hash_code ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct GNUNET_HashCode **hashes); + +/** + * Array of amounts + * + * @param db context of the database connection + * @param name name of the field in the table + * @param currency The currency + * @param[out] num number of elements in @e amounts + * @param[out] amounts where to store the result + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_array_amount ( + struct GNUNET_PQ_Context *db, + const char *name, + const char *currency, + size_t *num, + struct TALER_Amount **amounts); #endif /* TALER_PQ_LIB_H_ */ diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h deleted file mode 100644 index 991c56e65..000000000 --- a/src/include/taler_signatures.h +++ /dev/null @@ -1,1720 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler_signatures.h - * @brief message formats and signature constants used to define - * the binary formats of signatures in Taler - * @author Florian Dold - * @author Benedikt Mueller - * - * This file should define the constants and C structs that one needs - * to know to implement Taler clients (wallets or merchants or - * auditor) that need to produce or verify Taler signatures. - */ -#ifndef TALER_SIGNATURES_H -#define TALER_SIGNATURES_H - -#include <gnunet/gnunet_util_lib.h> -#include "taler_amount_lib.h" -#include "taler_crypto_lib.h" - -/** - * Cut-and-choose size for refreshing. Client looses the gamble (of - * unaccountable transfers) with probability 1/TALER_CNC_KAPPA. Refresh cost - * increases linearly with TALER_CNC_KAPPA, and 3 is sufficient up to a - * income/sales tax of 66% of total transaction value. As there is - * no good reason to change this security parameter, we declare it - * fixed and part of the protocol. - */ -#define TALER_CNC_KAPPA 3 - - -/*********************************************/ -/* Exchange offline signatures (with master key) */ -/*********************************************/ - -/** - * The given revocation key was revoked and must no longer be used. - */ -#define TALER_SIGNATURE_MASTER_SIGNING_KEY_REVOKED 1020 - -/** - * Add payto URI to the list of our wire methods. - */ -#define TALER_SIGNATURE_MASTER_ADD_WIRE 1021 - -/** - * Remove payto URI from the list of our wire methods. - */ -#define TALER_SIGNATURE_MASTER_DEL_WIRE 1023 - -/** - * Purpose for signing public keys signed by the exchange master key. - */ -#define TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY 1024 - -/** - * Purpose for denomination keys signed by the exchange master key. - */ -#define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY 1025 - -/** - * Add an auditor to the list of our auditors. - */ -#define TALER_SIGNATURE_MASTER_ADD_AUDITOR 1026 - -/** - * Remove an auditor from the list of our auditors. - */ -#define TALER_SIGNATURE_MASTER_DEL_AUDITOR 1027 - -/** - * Fees charged per (aggregate) wire transfer to the merchant. - */ -#define TALER_SIGNATURE_MASTER_WIRE_FEES 1028 - -/** - * The given revocation key was revoked and must no longer be used. - */ -#define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED 1029 - -/** - * Signature where the Exchange confirms its IBAN details in - * the /wire response. - */ -#define TALER_SIGNATURE_MASTER_WIRE_DETAILS 1030 - - -/*********************************************/ -/* Exchange online signatures (with signing key) */ -/*********************************************/ - -/** - * Purpose for the state of a reserve, signed by the exchange's signing - * key. - */ -#define TALER_SIGNATURE_EXCHANGE_RESERVE_STATUS 1032 - -/** - * Signature where the Exchange confirms a deposit request. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT 1033 - -/** - * Signature where the exchange (current signing key) confirms the - * no-reveal index for cut-and-choose and the validity of the melted - * coins. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT 1034 - -/** - * Signature where the Exchange confirms the full /keys response set. - */ -#define TALER_SIGNATURE_EXCHANGE_KEY_SET 1035 - -/** - * Signature where the Exchange confirms the /track/transaction response. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE 1036 - -/** - * Signature where the Exchange confirms the /wire/deposit response. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT 1037 - -/** - * Signature where the Exchange confirms a refund request. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND 1038 - -/** - * Signature where the Exchange confirms a recoup. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP 1039 - -/** - * Signature where the Exchange confirms it closed a reserve. - */ -#define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040 - -/** - * Signature where the Exchange confirms a recoup-refresh operation. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH 1041 - -/** - * Signature where the Exchange confirms that it does not know a denomination (hash). - */ -#define TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN 1042 - - -/** - * Signature where the Exchange confirms that it does not consider a denomination valid for the given operation - * at this time. - */ -#define TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED 1043 - -/** - * Signature by which an exchange affirms that an account - * successfully passed the KYC checks. - */ -#define TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS 1044 - - -/**********************/ -/* Auditor signatures */ -/**********************/ - -/** - * Signature where the auditor confirms that he is - * aware of certain denomination keys from the exchange. - */ -#define TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS 1064 - - -/***********************/ -/* Merchant signatures */ -/***********************/ - -/** - * Signature where the merchant confirms a contract (to the customer). - */ -#define TALER_SIGNATURE_MERCHANT_CONTRACT 1101 - -/** - * Signature where the merchant confirms a refund (of a coin). - */ -#define TALER_SIGNATURE_MERCHANT_REFUND 1102 - -/** - * Signature where the merchant confirms that he needs the wire - * transfer identifier for a deposit operation. - */ -#define TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION 1103 - -/** - * Signature where the merchant confirms that the payment was - * successful - */ -#define TALER_SIGNATURE_MERCHANT_PAYMENT_OK 1104 - -/** - * Signature where the merchant confirms that the user replayed - * a payment for a browser session. - */ -#define TALER_SIGNATURE_MERCHANT_PAY_SESSION 1106 - -/** - * Signature where the merchant confirms its own (salted) - * wire details (not yet really used). - */ -#define TALER_SIGNATURE_MERCHANT_WIRE_DETAILS 1107 - - -/*********************/ -/* Wallet signatures */ -/*********************/ - -/** - * Signature where the reserve key confirms a withdraw request. - */ -#define TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW 1200 - -/** - * Signature made by the wallet of a user to confirm a deposit of a coin. - */ -#define TALER_SIGNATURE_WALLET_COIN_DEPOSIT 1201 - -/** - * Signature using a coin key confirming the melting of a coin. - */ -#define TALER_SIGNATURE_WALLET_COIN_MELT 1202 - -/** - * Signature using a coin key requesting recoup. - */ -#define TALER_SIGNATURE_WALLET_COIN_RECOUP 1203 - -/** - * Signature using a coin key authenticating link data. - */ -#define TALER_SIGNATURE_WALLET_COIN_LINK 1204 - -/** - * Signature using a reserve key by which a wallet - * requests a payment target UUID for itself. - * Signs over just a purpose (no body), as the - * signature only serves to demonstrate that the request - * comes from the wallet controlling the private key, - * and not some third party. - */ -#define TALER_SIGNATURE_WALLET_ACCOUNT_SETUP 1205 - - -/******************************/ -/* Security module signatures */ -/******************************/ - -/** - * Signature on a denomination key announcement. - */ -#define TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY 1250 - -/** - * Signature on an exchange message signing key announcement. - */ -#define TALER_SIGNATURE_SM_SIGNING_KEY 1251 - -/*******************/ -/* Test signatures */ -/*******************/ - -/** - * EdDSA test signature. - */ -#define TALER_SIGNATURE_CLIENT_TEST_EDDSA 1302 - -/** - * EdDSA test signature. - */ -#define TALER_SIGNATURE_EXCHANGE_TEST_EDDSA 1303 - - -/************************/ -/* Anastasis signatures */ -/************************/ - -/** - * EdDSA signature for a policy upload. - */ -#define TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD 1400 - - -/*******************/ -/* Sync signatures */ -/*******************/ - - -/** - * EdDSA signature for a backup upload. - */ -#define TALER_SIGNATURE_SYNC_BACKUP_UPLOAD 1450 - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * @brief format used by the denomination crypto helper when affirming - * that it created a denomination key. - */ -struct TALER_DenominationKeyAnnouncementPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_SM_RSA_DENOMINATION_KEY. - * Used with an EdDSA signature of a `struct TALER_SecurityModulePublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the denomination public key. - */ - struct TALER_RsaPubHashP h_rsa; - - /** - * Hash of the section name in the configuration of this denomination. - */ - struct GNUNET_HashCode h_section_name; - - /** - * When does the key become available? - */ - struct GNUNET_TIME_AbsoluteNBO anchor_time; - - /** - * How long is the key available after @e anchor_time? - */ - struct GNUNET_TIME_RelativeNBO duration_withdraw; - -}; - - -/** - * @brief format used by the signing crypto helper when affirming - * that it created an exchange signing key. - */ -struct TALER_SigningKeyAnnouncementPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_SM_SIGNING_KEY. - * Used with an EdDSA signature of a `struct TALER_SecurityModulePublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Public signing key of the exchange this is about. - */ - struct TALER_ExchangePublicKeyP exchange_pub; - - /** - * When does the key become available? - */ - struct GNUNET_TIME_AbsoluteNBO anchor_time; - - /** - * How long is the key available after @e anchor_time? - */ - struct GNUNET_TIME_RelativeNBO duration; - -}; - -/** - * @brief Format used for to allow the wallet to authenticate - * link data provided by the exchange. - */ -struct TALER_LinkDataPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK. - * Used with an EdDSA signature of a `struct TALER_CoinPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the denomination public key of the new coin. - */ - struct TALER_DenominationHash h_denom_pub; - - /** - * Transfer public key (for which the private key was not revealed) - */ - struct TALER_TransferPublicKeyP transfer_pub; - - /** - * Hash of the blinded new coin. - */ - struct TALER_BlindedCoinHash coin_envelope_hash; -}; - - -/** - * @brief Format used for to generate the signature on a request to withdraw - * coins from a reserve. - */ -struct TALER_WithdrawRequestPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW. - * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Reserve public key (which reserve to withdraw from). This is - * the public key which must match the signature. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Value of the coin being exchangeed (matching the denomination key) - * plus the transaction fee. We include this in what is being - * signed so that we can verify a reserve's remaining total balance - * without needing to access the respective denomination key - * information each time. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Hash of the denomination public key for the coin that is withdrawn. - */ - struct TALER_DenominationHash h_denomination_pub GNUNET_PACKED; - - /** - * Hash of the (blinded) message to be signed by the Exchange. - */ - struct TALER_BlindedCoinHash h_coin_envelope GNUNET_PACKED; -}; - - -/** - * @brief Format used to generate the signature on a request to deposit - * a coin into the account of a merchant. - */ -struct TALER_DepositRequestPS -{ - /** - * Purpose must be #TALER_SIGNATURE_WALLET_COIN_DEPOSIT. - * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the contract for which this deposit is made. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * Hash over extension attributes shared with the exchange. - */ - struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct TALER_MerchantWireHash h_wire GNUNET_PACKED; - - /** - * Hash over the denomination public key used to sign the coin. - */ - struct TALER_DenominationHash h_denom_pub GNUNET_PACKED; - - /** - * Time when this request was generated. Used, for example, to - * assess when (roughly) the income was achieved for tax purposes. - * Note that the Exchange will only check that the timestamp is not "too - * far" into the future (i.e. several days). The fact that the - * timestamp falls within the validity period of the coin's - * denomination key is irrelevant for the validity of the deposit - * request, as obviously the customer and merchant could conspire to - * set any timestamp. Also, the Exchange must accept very old deposit - * requests, as the merchant might have been unable to transmit the - * deposit request in a timely fashion (so back-dating is not - * prevented). - */ - struct GNUNET_TIME_AbsoluteNBO wallet_timestamp; - - /** - * How much time does the merchant have to issue a refund request? - * Zero if refunds are not allowed. After this time, the coin - * cannot be refunded. - */ - struct GNUNET_TIME_AbsoluteNBO refund_deadline; - - /** - * Amount to be deposited, including deposit fee charged by the - * exchange. This is the total amount that the coin's value at the exchange - * will be reduced by. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Depositing fee charged by the exchange. This must match the Exchange's - * denomination key's depositing fee. If the client puts in an - * invalid deposit fee (too high or too low) that does not match the - * Exchange's denomination key, the deposit operation is invalid and - * will be rejected by the exchange. The @e amount_with_fee minus the - * @e deposit_fee is the amount that will be transferred to the - * account identified by @e h_wire. - */ - struct TALER_AmountNBO deposit_fee; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - -}; - - -/** - * @brief Format used to generate the signature on a confirmation - * from the exchange that a deposit request succeeded. - */ -struct TALER_DepositConfirmationPS -{ - /** - * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the contract for which this deposit is made. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct TALER_MerchantWireHash h_wire GNUNET_PACKED; - - /** - * Hash over the extension options of the deposit, 0 if there - * were not extension options. - */ - struct TALER_ExtensionContractHash h_extensions GNUNET_PACKED; - - /** - * Time when this confirmation was generated / when the exchange received - * the deposit request. - */ - struct GNUNET_TIME_AbsoluteNBO exchange_timestamp; - - /** - * By when does the exchange expect to pay the merchant - * (as per the merchant's request). - */ - struct GNUNET_TIME_AbsoluteNBO wire_deadline; - - /** - * How much time does the @e merchant have to issue a refund - * request? Zero if refunds are not allowed. After this time, the - * coin cannot be refunded. Note that the wire transfer will not be - * performed by the exchange until the refund deadline. This value - * is taken from the original deposit request. - */ - struct GNUNET_TIME_AbsoluteNBO refund_deadline; - - /** - * Amount to be deposited, excluding fee. Calculated from the - * amount with fee and the fee from the deposit request. - */ - struct TALER_AmountNBO amount_without_fee; - - /** - * The public key of the coin that was deposited. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant_pub; - -}; - - -/** - * @brief Format used to generate the signature on a request to refund - * a coin into the account of the customer. - */ -struct TALER_RefundRequestPS -{ - /** - * Purpose must be #TALER_SIGNATURE_MERCHANT_REFUND. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data to identify the contract - * which is being refunded. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * Merchant-generated transaction ID for the refund. - */ - uint64_t rtransaction_id GNUNET_PACKED; - - /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. - */ - struct TALER_AmountNBO refund_amount; -}; - - -/** - * @brief Format used to generate the signature on a request to refund - * a coin into the account of the customer. - */ -struct TALER_RefundConfirmationPS -{ - /** - * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data to identify the contract - * which is being refunded. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * Merchant-generated transaction ID for the refund. - */ - uint64_t rtransaction_id GNUNET_PACKED; - - /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. - */ - struct TALER_AmountNBO refund_amount; -}; - - -/** - * @brief Message signed by a coin to indicate that the coin should be - * melted. - */ -struct TALER_RefreshMeltCoinAffirmationPS -{ - /** - * Purpose is #TALER_SIGNATURE_WALLET_COIN_MELT. - * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Which melt commitment is made by the wallet. - */ - struct TALER_RefreshCommitmentP rc GNUNET_PACKED; - - /** - * Hash over the denomination public key used to sign the coin. - */ - struct TALER_DenominationHash h_denom_pub GNUNET_PACKED; - - /** - * How much of the value of the coin should be melted? This amount - * includes the fees, so the final amount contributed to the melt is - * this value minus the fee for melting the coin. We include the - * fee in what is being signed so that we can verify a reserve's - * remaining total balance without needing to access the respective - * denomination key information each time. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Melting fee charged by the exchange. This must match the Exchange's - * denomination key's melting fee. If the client puts in an invalid - * melting fee (too high or too low) that does not match the Exchange's - * denomination key, the melting operation is invalid and will be - * rejected by the exchange. The @e amount_with_fee minus the @e - * melt_fee is the amount that will be credited to the melting - * session. - */ - struct TALER_AmountNBO melt_fee; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_CoinSpendPublicKeyP coin_pub; -}; - - -/** - * @brief Format of the block signed by the Exchange in response to a successful - * "/refresh/melt" request. Hereby the exchange affirms that all of the - * coins were successfully melted. This also commits the exchange to a - * particular index to not be revealed during the refresh. - */ -struct TALER_RefreshMeltConfirmationPS -{ - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Commitment made in the /refresh/melt. - */ - struct TALER_RefreshCommitmentP rc GNUNET_PACKED; - - /** - * Index that the client will not have to reveal, in NBO. - * Must be smaller than #TALER_CNC_KAPPA. - */ - uint32_t noreveal_index GNUNET_PACKED; - -}; - - -/** - * @brief Information about a signing key of the exchange. Signing keys are used - * to sign exchange messages other than coins, i.e. to confirm that a - * deposit was successful or that a refresh was accepted. - */ -struct TALER_ExchangeSigningKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When does this signing key begin to be valid? - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * When does this signing key expire? Note: This is currently when - * the Exchange will definitively stop using it. Signatures made with - * the key remain valid until @e end. When checking validity periods, - * clients should allow for some overlap between keys and tolerate - * the use of either key during the overlap time (due to the - * possibility of clock skew). - */ - struct GNUNET_TIME_AbsoluteNBO expire; - - /** - * When do signatures with this signing key become invalid? After - * this point, these signatures cannot be used in (legal) disputes - * anymore, as the Exchange is then allowed to destroy its side of the - * evidence. @e end is expected to be significantly larger than @e - * expire (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO end; - - /** - * The public online signing key that the exchange will use - * between @e start and @e expire. - */ - struct TALER_ExchangePublicKeyP signkey_pub; -}; - - -/** - * @brief Signature made by the exchange over the full set of keys, used - * to detect cheating exchanges that give out different sets to - * different users. - */ -struct TALER_ExchangeKeySetPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_KEY_SET. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the key set issue. - */ - struct GNUNET_TIME_AbsoluteNBO list_issue_date; - - /** - * Hash over the various denomination signing keys returned. - */ - struct GNUNET_HashCode hc GNUNET_PACKED; -}; - - -/** - * @brief Signature by which an exchange affirms that an account - * successfully passed the KYC checks. - */ -struct TALER_ExchangeAccountSetupSuccessPS -{ - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS. Signed by a - * `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the payto for which the signature was - * made. - */ - struct TALER_PaytoHash h_payto; - - /** - * When was the signature made. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; -}; - - -/** - * @brief Signature made by the exchange offline key over the information of - * an auditor to be added to the exchange's set of auditors. - */ -struct TALER_MasterAddAuditorPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_ADD_AUDITOR. Signed - * by a `struct TALER_MasterPublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the change. - */ - struct GNUNET_TIME_AbsoluteNBO start_date; - - /** - * Public key of the auditor. - */ - struct TALER_AuditorPublicKeyP auditor_pub; - - /** - * Hash over the auditor's URL. - */ - struct GNUNET_HashCode h_auditor_url GNUNET_PACKED; -}; - - -/** - * @brief Signature made by the exchange offline key over the information of - * an auditor to be removed from the exchange's set of auditors. - */ -struct TALER_MasterDelAuditorPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_DEL_AUDITOR. Signed - * by a `struct TALER_MasterPublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the change. - */ - struct GNUNET_TIME_AbsoluteNBO end_date; - - /** - * Public key of the auditor. - */ - struct TALER_AuditorPublicKeyP auditor_pub; - -}; - - -/** - * @brief Signature made by the exchange offline key over the information of - * a payto:// URI to be added to the exchange's set of active wire accounts. - */ -struct TALER_MasterAddWirePS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_ADD_WIRE. Signed - * by a `struct TALER_MasterPublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the change. - */ - struct GNUNET_TIME_AbsoluteNBO start_date; - - /** - * Hash over the exchange's payto URI. - */ - struct TALER_PaytoHash h_payto GNUNET_PACKED; -}; - - -/** - * @brief Signature made by the exchange offline key over the information of - * a wire method to be removed to the exchange's set of active accounts. - */ -struct TALER_MasterDelWirePS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_DEL_WIRE. Signed - * by a `struct TALER_MasterPublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the change. - */ - struct GNUNET_TIME_AbsoluteNBO end_date; - - /** - * Hash over the exchange's payto URI. - */ - struct TALER_PaytoHash h_payto GNUNET_PACKED; - -}; - - -/** - * @brief Information about a denomination key. Denomination keys - * are used to sign coins of a certain value into existence. - */ -struct TALER_DenominationKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * The long-term offline master key of the exchange that was - * used to create @e signature. - */ - struct TALER_MasterPublicKeyP master; - - /** - * Start time of the validity period for this key. - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * The exchange will sign fresh coins between @e start and this time. - * @e expire_withdraw will be somewhat larger than @e start to - * ensure a sufficiently large anonymity set, while also allowing - * the Exchange to limit the financial damage in case of a key being - * compromised. Thus, exchanges with low volume are expected to have a - * longer withdraw period (@e expire_withdraw - @e start) than exchanges - * with high transaction volume. The period may also differ between - * types of coins. A exchange may also have a few denomination keys - * with the same value with overlapping validity periods, to address - * issues such as clock skew. - */ - struct GNUNET_TIME_AbsoluteNBO expire_withdraw; - - /** - * Coins signed with the denomination key must be spent or refreshed - * between @e start and this expiration time. After this time, the - * exchange will refuse transactions involving this key as it will - * "drop" the table with double-spending information (shortly after) - * this time. Note that wallets should refresh coins significantly - * before this time to be on the safe side. @e expire_deposit must be - * significantly larger than @e expire_withdraw (by months or even - * years). - */ - struct GNUNET_TIME_AbsoluteNBO expire_deposit; - - /** - * When do signatures with this denomination key become invalid? - * After this point, these signatures cannot be used in (legal) - * disputes anymore, as the Exchange is then allowed to destroy its side - * of the evidence. @e expire_legal is expected to be significantly - * larger than @e expire_deposit (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO expire_legal; - - /** - * The value of the coins signed with this denomination key. - */ - struct TALER_AmountNBO value; - - /** - * The fee the exchange charges when a coin of this type is withdrawn. - * (can be zero). - */ - struct TALER_AmountNBO fee_withdraw; - - /** - * The fee the exchange charges when a coin of this type is deposited. - * (can be zero). - */ - struct TALER_AmountNBO fee_deposit; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refresh; - - /** - * The fee the exchange charges when a coin of this type is refunded. - * (can be zero). Note that refund fees are charged to the customer; - * if a refund is given, the deposit fee is also refunded. - */ - struct TALER_AmountNBO fee_refund; - - /** - * Hash code of the denomination public key. (Used to avoid having - * the variable-size RSA key in this struct.) - */ - struct TALER_DenominationHash denom_hash GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by an auditor affirming - * the master public key and the denomination keys - * of a exchange. - */ -struct TALER_ExchangeKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the auditor's URL (including 0-terminator). - */ - struct GNUNET_HashCode auditor_url_hash; - - /** - * The long-term offline master key of the exchange, affirmed by the - * auditor. - */ - struct TALER_MasterPublicKeyP master; - - /** - * Start time of the validity period for this key. - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * The exchange will sign fresh coins between @e start and this time. - * @e expire_withdraw will be somewhat larger than @e start to - * ensure a sufficiently large anonymity set, while also allowing - * the Exchange to limit the financial damage in case of a key being - * compromised. Thus, exchanges with low volume are expected to have a - * longer withdraw period (@e expire_withdraw - @e start) than exchanges - * with high transaction volume. The period may also differ between - * types of coins. A exchange may also have a few denomination keys - * with the same value with overlapping validity periods, to address - * issues such as clock skew. - */ - struct GNUNET_TIME_AbsoluteNBO expire_withdraw; - - /** - * Coins signed with the denomination key must be spent or refreshed - * between @e start and this expiration time. After this time, the - * exchange will refuse transactions involving this key as it will - * "drop" the table with double-spending information (shortly after) - * this time. Note that wallets should refresh coins significantly - * before this time to be on the safe side. @e expire_deposit must be - * significantly larger than @e expire_withdraw (by months or even - * years). - */ - struct GNUNET_TIME_AbsoluteNBO expire_deposit; - - /** - * When do signatures with this denomination key become invalid? - * After this point, these signatures cannot be used in (legal) - * disputes anymore, as the Exchange is then allowed to destroy its side - * of the evidence. @e expire_legal is expected to be significantly - * larger than @e expire_deposit (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO expire_legal; - - /** - * The value of the coins signed with this denomination key. - */ - struct TALER_AmountNBO value; - - /** - * The fee the exchange charges when a coin of this type is withdrawn. - * (can be zero). - */ - struct TALER_AmountNBO fee_withdraw; - - /** - * The fee the exchange charges when a coin of this type is deposited. - * (can be zero). - */ - struct TALER_AmountNBO fee_deposit; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refresh; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refund; - - /** - * Hash code of the denomination public key. (Used to avoid having - * the variable-size RSA key in this struct.) - */ - struct TALER_DenominationHash denom_hash GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by the exchange's master - * key affirming the IBAN details for the exchange. - */ -struct TALER_MasterWireDetailsPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_WIRE_DETAILS. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the account holder's payto:// URL. - */ - struct TALER_PaytoHash h_wire_details GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by the exchange's master - * key affirming the IBAN details for the exchange. - */ -struct TALER_MerchantWireDetailsPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MERCHANT_WIRE_DETAILS. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Salted hash over the account holder's payto:// URL and - * the salt, as done by #TALER_exchange_wire_signature_hash(). - */ - struct TALER_MerchantWireHash h_wire_details GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by the exchange's master - * key stating the wire fee to be paid per wire transfer. - */ -struct TALER_MasterWireFeePS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_WIRE_FEES. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the wire method (yes, H("x-taler-bank") or H("iban")), in lower - * case, including 0-terminator. Used to uniquely identify which - * wire method these fees apply to. - */ - struct GNUNET_HashCode h_wire_method; - - /** - * Start date when the fee goes into effect. - */ - struct GNUNET_TIME_AbsoluteNBO start_date; - - /** - * End date when the fee stops being in effect (exclusive) - */ - struct GNUNET_TIME_AbsoluteNBO end_date; - - /** - * Fee charged to the merchant per wire transfer. - */ - struct TALER_AmountNBO wire_fee; - - /** - * Closing fee charged when we wire back funds of a reserve. - */ - struct TALER_AmountNBO closing_fee; - -}; - - -/** - * @brief Message confirming that a denomination key was revoked. - */ -struct TALER_MasterDenominationKeyRevocationPS -{ - /** - * Purpose is #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the denomination key. - */ - struct TALER_DenominationHash h_denom_pub; - -}; - - -/** - * @brief Message confirming that an exchange online signing key was revoked. - */ -struct TALER_MasterSigningKeyRevocationPS -{ - /** - * Purpose is #TALER_SIGNATURE_MASTER_SIGNING_KEY_REVOKED. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * The exchange's public key. - */ - struct TALER_ExchangePublicKeyP exchange_pub; - -}; - - -/** - * @brief Format used to generate the signature on a request to obtain - * the wire transfer identifier associated with a deposit. - */ -struct TALER_DepositTrackPS -{ - /** - * Purpose must be #TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data of the contract for which this deposit is made. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct TALER_MerchantWireHash h_wire GNUNET_PACKED; - - /** - * The Merchant's public key. The deposit inquiry request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - -}; - - -/** - * @brief Format internally used for packing the detailed information - * to generate the signature for /track/transfer signatures. - */ -struct TALER_WireDepositDetailP -{ - - /** - * Hash of the contract - */ - struct TALER_PrivateContractHash h_contract_terms; - - /** - * Time when the wire transfer was performed by the exchange. - */ - struct GNUNET_TIME_AbsoluteNBO execution_time; - - /** - * Coin's public key. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Total value of the coin. - */ - struct TALER_AmountNBO deposit_value; - - /** - * Fees charged by the exchange for the deposit. - */ - struct TALER_AmountNBO deposit_fee; - -}; - - -/** - * @brief Format used to generate the signature for /wire/deposit - * replies. - */ -struct TALER_WireDepositDataPS -{ - /** - * Purpose header for the signature over the contract with - * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Total amount that was transferred. - */ - struct TALER_AmountNBO total; - - /** - * Wire fee that was charged. - */ - struct TALER_AmountNBO wire_fee; - - /** - * Public key of the merchant (for all aggregated transactions). - */ - struct TALER_MerchantPublicKeyP merchant_pub; - - /** - * Hash of bank account of the merchant. - */ - struct TALER_PaytoHash h_payto; - - /** - * Hash of the individual deposits that were aggregated, - * each in the format of a `struct TALER_WireDepositDetailP`. - */ - struct GNUNET_HashCode h_details; - -}; - -/** - * The contract sent by the merchant to the wallet. - */ -struct TALER_ProposalDataPS -{ - /** - * Purpose header for the signature over the proposal data - * with purpose #TALER_SIGNATURE_MERCHANT_CONTRACT. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the JSON contract in UTF-8 including 0-termination, - * using JSON_COMPACT | JSON_SORT_KEYS - */ - struct TALER_PrivateContractHash hash; -}; - -/** - * Used by merchants to return signed responses to /pay requests. - * Currently only used to return 200 OK signed responses. - */ -struct TALER_PaymentResponsePS -{ - /** - * Set to #TALER_SIGNATURE_MERCHANT_PAYMENT_OK. Note that - * unsuccessful payments are usually proven by some exchange's signature. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the proposal data associated with this confirmation - */ - struct TALER_PrivateContractHash h_contract_terms; -}; - - -/** - * Details affirmed by the exchange about a wire transfer the exchange - * claims to have done with respect to a deposit operation. - */ -struct TALER_ConfirmWirePS -{ - /** - * Purpose header for the signature over the contract with - * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the wiring information of the merchant. - */ - struct TALER_MerchantWireHash h_wire GNUNET_PACKED; - - /** - * Hash over the contract for which this deposit is made. - */ - struct TALER_PrivateContractHash h_contract_terms GNUNET_PACKED; - - /** - * Raw value (binary encoding) of the wire transfer subject. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * When did the exchange execute this transfer? Note that the - * timestamp may not be exactly the same on the wire, i.e. - * because the wire has a different timezone or resolution. - */ - struct GNUNET_TIME_AbsoluteNBO execution_time; - - /** - * The contribution of @e coin_pub to the total transfer volume. - * This is the value of the deposit minus the fee. - */ - struct TALER_AmountNBO coin_contribution; - -}; - - -/** - * Signed data to request that a coin should be refunded as part of - * the "emergency" /recoup protocol. The refund will go back to the bank - * account that created the reserve. - */ -struct TALER_RecoupRequestPS -{ - /** - * Purpose is #TALER_SIGNATURE_WALLET_COIN_RECOUP - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Public key of the coin to be refunded. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Hash of the (revoked) denomination public key of the coin. - */ - struct TALER_DenominationHash h_denom_pub; - - /** - * Blinding factor that was used to withdraw the coin. - */ - union TALER_DenominationBlindingKeyP coin_blind; -}; - - -/** - * Response by which the exchange affirms that it will - * refund a coin as part of the emergency /recoup - * protocol. The recoup will go back to the bank - * account that created the reserve. - */ -struct TALER_RecoupConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange receive the recoup request? - * Indirectly determines when the wire transfer is (likely) - * to happen. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much of the coin's value will the exchange transfer? - * (Needed in case the coin was partially spent.) - */ - struct TALER_AmountNBO recoup_amount; - - /** - * Public key of the coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Public key of the reserve that will receive the recoup. - */ - struct TALER_ReservePublicKeyP reserve_pub; -}; - - -/** - * Response by which the exchange affirms that it will refund a refreshed coin - * as part of the emergency /recoup protocol. The recoup will go back to the - * old coin's balance. - */ -struct TALER_RecoupRefreshConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange receive the recoup request? - * Indirectly determines when the wire transfer is (likely) - * to happen. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much of the coin's value will the exchange transfer? - * (Needed in case the coin was partially spent.) - */ - struct TALER_AmountNBO recoup_amount; - - /** - * Public key of the refreshed coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Public key of the old coin that will receive the recoup. - */ - struct TALER_CoinSpendPublicKeyP old_coin_pub; -}; - - -/** - * Response by which the exchange affirms that it does not - * currently know a denomination by the given hash. - */ -struct TALER_DenominationUnknownAffirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_UNKNOWN - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange sign this message. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * Hash of the public denomination key we do not know. - */ - struct TALER_DenominationHash h_denom_pub; -}; - - -/** - * Response by which the exchange affirms that it does not - * currently consider the given denomination to be valid - * for the requested operation. - */ -struct TALER_DenominationExpiredAffirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_AFFIRM_DENOM_EXPIRED - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange sign this message. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * Name of the operation that is not allowed at this time. Might NOT be 0-terminated, but is padded with 0s. - */ - char operation[8]; - - /** - * Hash of the public denomination key we do not know. - */ - struct TALER_DenominationHash h_denom_pub; - -}; - - -/** - * Response by which the exchange affirms that it has - * closed a reserve and send back the funds. - */ -struct TALER_ReserveCloseConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange initiate the wire transfer. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much did the exchange send? - */ - struct TALER_AmountNBO closing_amount; - - /** - * How much did the exchange charge for closing the reserve? - */ - struct TALER_AmountNBO closing_fee; - - /** - * Public key of the reserve that received the recoup. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Hash of the receiver's bank account. - */ - struct TALER_PaytoHash h_payto; - - /** - * Wire transfer subject. - */ - struct TALER_WireTransferIdentifierRawP wtid; -}; - - -/** - * Used by the merchant to confirm to the frontend that - * the user did a payment replay with the current browser session. - */ -struct TALER_MerchantPaySessionSigPS -{ - /** - * Set to #TALER_SIGNATURE_MERCHANT_PAY_SESSION. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hashed order id. - * Hashed without the 0-termination. - */ - struct GNUNET_HashCode h_order_id GNUNET_PACKED; - - /** - * Hashed session id. - * Hashed without the 0-termination. - */ - struct GNUNET_HashCode h_session_id GNUNET_PACKED; - -}; - - -GNUNET_NETWORK_STRUCT_END - -#endif diff --git a/src/include/taler_sq_lib.h b/src/include/taler_sq_lib.h index 66bd38c82..b5749308e 100644 --- a/src/include/taler_sq_lib.h +++ b/src/include/taler_sq_lib.h @@ -61,33 +61,6 @@ TALER_SQ_query_param_json (const json_t *x); /** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_SQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. - * - * @param x pointer to the query parameter to pass - */ -struct GNUNET_SQ_QueryParam -TALER_SQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x); - - -/** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_SQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. - * - * @param x pointer to the query parameter to pass - */ -struct GNUNET_SQ_QueryParam -TALER_SQ_query_param_absolute_time_nbo (const struct - GNUNET_TIME_AbsoluteNBO *x); - - -/** * Currency amount expected. * * @param currency currency to use for @a amount @@ -121,32 +94,6 @@ struct GNUNET_SQ_ResultSpec TALER_SQ_result_spec_json (json_t **jp); -/** - * Rounded absolute time expected. - * In contrast to #GNUNET_SQ_query_param_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. - * - * @param[out] at where to store the result - * @return array entry for the result specification to use - */ -struct GNUNET_SQ_ResultSpec -TALER_SQ_result_spec_absolute_time (struct GNUNET_TIME_Absolute *at); - - -/** - * Rounded absolute time expected. - * In contrast to #GNUNET_SQ_result_spec_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. - * - * @param[out] at where to store the result - * @return array entry for the result specification to use - */ -struct GNUNET_SQ_ResultSpec -TALER_SQ_result_spec_absolute_time_nbo (struct GNUNET_TIME_AbsoluteNBO *at); - - #endif /* TALER_SQ_LIB_H_ */ /* end of include/taler_sq_lib.h */ diff --git a/src/include/taler_templating_lib.h b/src/include/taler_templating_lib.h new file mode 100644 index 000000000..6af6db715 --- /dev/null +++ b/src/include/taler_templating_lib.h @@ -0,0 +1,130 @@ +/* + This file is part of TALER + Copyright (C) 2020, 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler_templating_lib.h + * @brief logic to load and complete HTML templates + * @author Christian Grothoff + */ +#ifndef TALER_TEMPLATING_LIB_H +#define TALER_TEMPLATING_LIB_H + +#include <microhttpd.h> +#include "taler_mhd_lib.h" + +/** + * Fill in Mustach template @a tmpl using the data from @a root + * and return the result in @a result. + * + * @param tmpl 0-terminated string with Mustach template + * @param root JSON data to fill into the template + * @param[out] result where to write the result + * @param[out] result_size where to write the length of the result + * @return 0 on success, otherwise Mustach-specific error code + */ +int +TALER_TEMPLATING_fill (const char *tmpl, + const json_t *root, + void **result, + size_t *result_size); + + +/** + * Load a @a template and substitute using @a root, returning the result in a + * @a reply encoded suitable for the @a connection with the given @a + * http_status code. On errors, the @a http_status code + * is updated to reflect the type of error encoded in the + * @a reply. + * + * @param connection the connection we act upon + * @param[in,out] http_status code to use on success, + * set to alternative code on failure + * @param template basename of the template to load + * @param instance_id instance ID, used to compute static files URL + * @param taler_uri value for "Taler:" header to set, or NULL + * @param root JSON object to pass as the root context + * @param[out] reply where to write the response object + * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, + * #GNUNET_SYSERR on failure (to queue an error) + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_build (struct MHD_Connection *connection, + unsigned int *http_status, + const char *template, + const char *instance_id, + const char *taler_uri, + const json_t *root, + struct MHD_Response **reply); + + +/** + * Load a @a template and substitute using @a root, returning + * the result to the @a connection with the given + * @a http_status code. + * + * @param connection the connection we act upon + * @param http_status code to use on success + * @param template basename of the template to load + * @param instance_id instance ID, used to compute static files URL + * @param taler_uri value for "Taler:" header to set, or NULL + * @param root JSON object to pass as the root context + * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, + * #GNUNET_SYSERR on failure (to queue an error) + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_reply (struct MHD_Connection *connection, + unsigned int http_status, + const char *template, + const char *instance_id, + const char *taler_uri, + const json_t *root); + + +/** + * Load a @a template and substitute an error message based on @a ec and @a + * detail, returning the result to the @a connection with the given @a + * http_status code. + * + * @param connection the connection we act upon + * @param template_basename basename of the template to load + * @param http_status code to use on success + * @param ec error code to return + * @param detail optional text to add to the template + * @return #MHD_YES on success, #MHD_NO to just close the connection + */ +MHD_RESULT +TALER_TEMPLATING_reply_error (struct MHD_Connection *connection, + const char *template_basename, + unsigned int http_status, + enum TALER_ErrorCode ec, + const char *detail); + +/** + * Preload templates. + * + * @param subsystem name of the subsystem, "merchant" or "exchange" + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_init (const char *subsystem); + + +/** + * Nicely shut down templating subsystem. + */ +void +TALER_TEMPLATING_done (void); + +#endif diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index f50e13a21..f07d9be20 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2018 Taler Systems SA + (C) 2018-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -20,6 +20,8 @@ /** * @file include/taler_testing_lib.h * @brief API for writing an interpreter to test Taler components + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Christian Grothoff <christian@grothoff.org> * @author Marcello Stanisci */ @@ -27,11 +29,13 @@ #define TALER_TESTING_LIB_H #include "taler_util.h" -#include "taler_exchange_service.h" +#include <microhttpd.h> #include <gnunet/gnunet_json_lib.h> #include "taler_json_lib.h" +#include "taler_auditor_service.h" #include "taler_bank_service.h" -#include <microhttpd.h> +#include "taler_exchange_service.h" +#include "taler_fakebank_lib.h" /* ********************* Helper functions ********************* */ @@ -50,155 +54,156 @@ /** - * Allocate and return a piece of wire-details. Combines - * a @a payto -URL and adds some salt to create the JSON. + * Log an error message about us receiving an unexpected HTTP + * status code at the current command and fail the test. * - * @param payto payto://-URL to encapsulate - * @return JSON describing the account, including the - * payto://-URL of the account, must be manually decref'd + * @param is interpreter to fail + * @param status unexpected HTTP status code received + * @param expected expected HTTP status code */ -json_t * -TALER_TESTING_make_wire_details (const char *payto); +#define TALER_TESTING_unexpected_status(is,status,expected) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Unexpected response code %u (expected: %u) to command %s in %s:%u\n", \ + status, \ + expected, \ + TALER_TESTING_interpreter_get_current_label (is), \ + __FILE__, \ + __LINE__); \ + TALER_TESTING_interpreter_fail (is); \ + } while (0) + +/** + * Log an error message about us receiving an unexpected HTTP + * status code at the current command and fail the test and print the response + * body (expected as json). + * + * @param is interpreter to fail + * @param status unexpected HTTP status code received + * @param expected expected HTTP status code + * @param body received JSON-reply + */ +#define TALER_TESTING_unexpected_status_with_body(is,status,expected,body) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Unexpected response code %u (expected: %u) to " \ + "command %s in %s:%u\nwith body:\n>>%s<<\n", \ + status, \ + expected, \ + TALER_TESTING_interpreter_get_current_label (is), \ + __FILE__, \ + __LINE__, \ + json_dumps (body, JSON_INDENT (2))); \ + TALER_TESTING_interpreter_fail (is); \ + } while (0) /** - * Find denomination key matching the given amount. + * Log an error message about a command not having + * run to completion. * - * @param keys array of keys to search - * @param amount coin value to look for - * @return NULL if no matching key was found + * @param is interpreter + * @param label command label of the incomplete command */ -const struct TALER_EXCHANGE_DenomPublicKey * -TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *amount); +#define TALER_TESTING_command_incomplete(is,label) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Command %s (%s:%u) did not complete (at %s)\n", \ + label, \ + __FILE__, \ + __LINE__, \ + TALER_TESTING_interpreter_get_current_label (is)); \ + } while (0) /** - * Configuration data for an exchange. + * Common credentials used in a test. */ -struct TALER_TESTING_ExchangeConfiguration +struct TALER_TESTING_Credentials { /** - * Exchange base URL as it appears in the configuration. Note - * that it might differ from the one where the exchange actually - * listens from. + * Bank authentication details for the exchange bank + * account. */ - char *exchange_url; + struct TALER_BANK_AuthenticationData ba; /** - * Auditor base URL as it appears in the configuration. Note - * that it might differ from the one where the auditor actually - * listens from. + * Bank authentication details for the admin bank + * account. */ - char *auditor_url; + struct TALER_BANK_AuthenticationData ba_admin; -}; + /** + * Configuration file data. + */ + struct GNUNET_CONFIGURATION_Handle *cfg; -/** - * Connection to the database: aggregates - * plugin and session handles. - */ -struct TALER_TESTING_DatabaseConnection -{ /** - * Database plugin. + * Base URL of the exchange. */ - struct TALER_EXCHANGEDB_Plugin *plugin; + char *exchange_url; -}; + /** + * Base URL of the auditor. + */ + char *auditor_url; -struct TALER_TESTING_LibeufinServices -{ /** - * Nexus + * RFC 8905 URI of the exchange. */ - struct GNUNET_OS_Process *nexus; + char *exchange_payto; /** - * Sandbox + * RFC 8905 URI of a user. */ - struct GNUNET_OS_Process *sandbox; + char *user42_payto; + /** + * RFC 8905 URI of a user. + */ + char *user43_payto; }; -/** - * Prepare launching an exchange. Checks that the configured - * port is available, runs taler-exchange-keyup, - * taler-auditor-sign and taler-exchange-dbinit. Does not - * launch the exchange process itself. - * - * @param config_filename configuration file to use - * @param reset_db should we reset the database - * @param[out] ec will be set to the exchange configuration data - * @return #GNUNET_OK on success, #GNUNET_NO if test should be - * skipped, #GNUNET_SYSERR on test failure - */ -int -TALER_TESTING_prepare_exchange (const char *config_filename, - int reset_db, - struct TALER_TESTING_ExchangeConfiguration *ec); - - -/** - * "Canonical" cert_cb used when we are connecting to the - * Exchange. - * - * @param cls closure, typically, the "run" method containing - * all the commands to be run, and a closure for it. - * @param hr http response details - * @param keys the exchange's keys. - * @param compat protocol compatibility information. - */ -void -TALER_TESTING_cert_cb (void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_EXCHANGE_Keys *keys, - enum TALER_EXCHANGE_VersionCompatibility compat); - /** - * Wait for the exchange to have started. Waits for at - * most 10s, after that returns 77 to indicate an error. - * - * @param base_url what URL should we expect the exchange - * to be running at - * @return 0 on success + * What type of bank are we using? */ -int -TALER_TESTING_wait_exchange_ready (const char *base_url); - - -/** - * Wait for an HTTPD service to have started. Waits for at - * most 10s, after that returns 77 to indicate an error. - * - * @param base_url what URL should we expect the exchange - * to be running at - * @return 0 on success - */ -int -TALER_TESTING_wait_httpd_ready (const char *base_url); +enum TALER_TESTING_BankSystem +{ + TALER_TESTING_BS_FAKEBANK = 1, + TALER_TESTING_BS_IBAN = 2 +}; /** - * Wait for the auditor to have started. Waits for at - * most 10s, after that returns 77 to indicate an error. + * Obtain bank credentials for a given @a cfg_file using + * @a exchange_account_section as the basis for the + * exchange account. * - * @param base_url what URL should we expect the auditor - * to be running at - * @return 0 on success + * @param cfg_file name of configuration to parse + * @param exchange_account_section configuration section name for the exchange account to use + * @param bs type of bank to use + * @param[out] ua where to write user account details + * and other credentials */ -int -TALER_TESTING_wait_auditor_ready (const char *base_url); +enum GNUNET_GenericReturnValue +TALER_TESTING_get_credentials ( + const char *cfg_file, + const char *exchange_account_section, + enum TALER_TESTING_BankSystem bs, + struct TALER_TESTING_Credentials *ua); /** - * Remove files from previous runs + * Allocate and return a piece of wire-details. Combines + * a @a payto -URL and adds some salt to create the JSON. * - * @param config_name configuration file to use+ + * @param payto payto://-URL to encapsulate + * @return JSON describing the account, including the + * payto://-URL of the account, must be manually decref'd */ -void -TALER_TESTING_cleanup_files (const char *config_name); +json_t * +TALER_TESTING_make_wire_details (const char *payto); /** @@ -208,71 +213,23 @@ TALER_TESTING_cleanup_files (const char *config_name); * @param cfg configuration * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_TESTING_cleanup_files_cfg (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg); /** - * Run `taler-exchange-offline`. - * - * @param config_filename configuration file to use - * @param payto_uri bank account to enable, can be NULL - * @param auditor_pub public key of auditor to enable, can be NULL - * @param auditor_url URL of auditor to enable, can be NULL - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_run_exchange_offline (const char *config_filename, - const char *payto_uri, - const char *auditor_pub, - const char *auditor_url); - - -/** - * Run `taler-auditor-dbinit -r` (reset auditor database). - * - * @param config_filename configuration file to use - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_auditor_db_reset (const char *config_filename); - - -/** - * Run `taler-exchange-dbinit -r` (reset exchange database). - * - * @param config_filename configuration file to use - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_exchange_db_reset (const char *config_filename); - - -/** - * Run `taler-auditor-offline` tool. - * - * @param config_filename configuration file to use - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_run_auditor_offline (const char *config_filename); - - -/** - * Run `taler-auditor-exchange`. + * Find denomination key matching the given amount. * - * @param config_filename configuration file to use - * @param exchange_master_pub master public key of the exchange - * @param exchange_base_url what is the base URL of the exchange - * @param do_remove #GNUNET_NO to add exchange, #GNUNET_YES to remove - * @return #GNUNET_OK on success + * @param keys array of keys to search + * @param amount coin value to look for + * @param age_restricted must the denomination be age restricted? + * @return NULL if no matching key was found */ -int -TALER_TESTING_run_auditor_exchange (const char *config_filename, - const char *exchange_master_pub, - const char *exchange_base_url, - int do_remove); +const struct TALER_EXCHANGE_DenomPublicKey * +TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *amount, + bool age_restricted); /** @@ -281,198 +238,17 @@ TALER_TESTING_run_auditor_exchange (const char *config_filename, * @param url URL to extract port from, 80 is default * @return #GNUNET_OK if the port is free */ -int +enum GNUNET_GenericReturnValue TALER_TESTING_url_port_free (const char *url); -/** - * Configuration data for a bank. - */ -struct TALER_TESTING_BankConfiguration -{ - - /** - * Authentication data for the exchange user at the bank. - */ - struct TALER_BANK_AuthenticationData exchange_auth; - - /** - * Payto URL of the exchange's account ("2") - */ - char *exchange_payto; - - /** - * Payto URL of a user account ("42") - */ - char *user42_payto; - - /** - * Payto URL of another user's account ("43") - */ - char *user43_payto; - -}; - -/** - * Prepare launching a fakebank. Check that the configuration - * file has the right option, and that the port is available. - * If everything is OK, return the configuration data of the fakebank. - * - * @param config_filename configuration file to use - * @param config_section which account to use - * (must match x-taler-bank) - * @param[out] bc set to the bank's configuration data - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_prepare_fakebank (const char *config_filename, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); - - /* ******************* Generic interpreter logic ************ */ /** * Global state of the interpreter, used by a command * to access information about other commands. */ -struct TALER_TESTING_Interpreter -{ - - /** - * Commands the interpreter will run. - */ - struct TALER_TESTING_Command *commands; - - /** - * Interpreter task (if one is scheduled). - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * ID of task called whenever we get a SIGCHILD. - * Used for #TALER_TESTING_wait_for_sigchld(). - */ - struct GNUNET_SCHEDULER_Task *child_death_task; - - /** - * Main execution context for the main loop. - */ - struct GNUNET_CURL_Context *ctx; - - /** - * Our configuration. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Context for running the CURL event loop. - */ - struct GNUNET_CURL_RescheduleContext *rc; - - /** - * Handle to our fakebank, if #TALER_TESTING_run_with_fakebank() - * was used. Otherwise NULL. - */ - struct TALER_FAKEBANK_Handle *fakebank; - - /** - * Task run on timeout. - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * Function to call for cleanup at the end. Can be NULL. - */ - GNUNET_SCHEDULER_TaskCallback final_cleanup_cb; - - /** - * Closure for #final_cleanup_cb(). - */ - void *final_cleanup_cb_cls; - - /** - * Instruction pointer. Tells #interpreter_run() which instruction to run - * next. Need (signed) int because it gets -1 when rewinding the - * interpreter to the first CMD. - */ - int ip; - - /** - * Result of the testcases, #GNUNET_OK on success - */ - int result; - - /** - * Handle to the exchange. - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** - * Handle to the auditor. NULL unless specifically initialized - * as part of #TALER_TESTING_auditor_setup(). - */ - struct TALER_AUDITOR_Handle *auditor; - - /** - * Handle to exchange process; some commands need it - * to send signals. E.g. to trigger the key state reload. - */ - struct GNUNET_OS_Process *exchanged; - - /** - * Public key of the auditor. - */ - struct TALER_AuditorPublicKeyP auditor_pub; - - /** - * Private key of the auditor. - */ - struct TALER_AuditorPrivateKeyP auditor_priv; - - /** - * Private offline signing key. - */ - struct TALER_MasterPrivateKeyP master_priv; - - /** - * Public offline signing key. - */ - struct TALER_MasterPublicKeyP master_pub; - - /** - * URL of the auditor (as per configuration). - */ - char *auditor_url; - - /** - * URL of the exchange (as per configuration). - */ - char *exchange_url; - - /** - * Is the interpreter running (#GNUNET_YES) or waiting - * for /keys (#GNUNET_NO)? - */ - int working; - - /** - * Is the auditor running (#GNUNET_YES) or waiting - * for /version (#GNUNET_NO)? - */ - int auditor_working; - - /** - * How often have we gotten a /keys response so far? - */ - unsigned int key_generation; - - /** - * Exchange keys from last download. - */ - const struct TALER_EXCHANGE_Keys *keys; - -}; +struct TALER_TESTING_Interpreter; /** @@ -493,6 +269,11 @@ struct TALER_TESTING_Command const char *label; /** + * Variable name for the command, NULL for none. + */ + const char *name; + + /** * Runs the command. Note that upon return, the interpreter * will not automatically run the next command, as the command * may continue asynchronously in other scheduler tasks. Thus, @@ -502,12 +283,12 @@ struct TALER_TESTING_Command * * @param cls closure * @param cmd command being run - * @param i interpreter state + * @param is interpreter state */ void (*run)(void *cls, const struct TALER_TESTING_Command *cmd, - struct TALER_TESTING_Interpreter *i); + struct TALER_TESTING_Interpreter *is); /** @@ -531,7 +312,7 @@ struct TALER_TESTING_Command * @param index index number of the object to extract. * @return #GNUNET_OK on success */ - int + enum GNUNET_GenericReturnValue (*traits)(void *cls, const void **ret, const char *trait, @@ -576,7 +357,41 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is, /** - * Obtain main execution context for the main loop. + * Get command from hash map by variable name. + * + * @param is interpreter state. + * @param name name of the variable to get command by + * @return the command, if it is found, or NULL. + */ +const struct TALER_TESTING_Command * +TALER_TESTING_interpreter_get_command (struct TALER_TESTING_Interpreter *is, + const char *name); + + +/** + * Update the last request time of the current command + * to the current time. + * + * @param[in,out] is interpreter state where to show + * that we are doing something + */ +void +TALER_TESTING_touch_cmd (struct TALER_TESTING_Interpreter *is); + + +/** + * Increment the 'num_tries' counter for the current + * command. + * + * @param[in,out] is interpreter state where to + * increment the counter + */ +void +TALER_TESTING_inc_tries (struct TALER_TESTING_Interpreter *is); + + +/** + * Obtain CURL context for the main loop. * * @param is interpreter state. * @return CURL execution context. @@ -597,15 +412,6 @@ TALER_TESTING_interpreter_get_current_label ( /** - * Get connection handle to the fakebank. - * - * @param is interpreter state. - * @return the handle. - */ -struct TALER_FAKEBANK_Handle * -TALER_TESTING_interpreter_get_fakebank (struct TALER_TESTING_Interpreter *is); - -/** * Current command is done, run the next one. * * @param is interpreter state. @@ -621,14 +427,6 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is); void TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is); -/** - * Create command array terminator. - * - * @return a end-command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_end (void); - /** * Make the instruction pointer point to @a target_label @@ -685,20 +483,6 @@ TALER_TESTING_run2 (struct TALER_TESTING_Interpreter *is, /** - * First launch the fakebank, then schedule the first CMD - * in the array of all the CMDs to execute. - * - * @param is interpreter state. - * @param commands array of all the commands to execute. - * @param bank_url base URL of the fake bank. - */ -void -TALER_TESTING_run_with_fakebank (struct TALER_TESTING_Interpreter *is, - struct TALER_TESTING_Command *commands, - const char *bank_url); - - -/** * The function that contains the array of all the CMDs to run, * which is then on charge to call some fashion of * TALER_TESTING_run*. In all the test cases, this function is @@ -713,233 +497,197 @@ typedef void /** - * Install signal handlers plus schedules the main wrapper - * around the "run" method. + * Run Taler testing loop. Starts the GNUnet SCHEDULER (event loop). * - * @param main_cb the "run" method which coontains all the - * commands. - * @param main_cb_cls a closure for "run", typically NULL. - * @param cfg configuration to use - * @param exchanged exchange process handle: will be put in the - * state as some commands - e.g. revoke - need to send - * signal to it, for example to let it know to reload the - * key state. If NULL, the interpreter will run without - * trying to connect to the exchange first. - * @param exchange_connect #GNUNET_YES if the test should connect - * to the exchange, #GNUNET_NO otherwise - * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise. - * non-#GNUNET_OK codes are #GNUNET_SYSERR most of the - * times. + * @param main_cb main function to run + * @param main_cb_cls closure for @a main_cb */ -int -TALER_TESTING_setup (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_OS_Process *exchanged, - int exchange_connect); +enum GNUNET_GenericReturnValue +TALER_TESTING_loop (TALER_TESTING_Main main_cb, + void *main_cb_cls); /** - * Install signal handlers plus schedules the main wrapper - * around the "run" method. + * Convenience function to run a test. * - * @param main_cb the "run" method which contains all the - * commands. - * @param main_cb_cls a closure for "run", typically NULL. - * @param config_filename configuration filename. - * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise. - * non-GNUNET_OK codes are #GNUNET_SYSERR most of the - * times. + * @param argv command-line arguments given + * @param loglevel log level to use + * @param cfg_file configuration file to use + * @param exchange_account_section configuration section + * with exchange bank account to use + * @param bs bank system to use + * @param[in,out] cred global credentials to initialize + * @param main_cb main test function to run + * @param main_cb_cls closure for @a main_cb + * @return 0 on success, 77 on setup trouble, non-zero process status code otherwise */ int -TALER_TESTING_auditor_setup (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_filename); +TALER_TESTING_main (char *const *argv, + const char *loglevel, + const char *cfg_file, + const char *exchange_account_section, + enum TALER_TESTING_BankSystem bs, + struct TALER_TESTING_Credentials *cred, + TALER_TESTING_Main main_cb, + void *main_cb_cls); /** - * Closure for #TALER_TESTING_setup_with_exchange_cfg(). + * Callback over commands of an interpreter. + * + * @param cls closure + * @param cmd a command to process */ -struct TALER_TESTING_SetupContext -{ - /** - * Main function of the test to run. - */ - TALER_TESTING_Main main_cb; - - /** - * Closure for @e main_cb. - */ - void *main_cb_cls; - - /** - * Name of the configuration file. - */ - const char *config_filename; -}; +typedef void +(*TALER_TESTING_CommandIterator)( + void *cls, + const struct TALER_TESTING_Command *cmd); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the exchange using the given - * configuration file. + * Iterates over all of the top-level commands of an + * interpreter. * - * @param cls must be a `struct TALER_TESTING_SetupContext *` - * @param cfg configuration to use. - * @return #GNUNET_OK if no errors occurred. + * @param[in] is interpreter to iterate over + * @param asc true in execution order, false for reverse execution order + * @param cb function to call on each command + * @param cb_cls closure for cb */ -int -TALER_TESTING_setup_with_exchange_cfg ( - void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg); +void +TALER_TESTING_iterate (struct TALER_TESTING_Interpreter *is, + bool asc, + TALER_TESTING_CommandIterator cb, + void *cb_cls); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the exchange using the given - * configuration file. + * Look for substring in a programs' name. * - * @param main_cb main method. - * @param main_cb_cls main method closure. - * @param config_file configuration file name. Is is used - * by both this function and the exchange itself. In the - * first case it gives out the exchange port number and - * the exchange base URL so as to check whether the port - * is available and the exchange responds when requested - * at its base URL. - * @return #GNUNET_OK if no errors occurred. + * @param prog program's name to look into + * @param marker chunk to find in @a prog + * @return true if @a marker is in @a prog */ -int -TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_file); +bool +TALER_TESTING_has_in_name (const char *prog, + const char *marker); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the auditor and exchange using - * the given configuration file. + * Wait for an HTTPD service to have started. Waits for at + * most 10s, after that returns 77 to indicate an error. * - * @param cls must be a `struct TALER_TESTING_SetupContext *` - * @param cfg configuration to use. - * @return #GNUNET_OK if no errors occurred. + * @param base_url what URL should we expect the exchange + * to be running at + * @return 0 on success */ int -TALER_TESTING_setup_with_auditor_and_exchange_cfg ( - void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg); +TALER_TESTING_wait_httpd_ready (const char *base_url); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the auditor and exchange using - * the given configuration file. + * Parse reference to a coin. * - * @param main_cb main method. - * @param main_cb_cls main method closure. - * @param config_file configuration file name. Is is used - * by both this function and the exchange itself. In the - * first case it gives out the exchange port number and - * the exchange base URL so as to check whether the port - * is available and the exchange responds when requested - * at its base URL. - * @return #GNUNET_OK if no errors occurred. + * @param coin_reference of format $LABEL['#' $INDEX]? + * @param[out] cref where we return a copy of $LABEL + * @param[out] idx where we set $INDEX + * @return #GNUNET_SYSERR if $INDEX is present but not numeric */ -int -TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_file); +enum GNUNET_GenericReturnValue +TALER_TESTING_parse_coin_reference ( + const char *coin_reference, + char **cref, + unsigned int *idx); + + +/* ************** Specific interpreter commands ************ */ /** - * Start the (Python) bank process. Assume the port - * is available and the database is clean. Use the "prepare - * bank" function to do such tasks. + * Create command array terminator. * - * @param config_filename configuration filename. - * @param bank_url base URL of the bank, used by `wget' to check - * that the bank was started right. - * @return the process, or NULL if the process could not - * be started. + * @return a end-command. */ -struct GNUNET_OS_Process * -TALER_TESTING_run_bank (const char *config_filename, - const char *bank_url); +struct TALER_TESTING_Command +TALER_TESTING_cmd_end (void); + /** - * Start the (nexus) bank process. Assume the port - * is available and the database is clean. Use the "prepare - * bank" function to do such tasks. This function is also - * responsible to create the exchange EBICS subscriber at - * the nexus. + * Set variable to command as side-effect of + * running a command. * - * @param bc bank configuration of the bank - * @return the process, or NULL if the process could not - * be started. + * @param name name of the variable to set + * @param cmd command to set to variable when run + * @return modified command */ -struct TALER_TESTING_LibeufinServices -TALER_TESTING_run_libeufin (const struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_var (const char *name, + struct TALER_TESTING_Command cmd); /** - * Runs the Fakebank by guessing / extracting the portnumber - * from the base URL. + * Launch GNU Taler setup. * - * @param bank_url bank's base URL. - * @param currency currency the bank uses - * @return the fakebank process handle, or NULL if any - * error occurs. + * @param label command label. + * @param config_file configuration file to use + * @param ... NULL-terminated (const char *) arguments to pass to taler-benchmark-setup.sh + * @return the command. */ -struct TALER_FAKEBANK_Handle * -TALER_TESTING_run_fakebank (const char *bank_url, - const char *currency); +struct TALER_TESTING_Command +TALER_TESTING_cmd_system_start ( + const char *label, + const char *config_file, + ...); /** - * Prepare the bank execution. Check if the port is available - * and reset database. + * Connects to the exchange. * - * @param config_filename configuration file name. - * @param reset_db should we reset the bank's database - * @param config_section which configuration section should be used - * @param[out] bc set to the bank's configuration data - * @return #GNUNET_OK on success + * @param label command label + * @param cfg configuration to use + * @param last_keys_ref reference to command with prior /keys response, NULL for none + * @param wait_for_keys block until we got /keys + * @param load_private_key obtain private key from file indicated in @a cfg + * @return the command. */ -int -TALER_TESTING_prepare_bank (const char *config_filename, - int reset_db, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_exchange ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *last_keys_ref, + bool wait_for_keys, + bool load_private_key); + /** - * Prepare the Nexus execution. Check if the port is available - * and delete old database. + * Connects to the auditor. * - * @param config_filename configuration file name. - * @param reset_db should we reset the bank's database - * @param config_section section of the configuration with the exchange's account - * @param[out] bc set to the bank's configuration data - * @return the base url, or NULL upon errors. Must be freed - * by the caller. + * @param label command label + * @param cfg configuration to use + * @param load_auditor_keys obtain auditor keys from file indicated in @a cfg + * @return the command. */ -int -TALER_TESTING_prepare_nexus (const char *config_filename, - int reset_db, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_auditor ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + bool load_auditor_keys); + /** - * Look for substring in a programs' name. + * Runs the Fakebank in-process by guessing / extracting the portnumber + * from the base URL. * - * @param prog program's name to look into - * @param marker chunk to find in @a prog + * @param label command label + * @param cfg configuration to use + * @param exchange_account_section configuration section + * to use to determine bank account of the exchange + * @return the command. */ -int -TALER_TESTING_has_in_name (const char *prog, - const char *marker); - - -/* ************** Specific interpreter commands ************ */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_run_fakebank ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *exchange_account_section); /** @@ -998,10 +746,11 @@ TALER_TESTING_cmd_bank_debits (const char *label, /** * Create transfer command. * - * @param label command label. - * @param amount amount to transfer. + * @param label command label + * @param amount amount to transfer * @param auth authentication data to use - * @param payto_credit_account which account receives money. + * @param payto_debit_account which account to withdraw money from + * @param payto_credit_account which account receives money * @param wtid wire transfer identifier to use * @param exchange_base_url exchange URL to use * @return the command. @@ -1055,24 +804,20 @@ TALER_TESTING_cmd_exec_auditor_dbinit (const char *label, * Create a "deposit-confirmation" command. * * @param label command label. - * @param auditor auditor connection. * @param deposit_reference reference to any operation that can * provide a coin. - * @param coin_index if @a deposit_reference offers an array of - * coins, this parameter selects which one in that array. - * This value is currently ignored, as only one-coin - * deposits are implemented. + * @param num_coins number of coins expected in the batch deposit * @param amount_without_fee deposited amount without the fee * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_deposit_confirmation (const char *label, - struct TALER_AUDITOR_Handle *auditor, - const char *deposit_reference, - unsigned int coin_index, - const char *amount_without_fee, - unsigned int expected_response_code); +TALER_TESTING_cmd_deposit_confirmation ( + const char *label, + const char *deposit_reference, + unsigned int num_coins, + const char *amount_without_fee, + unsigned int expected_response_code); /** @@ -1084,48 +829,7 @@ TALER_TESTING_cmd_deposit_confirmation (const char *label, */ struct TALER_TESTING_Command TALER_TESTING_cmd_deposit_confirmation_with_retry ( - struct TALER_TESTING_Command - cmd); - - -/** - * Create a "list exchanges" command. - * - * @param label command label. - * @param auditor auditor connection. - * @param expected_response_code expected HTTP response code. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_exchanges (const char *label, - struct TALER_AUDITOR_Handle *auditor, - unsigned int expected_response_code); - - -/** - * Create a "list exchanges" command and check whether - * a particular exchange belongs to the returned bundle. - * - * @param label command label. - * @param expected_response_code expected HTTP response code. - * @param exchange_url URL of the exchange supposed to - * be included in the response. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_exchanges_with_url (const char *label, - unsigned int expected_response_code, - const char *exchange_url); - -/** - * Modify an exchanges command to enable retries when we get - * transient errors from the auditor. - * - * @param cmd a deposit confirmation command - * @return the command with retries enabled - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_exchanges_with_retry (struct TALER_TESTING_Command cmd); + struct TALER_TESTING_Command cmd); /** @@ -1195,6 +899,56 @@ TALER_TESTING_cmd_exec_wirewatch (const char *label, /** + * Make a "wirewatch" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @param account_section section to run wirewatch against + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_wirewatch2 (const char *label, + const char *config_filename, + const char *account_section); + + +/** + * Request URL via "wget". + * + * @param label command label. + * @param url URL to fetch + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_wget (const char *label, + const char *url); + + +/** + * Make a "expire" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_expire (const char *label, + const char *config_filename); + + +/** + * Make a "router" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_router (const char *label, + const char *config_filename); + + +/** * Run a "taler-exchange-aggregator" CMD. * * @param label command label. @@ -1277,6 +1031,7 @@ TALER_TESTING_cmd_exec_transfer (const char *label, * @param label command label. * @param reserve_reference command providing us with a reserve to withdraw from * @param amount how much we withdraw. + * @param age if > 0, age restriction applies * @param expected_response_code which HTTP response code * we expect from the exchange. * @return the withdraw command to be executed by the interpreter. @@ -1285,10 +1040,107 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_withdraw_amount (const char *label, const char *reserve_reference, const char *amount, + uint8_t age, unsigned int expected_response_code); /** + * Create a batch withdraw command, letting the caller specify the type of + * conflict between the coins and the desired amounts as string. + * + * Takes a variable, non-empty list of the denomination amounts via VARARGS, + * similar to #TALER_TESTING_cmd_withdraw_amount(), just using a batch + * withdraw. + * + * @param label command label. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param conflict if true, enforce a conflict (same priv key, different denom and age commiment) + * @param age if > 0, age restriction applies (same for all coins) + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @param amount how much we withdraw for the first coin + * @param ... NULL-terminated list of additional amounts to withdraw (one per coin) + * @return the withdraw command to be executed by the interpreter. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_batch_withdraw_with_conflict ( + const char *label, + const char *reserve_reference, + bool conflict, + uint8_t age, + unsigned int expected_response_code, + const char *amount, + ...); + +/** + * Create a batch withdraw command, letting the caller specify + * the desired amounts as string. Takes a variable, non-empty + * list of the denomination amounts via VARARGS, similar to + * #TALER_TESTING_cmd_withdraw_amount(), just using a batch withdraw. + * The coins are generated without a conflict (different private keys). + * + * @param label command label. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param age if > 0, age restriction applies (same for all coins) + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @param amount how much we withdraw for the first coin + * @param ... NULL-terminated list of additional amounts to withdraw (one per coin) + * @return the withdraw command to be executed by the interpreter. + */ +#define TALER_TESTING_cmd_batch_withdraw(label, \ + reserve_reference, \ + age, \ + expected_response_code, \ + amount, \ + ...) \ + TALER_TESTING_cmd_batch_withdraw_with_conflict ( \ + (label), \ + (reserve_reference), \ + false, \ + (age), \ + (expected_response_code), \ + (amount), \ + __VA_ARGS__) + +/** + * Create an age-withdraw command, letting the caller specify + * the maximum agend and desired amounts as string. Takes a variable, + * non-empty list of the denomination amounts via VARARGS, similar to + * #TALER_TESTING_cmd_withdraw_amount(), just using a batch withdraw. + * + * @param label command label. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param max_age maximum allowed age, same for each coin + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @param amount how much we withdraw for the first coin + * @param ... NULL-terminated list of additional amounts to withdraw (one per coin) + * @return the withdraw command to be executed by the interpreter. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_age_withdraw (const char *label, + const char *reserve_reference, + uint8_t max_age, + unsigned int expected_response_code, + const char *amount, + ...); + +/** + * Create a "age-withdraw reveal" command. + * + * @param label command label. + * @param age_withdraw_reference reference to a "age-withdraw" command. + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_age_withdraw_reveal ( + const char *label, + const char *age_withdraw_reference, + unsigned int expected_response_code); + +/** * Create a withdraw command, letting the caller specify * the desired amount as string and also re-using an existing * coin private key in the process (violating the specification, @@ -1297,8 +1149,9 @@ TALER_TESTING_cmd_withdraw_amount (const char *label, * @param label command label. * @param reserve_reference command providing us with a reserve to withdraw from * @param amount how much we withdraw. + * @param age if > 0, age restriction applies. * @param coin_ref reference to (withdraw/reveal) command of a coin - * from which we should re-use the private key + * from which we should reuse the private key * @param expected_response_code which HTTP response code * we expect from the exchange. * @return the withdraw command to be executed by the interpreter. @@ -1308,6 +1161,7 @@ TALER_TESTING_cmd_withdraw_amount_reuse_key ( const char *label, const char *reserve_reference, const char *amount, + uint8_t age, const char *coin_ref, unsigned int expected_response_code); @@ -1344,47 +1198,155 @@ TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd); /** - * Create a "wire" command. + * Create a GET "reserves" command. * * @param label the command label. - * @param expected_method which wire-transfer method is expected - * to be offered by the exchange. - * @param expected_fee the fee the exchange should charge. - * @param expected_response_code the HTTP response the exchange - * should return. + * @param reserve_reference reference to the reserve to check. + * @param expected_balance expected balance for the reserve. + * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_wire (const char *label, - const char *expected_method, - const char *expected_fee, - unsigned int expected_response_code); +TALER_TESTING_cmd_status (const char *label, + const char *reserve_reference, + const char *expected_balance, + unsigned int expected_response_code); /** - * Create a GET "reserves" command. + * Create a GET "reserves" command with a @a timeout. * * @param label the command label. * @param reserve_reference reference to the reserve to check. * @param expected_balance expected balance for the reserve. + * @param timeout how long to long-poll for the reserve to exist. * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_status (const char *label, - const char *reserve_reference, - const char *expected_balance, - unsigned int expected_response_code); +TALER_TESTING_cmd_reserve_poll (const char *label, + const char *reserve_reference, + const char *expected_balance, + struct GNUNET_TIME_Relative timeout, + unsigned int expected_response_code); + + +/** + * Wait for #TALER_TESTING_cmd_reserve_poll() to finish. + * Fail if it did not conclude by the timeout. + * + * @param label our label + * @param timeout how long to give the long poll to finish + * @param poll_reference reference to a #TALER_TESTING_cmd_reserve_poll() command + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_poll_finish (const char *label, + struct GNUNET_TIME_Relative timeout, + const char *poll_reference); + + +/** + * Create a GET "/reserves/$RID/history" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to check. + * @param expected_balance expected balance for the reserve. + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_history (const char *label, + const char *reserve_reference, + const char *expected_balance, + unsigned int expected_response_code); + + +/** + * Create a GET "/coins/$COIN_PUB/history" command. + * + * @param label the command label. + * @param coin_reference reference to the coin to check. + * @param expected_balance expected balance for the coin. + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_coin_history (const char *label, + const char *coin_reference, + const char *expected_balance, + unsigned int expected_response_code); + + +/** + * Create a POST "/reserves/$RID/open" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to open. + * @param reserve_pay amount to pay from the reserve balance + * @param expiration_time how long into the future should the reserve remain open + * @param min_purses minimum number of purses to allow + * @param expected_response_code expected HTTP response code. + * @param ... NULL terminated list of pairs of coin references and amounts + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_open (const char *label, + const char *reserve_reference, + const char *reserve_pay, + struct GNUNET_TIME_Relative expiration_time, + uint32_t min_purses, + unsigned int expected_response_code, + ...); + /** - * Index of the deposit value trait of a deposit command. + * Create a GET "/reserves/$RID/attest" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to get attestable attributes of. + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list of attributes expected + * @return the command. */ -#define TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_VALUE 0 +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_get_attestable (const char *label, + const char *reserve_reference, + unsigned int expected_response_code, + ...); + /** - * Index of the deposit fee trait of a deposit command. + * Create a POST "/reserves/$RID/attest" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to get attests for + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list of attributes that should be attested + * @return the command. */ -#define TALER_TESTING_CMD_DEPOSIT_TRAIT_IDX_DEPOSIT_FEE 1 +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_attest (const char *label, + const char *reserve_reference, + unsigned int expected_response_code, + ...); + + +/** + * Create a POST "/reserves/$RID/close" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to close. + * @param target_account where to wire funds remaining, can be NULL + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_close (const char *label, + const char *reserve_reference, + const char *target_account, + unsigned int expected_response_code); + /** * Create a "deposit" command. @@ -1477,6 +1439,31 @@ TALER_TESTING_cmd_deposit_replay (const char *label, /** + * Create a "batch deposit" command. + * + * @param label command label. + * @param target_account_payto target account for the "deposit" + * request. + * @param contract_terms contract terms to be signed over by the + * coin. + * @param refund_deadline refund deadline, zero means 'no refunds'. + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list with an even number of + * strings that alternate referring to coins + * (possibly with index using label#index notation) + * and the amount of that coin to deposit + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_batch_deposit (const char *label, + const char *target_account_payto, + const char *contract_terms, + struct GNUNET_TIME_Relative refund_deadline, + unsigned int expected_response_code, + ...); + + +/** * Create a "refresh melt" command. * * @param label command label. @@ -1709,14 +1696,13 @@ TALER_TESTING_cmd_check_bank_empty (const char *label); * provide a coin to be refunded. * @param refund_transaction_id transaction id to use * in the request. - * * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_refund_with_id (const char *label, unsigned int expected_response_code, const char *refund_amount, - const char *deposit_reference, + const char *coin_reference, uint64_t refund_transaction_id); @@ -1728,14 +1714,13 @@ TALER_TESTING_cmd_refund_with_id (const char *label, * @param refund_amount the amount to ask a refund for. * @param coin_reference reference to a command that can * provide a coin to be refunded. - * * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_refund (const char *label, unsigned int expected_response_code, const char *refund_amount, - const char *deposit_reference); + const char *coin_reference); /** @@ -1747,7 +1732,6 @@ TALER_TESTING_cmd_refund (const char *label, * offers a coin and reserve private key. May specify * the index of the coin using "$LABEL#$INDEX" syntax. * Here, $INDEX must be a non-negative number. - * @param melt_reference NULL if coin was not refreshed, otherwise label of the melt operation * @param amount how much do we expect to recoup, NULL for nothing * @return the command. */ @@ -1755,11 +1739,31 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_recoup (const char *label, unsigned int expected_response_code, const char *coin_reference, - const char *melt_reference, const char *amount); /** + * Make a "recoup-refresh" command. + * + * @param label the command label + * @param expected_response_code expected HTTP status code + * @param coin_reference reference to any command which + * offers a coin and reserve private key. May specify + * the index of the coin using "$LABEL#$INDEX" syntax. + * Here, $INDEX must be a non-negative number. + * @param melt_reference label of the melt operation + * @param amount how much do we expect to recoup, NULL for nothing + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_recoup_refresh (const char *label, + unsigned int expected_response_code, + const char *coin_reference, + const char *melt_reference, + const char *amount); + + +/** * Make a "revoke" command. * * @param label the command label. @@ -1815,60 +1819,6 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_wait_service (const char *label, const char *url); - -/** - * Make a "check keys" command. - * - * @param label command label - * @param generation how many /keys responses are expected to - * have been returned when this CMD will be run. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys (const char *label, - unsigned int generation); - - -/** - * Make a "check keys" command that forcedly does NOT cherry pick; - * just redownload the whole /keys. - * - * @param label command label - * @param generation when this command is run, exactly @a - * generation /keys downloads took place. If the number - * of downloads is less than @a generation, the logic will - * first make sure that @a generation downloads are done, - * and _then_ execute the rest of the command. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys_pull_all_keys (const char *label, - unsigned int generation); - - -/** - * Make a "check keys" command. It lets the user set a last denom issue date to be - * used in the request for /keys. - * - * @param label command label - * @param generation when this command is run, exactly @a - * generation /keys downloads took place. If the number - * of downloads is less than @a generation, the logic will - * first make sure that @a generation downloads are done, - * and _then_ execute the rest of the command. - * @param last_denom_date_ref previous /keys command to use to - * obtain the "last_denom_date" value from; "zero" can be used - * as a special value to force an absolute time of zero to be - * given to as an argument - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys_with_last_denom ( - const char *label, - unsigned int generation, - const char *last_denom_date_ref); - - /** * Create a "batch" command. Such command takes a * end_CMD-terminated array of CMDs and executed them. @@ -1894,13 +1844,18 @@ TALER_TESTING_cmd_batch (const char *label, bool TALER_TESTING_cmd_is_batch (const struct TALER_TESTING_Command *cmd); + /** * Advance internal pointer to next command. * * @param is interpreter state. + * @param[in,out] cls closure of the batch + * @return true to advance IP in parent */ -void -TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is); +bool +TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is, + void *cls); + /** * Obtain what command the batch is at. @@ -1923,34 +1878,10 @@ TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd, /** - * Make a serialize-keys CMD. - * - * @param label CMD label - * @return the CMD. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_serialize_keys (const char *label); - - -/** - * Make a connect-with-state CMD. This command - * will use a serialized key state to reconnect - * to the exchange. - * - * @param label command label - * @param state_reference label of a CMD offering - * a serialized key state. - * @return the CMD. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_connect_with_state (const char *label, - const char *state_reference); - -/** * Make the "insert-deposit" CMD. * * @param label command label. - * @param dbc collects plugin and session handles + * @param db_cfg configuration to talk to the DB * @param merchant_name Human-readable name of the merchant. * @param merchant_account merchant's account name (NOT a payto:// URI) * @param exchange_timestamp when did the exchange receive the deposit @@ -1963,10 +1894,10 @@ TALER_TESTING_cmd_connect_with_state (const char *label, struct TALER_TESTING_Command TALER_TESTING_cmd_insert_deposit ( const char *label, - const struct TALER_TESTING_DatabaseConnection *dbc, + const struct GNUNET_CONFIGURATION_Handle *db_cfg, const char *merchant_name, const char *merchant_account, - struct GNUNET_TIME_Absolute exchange_timestamp, + struct GNUNET_TIME_Timestamp exchange_timestamp, struct GNUNET_TIME_Relative wire_deadline, const char *amount_with_fee, const char *deposit_fee); @@ -1988,7 +1919,7 @@ struct TALER_TESTING_Timer struct GNUNET_TIME_Relative total_duration; /** - * Total time spend waiting for the *successful* exeuction + * Total time spend waiting for the *successful* execution * in all commands of this type. */ struct GNUNET_TIME_Relative success_latency; @@ -2065,6 +1996,7 @@ TALER_TESTING_cmd_auditor_add_denom_sig (const char *label, const char *denom_ref, bool bad_sig); + /** * Add statement about wire fees of the exchange. This is always * done for a few hours around the current time (for the test). @@ -2119,6 +2051,19 @@ TALER_TESTING_cmd_wire_del (const char *label, unsigned int expected_http_status, bool bad_sig); +/** + * Sign all extensions that the exchange has to offer, f. e. the extension for + * age restriction. This has to be run before any withdrawal of age restricted + * can be performed. + * + * @param label command label. + * @param config_filename configuration filename. + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label, + const char *config_filename); + /** * Sign all exchange denomination and online signing keys @@ -2136,7 +2081,7 @@ TALER_TESTING_cmd_exec_offline_sign_keys (const char *label, /** - * Sign a wire fee. + * Sign a wire fee structure. * * @param label command label. * @param config_filename configuration filename. @@ -2152,6 +2097,31 @@ TALER_TESTING_cmd_exec_offline_sign_fees (const char *label, /** + * Sign global fee structure. + * + * @param label command label. + * @param config_filename configuration filename. + * @param history_fee the history fee to charge (for the current year) + * @param account_fee the account fee to charge (for the current year) + * @param purse_fee the purse fee to charge (for the current year) + * @param purse_timeout when do purses time out + * @param history_expiration when does an account history expire + * @param num_purses number of (free) active purses per account + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_global_fees ( + const char *label, + const char *config_filename, + const char *history_fee, + const char *account_fee, + const char *purse_fee, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + unsigned int num_purses); + + +/** * Revoke an exchange denomination key. * * @param label command label. @@ -2190,36 +2160,18 @@ TALER_TESTING_cmd_revoke_sign_key ( /** - * Have the auditor affirm that it is auditing the given - * denomination key and upload the auditor's signature to - * the exchange. - * - * @param label command label. - * @param expected_http_status expected HTTP status from exchange - * @param denom_ref reference to a command that identifies - * a denomination key (i.e. because it was used to - * withdraw a coin). - * @param bad_sig should we use a bogus signature? - * @return the command - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_auditor_add_denom_sig (const char *label, - unsigned int expected_http_status, - const char *denom_ref, - bool bad_sig); - - -/** * Create a request for a wallet's KYC UUID. * * @param label command label. * @param reserve_reference command with reserve private key to use (or NULL to create a fresh reserve key). + * @param threshold_balance balance amount to pass to the exchange * @param expected_response_code expected HTTP status * @return the command */ struct TALER_TESTING_Command TALER_TESTING_cmd_wallet_kyc_get (const char *label, const char *reserve_reference, + const char *threshold_balance, unsigned int expected_response_code); @@ -2238,22 +2190,38 @@ TALER_TESTING_cmd_check_kyc_get (const char *label, /** - * Create a KYC proof request. + * Create a KYC proof request. Only useful in conjunction with the OAuth2.0 + * logic, as it generates an OAuth2.0-specific request. * * @param label command label. * @param payment_target_reference command with a payment target to query + * @param logic_section name of the KYC provider section + * in the exchange configuration for this proof * @param code OAuth 2.0 code to use - * @param state OAuth 2.0 state to use * @param expected_response_code expected HTTP status * @return the command */ struct TALER_TESTING_Command -TALER_TESTING_cmd_proof_kyc (const char *label, - const char *payment_target_reference, - const char *code, - const char *state, - unsigned int expected_response_code); +TALER_TESTING_cmd_proof_kyc_oauth2 ( + const char *label, + const char *payment_target_reference, + const char *logic_section, + const char *code, + unsigned int expected_response_code); + +/** + * Starts a fake OAuth 2.0 service on @a port for testing + * KYC processes which also provides a @a birthdate in a response + * + * @param label command label + * @param birthdate fixed birthdate, such as "2022-03-04", "2022-03-00", "2022-00-00" + * @param port the TCP port to listen on + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_oauth_with_birthdate (const char *label, + const char *birthdate, + uint16_t port); /** * Starts a fake OAuth 2.0 service on @a port for testing @@ -2262,9 +2230,267 @@ TALER_TESTING_cmd_proof_kyc (const char *label, * @param label command label * @param port the TCP port to listen on */ +#define TALER_TESTING_cmd_oauth(label, port) \ + TALER_TESTING_cmd_oauth_with_birthdate ((label), NULL, (port)) + + +/* ****************** P2P payment commands ****************** */ + + +/** + * Creates a purse with deposits. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param contract_terms contract, JSON string + * @param upload_contract should we upload the contract + * @param purse_expiration how long until the purse expires + * @param ... NULL-terminated list of references to coins to be deposited + * @return the command + */ struct TALER_TESTING_Command -TALER_TESTING_cmd_oauth (const char *label, - uint16_t port); +TALER_TESTING_cmd_purse_create_with_deposit ( + const char *label, + unsigned int expected_http_status, + const char *contract_terms, + bool upload_contract, + struct GNUNET_TIME_Relative purse_expiration, + ...); + + +/** + * Deletes a purse. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param purse_cmd command that created the purse + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_delete ( + const char *label, + unsigned int expected_http_status, + const char *purse_cmd); + + +/** + * Retrieve contract (also checks that the contract matches + * the upload command). + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param for_merge true if for merge, false if for deposit + * @param contract_ref reference to a command providing us with the contract private key + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_contract_get ( + const char *label, + unsigned int expected_http_status, + bool for_merge, + const char *contract_ref); + + +/** + * Retrieve purse state by merge private key. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param merge_ref reference to a command providing us with the merge private key + * @param reserve_ref reference to a command providing us with a reserve private key; if NULL, we create a fresh reserve + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_merge ( + const char *label, + unsigned int expected_http_status, + const char *merge_ref, + const char *reserve_ref); + + +/** + * Retrieve purse state. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param purse_ref reference to a command providing us with the purse private key + * @param expected_balance how much should be in the purse + * @param wait_for_merge true to wait for a merge event, otherwise wait for a deposit event + * @param timeout how long to wait + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_poll ( + const char *label, + unsigned int expected_http_status, + const char *purse_ref, + const char *expected_balance, + bool wait_for_merge, + struct GNUNET_TIME_Relative timeout); + + +/** + * Wait for the poll command to complete. + * + * @param label command label + * @param timeout how long to wait at most + * @param poll_reference which poll command to wait for + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_poll_finish (const char *label, + struct GNUNET_TIME_Relative timeout, + const char *poll_reference); + + +/** + * Creates a purse with reserve. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param contract_terms contract, JSON string + * @param upload_contract should we upload the contract + * @param pay_purse_fee should we pay a fee to create the purse + * @param expiration when should the purse expire + * @param reserve_ref reference to reserve key, or NULL to create a new reserve + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_create_with_reserve ( + const char *label, + unsigned int expected_http_status, + const char *contract_terms, + bool upload_contract, + bool pay_purse_fee, + struct GNUNET_TIME_Relative expiration, + const char *reserve_ref); + + +/** + * Deposit coins into a purse. + * + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param min_age age restriction of the purse + * @param purse_ref reference to the purse + * @param ... NULL-terminated list of references to coins to be deposited + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_deposit_coins ( + const char *label, + unsigned int expected_http_status, + uint8_t min_age, + const char *purse_ref, + ...); + + +/** + * Setup AML officer. + * + * @param label command label + * @param ref_cmd command that previously created the + * officer, NULL to create one this time + * @param name full legal name of the officer to use + * @param is_active true to set the officer to active + * @param read_only true to restrict the officer to read-only + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_officer ( + const char *label, + const char *ref_cmd, + const char *name, + bool is_active, + bool read_only); + + +/** + * Make AML decision. + * + * @param label command label + * @param ref_officer command that previously created an + * officer + * @param ref_operation command that previously created an + * h_payto which to make an AML decision about + * @param new_threshold new threshold to set + * @param justification justification given for the decision + * @param new_state new AML state for the account + * @param kyc_requirement KYC requirement to impose + * @param expected_response expected HTTP return status + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_take_aml_decision ( + const char *label, + const char *ref_officer, + const char *ref_operation, + const char *new_threshold, + const char *justification, + enum TALER_AmlDecisionState new_state, + const char *kyc_requirement, + unsigned int expected_response); + + +/** + * Fetch AML decision. + * + * @param label command label + * @param ref_officer command that previously created an + * officer + * @param ref_operation command that previously created an + * h_payto which to make an AML decision about + * @param expected_http_status expected HTTP response status + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_check_aml_decision ( + const char *label, + const char *ref_officer, + const char *ref_operation, + unsigned int expected_http_status); + + +/** + * Fetch AML decisions. + * + * @param label command label + * @param ref_officer command that previously created an + * officer + * @param filter AML state to filter by + * @param expected_http_status expected HTTP response status + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_check_aml_decisions ( + const char *label, + const char *ref_officer, + enum TALER_AmlDecisionState filter, + unsigned int expected_http_status); + + +/* ****************** convenience functions ************** */ + +/** + * Get exchange URL from interpreter. Convenience function. + * + * @param is interpreter state. + * @return the exchange URL, or NULL on error + */ +const char * +TALER_TESTING_get_exchange_url ( + struct TALER_TESTING_Interpreter *is); + + +/** + * Get exchange keys from interpreter. Convenience function. + * + * @param is interpreter state. + * @return the exchange keys, or NULL on error + */ +struct TALER_EXCHANGE_Keys * +TALER_TESTING_get_keys ( + struct TALER_TESTING_Interpreter *is); /* *** Generic trait logic for implementing traits ********* */ @@ -2423,55 +2649,85 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, */ #define TALER_TESTING_SIMPLE_TRAITS(op) \ op (bank_row, const uint64_t) \ - op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ - op (reserve_pub, const struct TALER_ReservePublicKeyP) \ + op (officer_pub, const struct TALER_AmlOfficerPublicKeyP) \ + op (officer_priv, const struct TALER_AmlOfficerPrivateKeyP) \ + op (officer_name, const char) \ + op (aml_decision, enum TALER_AmlDecisionState) \ + op (aml_justification, const char) \ + op (auditor_priv, const struct TALER_AuditorPrivateKeyP) \ + op (auditor_pub, const struct TALER_AuditorPublicKeyP) \ + op (master_priv, const struct TALER_MasterPrivateKeyP) \ + op (master_pub, const struct TALER_MasterPublicKeyP) \ + op (purse_priv, const struct TALER_PurseContractPrivateKeyP) \ + op (purse_pub, const struct TALER_PurseContractPublicKeyP) \ + op (merge_priv, const struct TALER_PurseMergePrivateKeyP) \ + op (merge_pub, const struct TALER_PurseMergePublicKeyP) \ + op (contract_priv, const struct TALER_ContractDiffiePrivateP) \ + op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ + op (reserve_sig, const struct TALER_ReserveSignatureP) \ + op (h_payto, const struct TALER_PaytoHashP) \ + op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \ + op (refresh_secret, const struct TALER_RefreshMasterSecretP) \ + op (reserve_pub, const struct TALER_ReservePublicKeyP) \ op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \ op (merchant_pub, const struct TALER_MerchantPublicKeyP) \ op (merchant_sig, const struct TALER_MerchantSignatureP) \ op (wtid, const struct TALER_WireTransferIdentifierRawP) \ + op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ op (contract_terms, const json_t) \ op (wire_details, const json_t) \ - op (exchange_keys, const json_t) \ - op (reserve_history, const struct TALER_EXCHANGE_ReserveHistory) \ - op (exchange_url, const char *) \ - op (exchange_bank_account_url, const char *) \ - op (taler_uri, const char *) \ - op (payto_uri, const char *) \ - op (kyc_url, const char *) \ - op (web_url, const char *) \ + op (exchange_url, const char) \ + op (auditor_url, const char) \ + op (exchange_bank_account_url, const char) \ + op (taler_uri, const char) \ + op (payto_uri, const char) \ + op (kyc_url, const char) \ + op (web_url, const char) \ op (row, const uint64_t) \ - op (payment_target_uuid, const uint64_t) \ + op (legi_requirement_row, const uint64_t) \ op (array_length, const unsigned int) \ - op (credit_payto_uri, const char *) \ - op (debit_payto_uri, const char *) \ - op (order_id, const char *) \ + op (credit_payto_uri, const char) \ + op (debit_payto_uri, const char) \ + op (order_id, const char) \ op (amount, const struct TALER_Amount) \ - op (amount_with_fee, const struct TALER_Amount) \ - op (deposit_amount, const struct TALER_Amount) \ - op (deposit_fee_amount, const struct TALER_Amount) \ - op (batch_cmds, struct TALER_TESTING_Command *) \ + op (amount_with_fee, const struct TALER_Amount) \ + op (batch_cmds, struct TALER_TESTING_Command) \ op (uuid, const struct GNUNET_Uuid) \ - op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \ + op (fresh_coins, const struct TALER_TESTING_FreshCoinData *) \ op (claim_token, const struct TALER_ClaimTokenP) \ op (relative_time, const struct GNUNET_TIME_Relative) \ + op (fakebank, struct TALER_FAKEBANK_Handle) \ + op (keys, struct TALER_EXCHANGE_Keys) \ op (process, struct GNUNET_OS_Process *) /** * Call #op on all indexed traits. */ -#define TALER_TESTING_INDEXED_TRAITS(op) \ - op (denom_pub, const struct TALER_EXCHANGE_DenomPublicKey) \ - op (denom_sig, const struct TALER_DenominationSignature) \ - op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \ - op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \ - op (absolute_time, const struct GNUNET_TIME_Absolute) \ - op (wire_deadline, const struct GNUNET_TIME_Absolute) \ - op (refund_deadline, const struct GNUNET_TIME_Absolute) \ - op (exchange_pub, const struct TALER_ExchangePublicKeyP) \ - op (exchange_sig, const struct TALER_ExchangeSignatureP) \ - op (blinding_key, const union TALER_DenominationBlindingKeyP) - +#define TALER_TESTING_INDEXED_TRAITS(op) \ + op (denom_pub, const struct TALER_EXCHANGE_DenomPublicKey) \ + op (denom_sig, const struct TALER_DenominationSignature) \ + op (amounts, const struct TALER_Amount) \ + op (deposit_amount, const struct TALER_Amount) \ + op (deposit_fee_amount, const struct TALER_Amount) \ + op (age_commitment, const struct TALER_AgeCommitment) \ + op (age_commitment_proof, const struct TALER_AgeCommitmentProof) \ + op (h_age_commitment, const struct TALER_AgeCommitmentHash) \ + op (reserve_history, const struct TALER_EXCHANGE_ReserveHistoryEntry) \ + op (coin_history, const struct TALER_EXCHANGE_CoinHistoryEntry) \ + op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ + op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \ + op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \ + op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \ + op (coin_sig, const struct TALER_CoinSpendSignatureP) \ + op (absolute_time, const struct GNUNET_TIME_Absolute) \ + op (timestamp, const struct GNUNET_TIME_Timestamp) \ + op (wire_deadline, const struct GNUNET_TIME_Timestamp) \ + op (refund_deadline, const struct GNUNET_TIME_Timestamp) \ + op (exchange_pub, const struct TALER_ExchangePublicKeyP) \ + op (exchange_sig, const struct TALER_ExchangeSignatureP) \ + op (blinding_key, const union GNUNET_CRYPTO_BlindingSecretP) \ + op (h_blinded_coin, const struct TALER_BlindedCoinHashP) TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) diff --git a/src/include/taler_util.h b/src/include/taler_util.h index 8d7f5f754..8feb8451c 100644 --- a/src/include/taler_util.h +++ b/src/include/taler_util.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2021 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -16,11 +16,17 @@ /** * @file include/taler_util.h * @brief Interface for common utility functions + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Sree Harsha Totakura <sreeharsha@totakura.in> + * @author Christian Grothoff */ #ifndef TALER_UTIL_H #define TALER_UTIL_H +#include <gnunet/gnunet_common.h> +#define __TALER_UTIL_LIB_H_INSIDE__ + #include <gnunet/gnunet_util_lib.h> #include <microhttpd.h> #include "taler_amount_lib.h" @@ -30,7 +36,7 @@ * Version of the Taler API, in hex. * Thus 0.8.4-1 = 0x00080401. */ -#define TALER_API_VERSION 0x00080401 +#define TALER_API_VERSION 0x00090401 /** * Stringify operator. @@ -79,6 +85,22 @@ /** + * HTTP header with an AML officer signature to approve the inquiry. + * Used only in GET Requests. + */ +#define TALER_AML_OFFICER_SIGNATURE_HEADER "Taler-AML-Officer-Signature" + +/** + * Header with signature for reserve history requests. + */ +#define TALER_RESERVE_HISTORY_SIGNATURE_HEADER "Taler-Reserve-History-Signature" + +/** + * Header with signature for coin history requests. + */ +#define TALER_COIN_HISTORY_SIGNATURE_HEADER "Taler-Coin-History-Signature" + +/** * Log an error message at log-level 'level' that indicates * a failure of the command 'cmd' with the message given * by gcry_strerror(rc). @@ -125,12 +147,13 @@ TALER_b2s (const void *buf, * @param obj address of object to convert * @return string representing the binary obj buffer */ -#define TALER_B2S(obj) TALER_b2s (obj, sizeof (*obj)) +#define TALER_B2S(obj) TALER_b2s ((obj), sizeof (*(obj))) /** * Obtain denomination amount from configuration file. * + * @param cfg configuration to extract data from * @param section section of the configuration to access * @param option option of the configuration to access * @param[out] denom set to the amount found in configuration @@ -144,6 +167,39 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg, /** + * Obtain denomination fee structure of a + * denomination from configuration file. All + * fee options must start with "fee_" and have + * names typical for the respective fees. + * + * @param cfg configuration to extract data from + * @param currency expected currency + * @param section section of the configuration to access + * @param[out] fees set to the denomination fees + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +enum GNUNET_GenericReturnValue +TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *currency, + const char *section, + struct TALER_DenomFeeSet *fees); + + +/** + * Check that all denominations in @a fees use + * @a currency + * + * @param currency desired currency + * @param fees fee set to check + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_denom_fee_check_currency ( + const char *currency, + const struct TALER_DenomFeeSet *fees); + + +/** * Load our currency from the @a cfg (in section [taler] * the option "CURRENCY"). * @@ -157,6 +213,101 @@ TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg, /** + * Details about how to render a currency. + */ +struct TALER_CurrencySpecification +{ + /** + * Currency code of the currency. + */ + char currency[TALER_CURRENCY_LEN]; + + /** + * Human-readable long name of the currency, e.g. + * "Japanese Yen". + */ + char *name; + + /** + * how many digits the user may enter at most after the @e decimal_separator + */ + unsigned int num_fractional_input_digits; + + /** + * how many digits we render in normal scale after the @e decimal_separator + */ + unsigned int num_fractional_normal_digits; + + /** + * how many digits we render in after the @e decimal_separator even if all + * remaining digits are zero. + */ + unsigned int num_fractional_trailing_zero_digits; + + /** + * Mapping of powers of 10 to alternative currency names or symbols. + * Keys are the decimal powers, values the currency symbol to use. + * Map MUST contain an entry for "0" to the default currency symbol. + */ + json_t *map_alt_unit_names; + +}; + + +/** + * Parse information about supported currencies from + * our configuration. + * + * @param cfg configuration to parse + * @param[out] num_currencies set to number of enabled currencies, length of @e cspecs + * @param[out] cspecs set to currency specification array + * @return #GNUNET_OK on success, #GNUNET_NO if zero + * currency specifications were enabled, + * #GNUNET_SYSERR if the configuration was malformed + */ +enum GNUNET_GenericReturnValue +TALER_CONFIG_parse_currencies (const struct GNUNET_CONFIGURATION_Handle *cfg, + unsigned int *num_currencies, + struct TALER_CurrencySpecification **cspecs); + + +/** + * Free @a cspecs array. + * + * @param num_currencies length of @a cspecs array + * @param[in] cspecs array to free + */ +void +TALER_CONFIG_free_currencies ( + unsigned int num_currencies, + struct TALER_CurrencySpecification cspecs[static num_currencies]); + + +/** + * Convert a currency specification to the + * respective JSON object. + * + * @param cspec currency specification + * @return JSON object encoding @a cspec for `/config`. + */ +json_t * +TALER_CONFIG_currency_specs_to_json ( + const struct TALER_CurrencySpecification *cspec); + + +/** + * Check that @a map contains a valid currency scale + * map that maps integers from [-12,24] to currency + * symbols given as strings. + * + * @param map map to check + * @return #GNUNET_OK if @a map is valid + */ +enum GNUNET_GenericReturnValue +TALER_check_currency_scale_map (const json_t *map); + + +/** * Allow user to specify an amount on the command line. * * @param shortName short name of the option @@ -188,6 +339,16 @@ TALER_OS_init (void); /** + * Re-encode string at @a inp to match RFC 8785 (section 3.2.2.2). + * + * @param[in,out] inp pointer to string to re-encode + * @return number of bytes in resulting @a inp + */ +size_t +TALER_rfc8785encode (char **inp); + + +/** * URL-encode a string according to rfc3986. * * @param s string to encode @@ -209,6 +370,17 @@ TALER_url_valid_charset (const char *url); /** + * Test if the URL is a valid "http" (or "https") + * URL (includes test for #TALER_url_valid_charset()). + * + * @param url a string to test if it could be a valid URL + * @return true if @a url is well-formed + */ +bool +TALER_is_web_url (const char *url); + + +/** * Check if @a lang matches the @a language_pattern, and if so with * which preference. * See also: https://tools.ietf.org/html/rfc7231#section-5.3.1 @@ -244,8 +416,9 @@ TALER_mhd_is_https (struct MHD_Connection *connection); * that a NULL value does not terminate the list, only a NULL key signals the * end of the list of arguments. * - * @param base_url absolute base URL to use - * @param path path of the url + * @param base_url absolute base URL to use, must either + * end with '/' *or* @a path must be the empty string + * @param path path of the url to append to the @a base_url * @param ... NULL-terminated key-value pairs (char *) for query parameters, * only the value will be url-encoded * @returns the URL, must be freed with #GNUNET_free @@ -328,16 +501,17 @@ TALER_payto_get_method (const char *payto_uri); /** - * Construct a payto://-URI from a Taler @a reserve_pub at - * a @exchange_base_url + * Normalize payto://-URI to make "strcmp()" sufficient + * to check if two payto-URIs refer to the same bank + * account. Removes optional arguments (everything after + * "?") and applies method-specific normalizations to + * the main part of the URI. * - * @param exchange_base_url the URL of the exchange - * @param reserve_pub public key of the reserve - * @return payto:// URI encoding the reserve's address + * @param input a payto://-URI + * @return normalized URI, or NULL if @a input was not well-formed */ char * -TALER_payto_from_reserve (const char *exchange_base_url, - const struct TALER_ReservePublicKeyP *reserve_pub); +TALER_payto_normalize (const char *input); /** @@ -352,6 +526,16 @@ TALER_xtalerbank_account_from_payto (const char *payto); /** + * Obtain the receiver name from a payto URL. + * + * @param payto an x-taler-bank payto URL + * @return only the receiver name from the @a payto URL, NULL if not an x-taler-bank payto URL + */ +char * +TALER_payto_get_receiver_name (const char *payto); + + +/** * Extract the subject value from the URI parameters. * * @param payto_uri the URL to parse @@ -374,6 +558,19 @@ TALER_payto_validate (const char *payto_uri); /** + * Create payto://-URI for a given exchange base URL + * and a @a reserve_pub. + * + * @param exchange_url the base URL of the exchange + * @param reserve_pub the public key of the reserve + * @return payto://-URI for the reserve (without receiver-name!) + */ +char * +TALER_reserve_make_payto (const char *exchange_url, + const struct TALER_ReservePublicKeyP *reserve_pub); + + +/** * Check that an IBAN number is well-formed. * * Validates given IBAN according to the European Banking Standards. See: @@ -435,4 +632,198 @@ const char * TALER_yna_to_string (enum TALER_EXCHANGE_YesNoAll yna); +#ifdef __APPLE__ +/** + * Returns the first occurrence of `c` in `s`, or returns the null-byte + * terminating the string if it does not occur. + * + * @param s the string to search in + * @param c the character to search for + * @return char* the first occurrence of `c` in `s` + */ +char *strchrnul (const char *s, int c); + +#endif + +/** + * @brief Parses a date information into days after 1970-01-01 (or 0) + * + * The input MUST be of the form + * + * 1) YYYY-MM-DD, representing a valid date + * 2) YYYY-MM-00, representing a valid month in a particular year + * 3) YYYY-00-00, representing a valid year. + * + * In the cases 2) and 3) the out parameter is set to the beginning of the + * time, f.e. 1950-00-00 == 1950-01-01 and 1888-03-00 == 1888-03-01 + * + * The output will set to the number of days after 1970-01-01 or 0, if the input + * represents a date belonging to the largest allowed age group. + * + * @param in Input string representation of the date + * @param mask Age mask + * @param[out] out Where to write the result + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_parse_coarse_date ( + const char *in, + const struct TALER_AgeMask *mask, + uint32_t *out); + + +/** + * @brief Parses a string as a list of age groups. + * + * The string must consist of a colon-separated list of increasing integers + * between 0 and 31. Each entry represents the beginning of a new age group. + * F.e. the string + * + * "8:10:12:14:16:18:21" + * + * represents the following list of eight age groups: + * + * | Group | Ages | + * | -----:|:------------- | + * | 0 | 0, 1, ..., 7 | + * | 1 | 8, 9 | + * | 2 | 10, 11 | + * | 3 | 12, 13 | + * | 4 | 14, 15 | + * | 5 | 16, 17 | + * | 6 | 18, 19, 20 | + * | 7 | 21, ... | + * + * which is then encoded as a bit mask with the corresponding bits set: + * + * 31 24 16 8 0 + * | | | | | + * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + * + * @param groups String representation of age groups + * @param[out] mask Mask representation for age restriction. + * @return Error, if age groups were invalid, OK otherwise. + */ +enum GNUNET_GenericReturnValue +TALER_parse_age_group_string ( + const char *groups, + struct TALER_AgeMask *mask); + + +/** + * @brief Encodes the age mask into a string, like "8:10:12:14:16:18:21" + * + * NOTE: This function uses a static buffer. It is not safe to call this + * function concurrently. + * + * @param mask Age mask + * @return String representation of the age mask. + * Can be used as value in the TALER config. + */ +const char * +TALER_age_mask_to_string ( + const struct TALER_AgeMask *mask); + + +/** + * @brief returns the age group of a given age for a given age mask + * + * @param mask Age mask + * @param age The given age + * @return age group + */ +uint8_t +TALER_get_age_group ( + const struct TALER_AgeMask *mask, + uint8_t age); + + +/** + * @brief Parses a JSON object { "age_groups": "a:b:...y:z" }. + * + * @param root is the json object + * @param[out] mask on success, will contain the age mask + * @return #GNUNET_OK on success and #GNUNET_SYSERR on failure. + */ +enum GNUNET_GenericReturnValue +TALER_JSON_parse_age_groups (const json_t *root, + struct TALER_AgeMask *mask); + + +/** + * @brief Return the lowest age in the corresponding group for a given age + * according the given age mask. + * + * @param mask age mask + * @param age age to check + * @return lowest age in corresponding age group + */ +uint8_t +TALER_get_lowest_age ( + const struct TALER_AgeMask *mask, + uint8_t age); + + +/** + * @brief Get the lowest age for the largest age group + * + * @param mask the age mask + * @return lowest age for the largest age group + */ +#define TALER_adult_age(mask) \ + sizeof((mask)->bits) * 8 - __builtin_clz ((mask)->bits) - 1 + +/** + * Handle to an external process that will assist + * with some JSON-to-JSON conversion. + */ +struct TALER_JSON_ExternalConversion; + +/** + * Type of a callback that receives a JSON @a result. + * + * @param cls closure + * @param status_type how did the process die + * @param code termination status code from the process + * @param result some JSON result, NULL if we failed to get an JSON output + */ +typedef void +(*TALER_JSON_JsonCallback) (void *cls, + enum GNUNET_OS_ProcessStatusType status_type, + unsigned long code, + const json_t *result); + + +/** + * Launch some external helper @a binary to convert some @a input + * and eventually call @a cb with the result. + * + * @param input JSON to serialize and pass to the helper process + * @param cb function to call on the result + * @param cb_cls closure for @a cb + * @param binary name of the binary to execute + * @param ... NULL-terminated list of arguments for the @a binary, + * usually starting with again the name of the binary + * @return handle to cancel the operation (and kill the helper) + */ +struct TALER_JSON_ExternalConversion * +TALER_JSON_external_conversion_start (const json_t *input, + TALER_JSON_JsonCallback cb, + void *cb_cls, + const char *binary, + ...); + +/** + * Abort external conversion, killing the process and preventing + * the callback from being called. Must not be called after the + * callback was invoked. + * + * @param[in] ec external conversion handle to cancel + */ +void +TALER_JSON_external_conversion_stop ( + struct TALER_JSON_ExternalConversion *ec); + +#undef __TALER_UTIL_LIB_H_INSIDE__ + #endif |