diff options
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/Makefile.am | 1 | ||||
-rw-r--r-- | src/include/platform.h | 219 | ||||
-rw-r--r-- | src/include/taler_amount_lib.h | 16 | ||||
-rw-r--r-- | src/include/taler_attributes.h | 129 | ||||
-rw-r--r-- | src/include/taler_auditor_service.h | 206 | ||||
-rw-r--r-- | src/include/taler_auditordb_plugin.h | 1172 | ||||
-rw-r--r-- | src/include/taler_bank_service.h | 143 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 1108 | ||||
-rw-r--r-- | src/include/taler_curl_lib.h | 13 | ||||
-rw-r--r-- | src/include/taler_exchange_service.h | 3460 | ||||
-rw-r--r-- | src/include/taler_exchangedb_lib.h | 5 | ||||
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 1475 | ||||
-rw-r--r-- | src/include/taler_extensions.h | 32 | ||||
-rw-r--r-- | src/include/taler_extensions_policy.h | 21 | ||||
-rw-r--r-- | src/include/taler_json_lib.h | 248 | ||||
-rw-r--r-- | src/include/taler_kyclogic_lib.h | 87 | ||||
-rw-r--r-- | src/include/taler_kyclogic_plugin.h | 16 | ||||
-rw-r--r-- | src/include/taler_mhd_lib.h | 358 | ||||
-rw-r--r-- | src/include/taler_pq_lib.h | 254 | ||||
-rw-r--r-- | src/include/taler_templating_lib.h | 37 | ||||
-rw-r--r-- | src/include/taler_testing_lib.h | 1386 | ||||
-rw-r--r-- | src/include/taler_util.h | 287 |
22 files changed, 7016 insertions, 3657 deletions
diff --git a/src/include/Makefile.am b/src/include/Makefile.am index b2ae8bcc4..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 \ 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 a529cfb84..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 @@ -398,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 c20b789cc..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_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,15 +310,18 @@ typedef void */ struct TALER_AUDITOR_DepositConfirmationHandle * TALER_AUDITOR_deposit_confirmation ( - struct TALER_AUDITOR_Handle *auditor, + 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 *amount_without_fee, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + 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, @@ -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 cf27668b6..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-2022 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 @@ -90,257 +76,10 @@ typedef enum GNUNET_GenericReturnValue /** - * Structure for remembering the wire auditor's progress over the - * various tables and (auditor) transactions. - */ -struct TALER_AUDITORDB_WireProgressPoint -{ - - /** - * Time until which we have confirmed that all wire transactions - * that the exchange should do, have indeed been done. - */ - struct GNUNET_TIME_Timestamp 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 - */ - uint64_t last_reserve_in_serial_id; - - /** - * serial ID of the last wire_out the wire auditor processed - */ - uint64_t last_wire_out_serial_id; - -}; - - -/** - * Structure for remembering the wire auditor's progress - * with respect to the bank transaction histories. - */ -struct TALER_AUDITORDB_BankAccountProgressPoint -{ - /** - * How far are we in the incoming wire transaction history - */ - uint64_t in_wire_off; - - /** - * How far are we in the outgoing wire transaction history - */ - uint64_t out_wire_off; - -}; - - -/** - * 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 - */ - uint64_t last_reserve_in_serial_id; - - /** - * serial ID of the last reserve_out (withdraw) the auditor processed - */ - uint64_t last_reserve_out_serial_id; - - /** - * serial ID of the last recoup entry the auditor processed when - * considering reserves. - */ - uint64_t last_reserve_recoup_serial_id; - - /** - * serial ID of the last open_requests entry the auditor processed. - */ - uint64_t last_reserve_open_serial_id; - - /** - * serial ID of the last reserve_close entry the auditor processed. - */ - uint64_t last_reserve_close_serial_id; - - /** - * Serial ID of the last purse_decisions entry the auditor processed. - */ - uint64_t last_purse_decisions_serial_id; - - /** - * serial ID of the last account_merges entry the auditor processed. - */ - uint64_t last_account_merges_serial_id; - - /** - * serial ID of the last history_requests entry the auditor processed. - */ - uint64_t last_history_requests_serial_id; - -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing purses. - */ -struct TALER_AUDITORDB_ProgressPointPurse -{ - /** - * serial ID of the last purse_request transfer the auditor processed - */ - uint64_t last_purse_request_serial_id; - - /** - * serial ID of the last purse_decision the auditor processed - */ - uint64_t last_purse_decision_serial_id; - - /** - * serial ID of the last purse_merge entry the auditor processed when - * considering reserves. - */ - uint64_t last_purse_merge_serial_id; - - /** - * serial ID of the last account_merge entry the auditor processed. - */ - uint64_t last_account_merge_serial_id; - - /** - * serial ID of the last purse_deposits entry the auditor processed. - */ - uint64_t last_purse_deposits_serial_id; - -}; - - -/** - * Global statistics about purses. - */ -struct TALER_AUDITORDB_PurseBalance -{ - /** - * Balance in all unmerged and unexpired purses. - */ - struct TALER_Amount balance; - - /** - * Total number of open purses. - */ - uint64_t open_purses; -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing reserves. - */ -struct TALER_AUDITORDB_ProgressPointDepositConfirmation -{ - /** - * serial ID of the last deposit_confirmation the auditor processed - */ - 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 -{ - - /** - * serial ID of the last prewire transfer the 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 coins. - */ -struct TALER_AUDITORDB_ProgressPointCoin -{ - /** - * serial ID of the last withdraw the auditor processed - */ - uint64_t last_withdraw_serial_id; - - /** - * serial ID of the last deposit the auditor processed - */ - uint64_t last_deposit_serial_id; - - /** - * serial ID of the last refresh the auditor processed - */ - uint64_t last_melt_serial_id; - - /** - * serial ID of the last refund the auditor processed - */ - uint64_t last_refund_serial_id; - - /** - * Serial ID of the last recoup operation the auditor processed. - */ - uint64_t last_recoup_serial_id; - - /** - * Serial ID of the last recoup-of-refresh operation the auditor processed. - */ - uint64_t last_recoup_refresh_serial_id; - - /** - * Serial ID of the last reserve_open_deposits operation the auditor processed. - */ - uint64_t last_open_deposits_serial_id; - - /** - * Serial ID of the last purse_deposits operation the auditor processed. - */ - uint64_t last_purse_deposits_serial_id; - - /** - * Serial ID of the last purse_refunds operation the auditor processed. - */ - uint64_t last_purse_refunds_serial_id; - -}; - - -/** * Information about a signing key of an exchange. */ struct TALER_AUDITORDB_ExchangeSigningKey { - /** - * Public master key of the exchange that certified @e master_sig. - */ - struct TALER_MasterPublicKeyP master_public_key; /** * When does @e exchange_pub start to be used? @@ -414,14 +153,23 @@ struct TALER_AUDITORDB_DepositConfirmation * Amount to be deposited, excluding fee. Calculated from the * amount with fee and the fee from the deposit request. */ - struct TALER_Amount amount_without_fee; + struct TALER_Amount total_without_fee; + + /** + * Length of the @e coin_pubs and @e coin_sigs arrays. + */ + unsigned int num_coins; + + /** + * Array of the coin public keys involved in the + * batch deposit operation. + */ + const struct TALER_CoinSpendPublicKeyP *coin_pubs; /** - * 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). + * Array of coin deposit signatures from the deposit operation. */ - struct TALER_CoinSpendPublicKeyP coin_pub; + const struct TALER_CoinSpendSignatureP *coin_sigs; /** * The Merchant's public key. Allows the merchant to later refund @@ -445,12 +193,6 @@ struct TALER_AUDITORDB_DepositConfirmation */ struct TALER_MasterSignatureP master_sig; - /** - * Master public key of the exchange corresponding to @e master_sig. - * Identifies the exchange this is about. - */ - struct TALER_MasterPublicKeyP master_public_key; - }; @@ -533,62 +275,6 @@ struct TALER_AUDITORDB_DenominationCirculationData /** - * Balance values for all denominations. - */ -struct TALER_AUDITORDB_GlobalCoinBalance -{ - /** - * Amount of outstanding coins in circulation. - */ - struct TALER_Amount total_escrowed; - - /** - * Amount collected in deposit fees. - */ - struct TALER_Amount deposit_fee_balance; - - /** - * Amount collected in melt fees. - */ - struct TALER_Amount melt_fee_balance; - - /** - * Amount collected in refund fees. - */ - struct TALER_Amount refund_fee_balance; - - /** - * Amount collected in purse fees from coins. - */ - struct TALER_Amount purse_fee_balance; - - /** - * Amount collected in reserve open deposit fees from coins. - */ - struct TALER_Amount open_deposit_fee_balance; - - /** - * Total amount that could still be theoretically - * lost in the future due to recoup operations. - * (Total put into circulation minus @e loss - * and @e irregular_recoup.) - */ - struct TALER_Amount risk; - - /** - * Amount lost due to recoups. - */ - struct TALER_Amount loss; - - /** - * Amount lost due to coin operations that the exchange - * should not have permitted. - */ - struct TALER_Amount irregular_loss; -}; - - -/** * Function called with deposit confirmations stored in * the auditor's database. * @@ -605,6 +291,25 @@ 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 @@ -656,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. @@ -675,10 +422,14 @@ struct TALER_AUDITORDB_Plugin * 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); /** @@ -723,106 +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 + * @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_coin)( + (*insert_auditor_progress)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); + const char *progress_key, + uint64_t progress_offset, + ...); /** @@ -830,324 +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 ppc 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_coin)( + (*update_auditor_progress)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); + 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] ppc 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_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); + (*get_auditor_progress)(void *cls, + const char *progress_key, + uint64_t *progress_offset, + ...); /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. + * 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 ppr 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 - (*update_auditor_progress_reserve)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointReserve *ppr); + (*insert_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_value, + ...); /** - * 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 ppp where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_purse)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointPurse *ppp); - - - /** - * 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 ppp where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_purse)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointPurse *ppp); - - - /** - * 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] ppp set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_auditor_progress_purse)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointPurse *ppp); - - - /** - * 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 - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_deposit_confirmation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); - - - /** - * 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 ppdc where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_deposit_confirmation)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); - - - /** - * 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 - * @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); - - - /** - * 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 ppa where is the auditor in processing - * @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); - - - /** - * 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. - * - * @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 - * @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); - - - /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * 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 account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @param bapp progress in wire transaction histories + * @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 - (*insert_wire_auditor_account_progress)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - const struct TALER_AUDITORDB_BankAccountProgressPoint *bapp); + (*update_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_amount, + ...); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * 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 bapp progress in wire transaction histories + * @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 - (*update_wire_auditor_account_progress)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - const struct TALER_AUDITORDB_BankAccountProgressPoint *bapp); + (*get_balance)(void *cls, + const char *balance_key, + struct TALER_Amount *balance_value, + ...); /** - * Get information about the progress of the wire auditor. + * 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[out] pp where is the auditor in processing - * @param[out] bapp how far are we in the wire transaction histories - * @return transaction status code + * @param sk signing key information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*get_wire_auditor_account_progress)( + (*insert_exchange_signkey)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - struct TALER_AUDITORDB_BankAccountProgressPoint *bapp); + const struct TALER_AUDITORDB_ExchangeSigningKey *sk); /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * 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 pp where is the auditor in processing - * @return transaction status code + * @param dc deposit confirmation information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*insert_wire_auditor_progress)( + (*insert_deposit_confirmation)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_WireProgressPoint *pp); + const struct TALER_AUDITORDB_DepositConfirmation *dc); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * 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 - (*update_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); /** - * Get information about the progress of the wire auditor. + * 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[out] pp set to where the auditor is in processing - * @return transaction status code + * @param row_id row to delete + * @return query result status */ enum GNUNET_DB_QueryStatus - (*get_wire_auditor_progress)( + (*delete_deposit_confirmation)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_WireProgressPoint *pp); + uint64_t row_id); /** @@ -1156,7 +640,6 @@ 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 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 @@ -1166,7 +649,6 @@ struct TALER_AUDITORDB_Plugin (*insert_reserve_info)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, struct GNUNET_TIME_Timestamp expiration_date, const char *origin_account); @@ -1178,7 +660,6 @@ 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 rfb balance amounts for the reserve * @param expiration_date expiration date of the reserve * @return transaction status code @@ -1187,7 +668,6 @@ struct TALER_AUDITORDB_Plugin (*update_reserve_info)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, struct GNUNET_TIME_Timestamp expiration_date); @@ -1197,7 +677,6 @@ 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] rfb set to balances associated with the reserve * @param[out] expiration_date expiration date of the reserve @@ -1208,7 +687,6 @@ struct TALER_AUDITORDB_Plugin (*get_reserve_info)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, uint64_t *rowid, struct TALER_AUDITORDB_ReserveFeeBalance *rfb, struct GNUNET_TIME_Timestamp *expiration_date, @@ -1220,13 +698,62 @@ 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 new row into the pending deposits table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @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_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); + + + /** + * 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 batch_deposit_serial_id which entry to delete + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*delete_pending_deposit)( + void *cls, + uint64_t batch_deposit_serial_id); + + + /** + * Return (batch) deposits for which we have not yet + * seen the required wire transfer. + * + * @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 + (*select_pending_deposits)( + void *cls, + struct GNUNET_TIME_Absolute deadline, + TALER_AUDITORDB_WireMissingCallback cb, + void *cb_cls); /** @@ -1235,7 +762,6 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub public key of the purse - * @param master_pub master public key of the exchange * @param balance balance of the purse * @param expiration_date expiration date of the purse * @return transaction status code @@ -1244,7 +770,6 @@ struct TALER_AUDITORDB_Plugin (*insert_purse_info)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_Amount *balance, struct GNUNET_TIME_Timestamp expiration_date); @@ -1255,7 +780,6 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub public key of the purse - * @param master_pub master public key of the exchange * @param balance new balance for the purse * @return transaction status code */ @@ -1263,7 +787,6 @@ struct TALER_AUDITORDB_Plugin (*update_purse_info)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_Amount *balance); @@ -1272,7 +795,6 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub public key of the purse - * @param master_pub master public key of the exchange * @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 @@ -1282,7 +804,6 @@ struct TALER_AUDITORDB_Plugin (*get_purse_info)( void *cls, const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_MasterPublicKeyP *master_pub, uint64_t *rowid, struct TALER_Amount *balance, struct GNUNET_TIME_Timestamp *expiration_date); @@ -1293,21 +814,18 @@ struct TALER_AUDITORDB_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param purse_pub public key of the reserve - * @param master_pub master public key of the exchange * @return transaction status code */ enum GNUNET_DB_QueryStatus (*delete_purse_info)( void *cls, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_MasterPublicKeyP *master_pub); + const struct TALER_PurseContractPublicKeyP *purse_pub); /** * Get information about expired purses. * * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange * @param cb function to call on expired purses * @param cb_cls closure for @a cb * @return transaction status code @@ -1315,162 +833,11 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*select_purse_expired)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, TALER_AUDITORDB_ExpiredPurseCallback cb, void *cb_cls); /** - * Delete information about a purse. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param purse_pub public key of the purse - * @param master_pub master public key of the exchange - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*del_purse_info)(void *cls, - const struct TALER_PurseContractPublicKeyP *purse_pub, - const struct TALER_MasterPublicKeyP *master_pub); - - - /** - * Insert information about all reserves. There must not be an - * existing record for the @a master_pub. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param rfb reserve balances summary to store - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_reserve_summary)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ReserveFeeBalance *rfb); - - - /** - * Update information about all reserves. 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 rfb reserve balances summary to store - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_reserve_summary)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ReserveFeeBalance *rfb); - - - /** - * Get summary information about all reserves. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param[out] rfb reserve balances summary to initialize - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_reserve_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ReserveFeeBalance *rfb); - - - /** - * Insert information about all purses. There must not be an - * existing record for the @a master_pub. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param sum purse balance summary to store - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_purse_summary)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_PurseBalance *sum); - - - /** - * Update information about all purses. 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 sum purse balances summary to store - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_purse_summary)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_PurseBalance *sum); - - - /** - * Get summary information about all purses. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master public key of the exchange - * @param[out] sum purse balances summary to initialize - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_purse_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_PurseBalance *sum); - - - /** - * Insert information about exchange's wire fee balance. There must not be an - * existing record for the same @a master_pub. - * - * @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 - * @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 information about exchange's wire fee balance. 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 - * @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); - - - /** - * Get summary information about an exchanges wire fee balance. - * - * @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 - * @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); - - - /** * Insert information about a denomination key's balances. There * must not be an existing record for the denomination key. * @@ -1501,22 +868,6 @@ struct TALER_AUDITORDB_Plugin const struct TALER_DenominationHashP *denom_pub_hash, const struct TALER_AUDITORDB_DenominationCirculationData *dcd); - - /** - * Get information about a denomination key's balances. - * - * @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] dcd denomination circulation data to initialize - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_denomination_balance)( - void *cls, - const struct TALER_DenominationHashP *denom_pub_hash, - struct TALER_AUDITORDB_DenominationCirculationData *dcd); - - /** * Delete information about a denomination key's balances. * @@ -1531,49 +882,18 @@ struct TALER_AUDITORDB_Plugin /** - * 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 dfb denomination balance data to store - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_balance_summary)( - void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_GlobalCoinBalance *dfb); - - - /** - * Update information about an exchange's denomination balances. There - * must be an existing record for the exchange. + * 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 dfb denomination balance data to store + * @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 - (*update_balance_summary)( + (*get_denomination_balance)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_GlobalCoinBalance *dfb); - - - /** - * Get information about an exchange's denomination balances. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param master_pub master key of the exchange - * @param[out] dfb where to return the denomination balances - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_balance_summary)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_GlobalCoinBalance *dfb); + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** @@ -1581,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 @@ -1593,7 +912,6 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_denom_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, const struct TALER_DenominationHashP *denom_pub_hash, struct GNUNET_TIME_Timestamp revenue_timestamp, const struct TALER_Amount *revenue_balance, @@ -1601,11 +919,9 @@ struct TALER_AUDITORDB_Plugin /** - * 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 @@ -1613,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); @@ -1622,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 @@ -1631,7 +945,6 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_reserve_revenue)( void *cls, - const struct TALER_MasterPublicKeyP *master_pub, struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Timestamp end_time, const struct TALER_Amount *reserve_profits); @@ -1641,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 @@ -1649,61 +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 - * @param drained_profits total profits drained by the exchange so far - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_predicted_result)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance, - const struct TALER_Amount *drained_profits); - - - /** - * 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 - * @param drained_profits total profits drained by the exchange so far - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_predicted_result)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance, - const struct TALER_Amount *drained_profits); - - - /** - * 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 - * @param[out] drained_profits total profits drained by the exchange so far - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_predicted_balance)(void *cls, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *balance, - struct TALER_Amount *drained_profits); - - }; diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h index b5d4dcceb..e8e32947b 100644 --- a/src/include/taler_bank_service.h +++ b/src/include/taler_bank_service.h @@ -100,25 +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_Timestamp timestamp, - const json_t *json); + const struct TALER_BANK_AdminAddIncomingResponse *air); /** @@ -191,21 +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_Timestamp timestamp); + const struct TALER_BANK_TransferResponse *tr); /** @@ -285,10 +367,6 @@ struct TALER_BANK_CreditDetails */ const char *debit_account_uri; - /** - * payto://-URL of the target account that received the funds. - */ - const char *credit_account_uri; }; @@ -328,6 +406,11 @@ struct TALER_BANK_CreditHistoryResponse { /** + * 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; @@ -337,7 +420,7 @@ struct TALER_BANK_CreditHistoryResponse */ unsigned int details_length; - } success; + } ok; } details; @@ -436,11 +519,6 @@ struct TALER_BANK_DebitDetails const char *exchange_base_url; /** - * payto://-URI of the source account that send the funds. - */ - const char *debit_account_uri; - - /** * payto://-URI of the target account that received the funds. */ const char *credit_account_uri; @@ -484,6 +562,11 @@ struct TALER_BANK_DebitHistoryResponse { /** + * 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; @@ -493,7 +576,7 @@ struct TALER_BANK_DebitHistoryResponse */ unsigned int details_length; - } success; + } ok; } details; diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 631883f41..e3ae829fd 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-2022 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,7 +18,12 @@ * @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 @@ -42,6 +47,59 @@ * 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 ************* */ @@ -143,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. @@ -420,6 +490,17 @@ struct TALER_AgeCommitmentPublicKeyP }; +/* + * @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 online public keys used by the wallet to establish a purse and the associated contract meta data. */ @@ -496,20 +577,39 @@ struct TALER_PurseMergeSignatureP /** - * @brief Type of blinding keys for Taler. - * must be 32 bytes (DB) + * @brief Type of online public keys used by AML officers. */ -union TALER_DenominationBlindingKeyP +struct TALER_AmlOfficerPublicKeyP { /** - * Clause Schnorr Signatures have 2 blinding secrets, each containing two unpredictable values. (must be 32 bytes) + * Taler uses EdDSA for AML decision signing. */ - struct GNUNET_CRYPTO_CsNonce nonce; + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + +/** + * @brief Type of online private keys used to identify + * AML officers. + */ +struct TALER_AmlOfficerPrivateKeyP +{ /** - * Taler uses RSA for blind signatures. + * Taler uses EdDSA for AML decision signing. */ - struct GNUNET_CRYPTO_RsaBlindingKeySecret rsa_bks; + 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; }; @@ -527,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. */ @@ -702,9 +815,9 @@ struct TALER_CoinPubHashP /** - * @brief Value that uniquely identifies a tip. + * @brief Value that uniquely identifies a reward. */ -struct TALER_TipIdentifierP +struct TALER_RewardIdentifierP { /** * The tip identifier is a SHA-512 hash code. @@ -825,6 +938,38 @@ GNUNET_NETWORK_STRUCT_END /** + * 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 + */ +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 @@ -1006,6 +1151,7 @@ void TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, struct TALER_RsaPubHashP *h_rsa); + /** * Hash @a cs. * @@ -1018,75 +1164,16 @@ TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs, /** - * Types of public keys used for denominations in Taler. - */ -enum TALER_DenominationCipher -{ - - /** - * Invalid type of signature. - */ - TALER_DENOMINATION_INVALID = 0, - - /** - * RSA blind signature. - */ - TALER_DENOMINATION_RSA = 1, - - /** - * Clause Blind Schnorr signature. - */ - TALER_DENOMINATION_CS = 2 -}; - - -/** * @brief Type of (unblinded) coin signatures for Taler. */ struct TALER_DenominationSignature { - - /** - * Type of the signature. - */ - enum TALER_DenominationCipher cipher; - /** - * Details, depending on @e cipher. + * Denominations use blind signatures. */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - */ - struct GNUNET_CRYPTO_CsSignature cs_signature; - - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaSignature *rsa_signature; - - } details; - + struct GNUNET_CRYPTO_UnblindedSignature *unblinded_sig; }; -/** - * The Sign Answer for Clause Blind Schnorr signature. - * The sign operation returns a parameter @param b and the signature - * scalar @param s_scalar. - */ -struct TALER_BlindedDenominationCsSignAnswer -{ - /** - * To make ROS problem harder, the signer chooses an unpredictable b and only calculates signature of c_b - */ - unsigned int b; - - /** - * The blinded s scalar calculated from c_b - */ - struct GNUNET_CRYPTO_CsBlindS s_scalar; -}; /** * @brief Type for *blinded* denomination signatures for Taler. @@ -1094,33 +1181,13 @@ struct TALER_BlindedDenominationCsSignAnswer */ struct TALER_BlindedDenominationSignature { - - /** - * Type of the signature. - */ - enum TALER_DenominationCipher cipher; - /** - * Details, depending on @e cipher. + * Denominations use blind signatures. */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - * At this point only the blinded s scalar is used. - * The final signature consisting of r,s is built after unblinding. - */ - struct TALER_BlindedDenominationCsSignAnswer blinded_cs_answer; - - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature; - - } details; - + struct GNUNET_CRYPTO_BlindedSignature *blinded_sig; }; + /* *************** Age Restriction *********************************** */ /* @@ -1169,13 +1236,8 @@ struct TALER_AgeAttestation #endif }; -extern const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash; #define TALER_AgeCommitmentHash_isNullOrZero(ph) ((NULL == ph) || \ - (0 == memcmp (ph, \ - & \ - TALER_ZeroAgeCommitmentHash, \ - sizeof(struct \ - TALER_AgeCommitmentHash)))) + GNUNET_is_zero (ph)) /** * @brief Type of public signing keys for verifying blindly signed coins. @@ -1184,31 +1246,15 @@ struct TALER_DenominationPublicKey { /** - * Type of the public key. - */ - enum TALER_DenominationCipher cipher; - - /** * Age restriction mask used for the key. */ struct TALER_AgeMask age_mask; /** - * Details, depending on @e cipher. + * Type of the public key. */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - */ - struct GNUNET_CRYPTO_CsPublicKey cs_public_key; - - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key; + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub_key; - } details; }; @@ -1218,121 +1264,21 @@ struct TALER_DenominationPublicKey struct TALER_DenominationPrivateKey { - /** - * Type of the public key. - */ - enum TALER_DenominationCipher cipher; - - /** - * Details, depending on @e cipher. - */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - */ - struct GNUNET_CRYPTO_CsPrivateKey cs_private_key; - - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key; - - } details; -}; - -/** - * @brief RSA Parameters to create blinded signature - * - */ -struct TALER_BlindedRsaPlanchet -{ - /** - * Blinded message to be signed - * Note: is malloc()'ed! - */ - void *blinded_msg; - - /** - * Size of the @e blinded_msg to be signed. - */ - size_t blinded_msg_size; -}; - - -/** - * Withdraw nonce for CS denominations - */ -struct TALER_CsNonce -{ - /** - * 32 bit nonce to include in withdrawals when using CS. - */ - struct GNUNET_CRYPTO_CsNonce nonce; -}; - - -/** - * @brief CS Parameters to create blinded signature - */ -struct TALER_BlindedCsPlanchet -{ - /** - * The Clause Schnorr c_0 and c_1 containing the blinded message - */ - struct GNUNET_CRYPTO_CsC c[2]; + struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv_key; - /** - * Public nonce. - */ - struct TALER_CsNonce nonce; }; /** - * @brief Type including Parameters to create blinded signature + * @brief Blinded planchet send to exchange for blind signing. */ struct TALER_BlindedPlanchet { /** - * Type of the sign blinded message + * A blinded message. */ - enum TALER_DenominationCipher cipher; - - /** - * Details, depending on @e cipher. - */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - */ - struct TALER_BlindedCsPlanchet cs_blinded_planchet; - - /** - * If we use #TALER_DENOMINATION_RSA in @a cipher. - */ - struct TALER_BlindedRsaPlanchet rsa_blinded_planchet; - - } details; -}; - - -/** - * Pair of Public R values for Cs denominations - */ -struct TALER_DenominationCSPublicRPairP -{ - struct GNUNET_CRYPTO_CsRPublic r_pub[2]; -}; + struct GNUNET_CRYPTO_BlindedMessage *blinded_message; - -/** - * Secret r for Cs denominations - */ -struct TALER_DenominationCSPrivateRPairP -{ - struct GNUNET_CRYPTO_CsRSecret r[2]; }; @@ -1403,38 +1349,39 @@ struct TALER_TrackTransferDetails /** - * @brief Type of algorithm specific Values for withdrawal + * @brief Inputs needed from the exchange for blind signing. */ struct TALER_ExchangeWithdrawValues { /** - * Type of the signature. - */ - enum TALER_DenominationCipher cipher; - - /** - * Details, depending on @e cipher. + * Input values. */ - union - { - /** - * If we use #TALER_DENOMINATION_CS in @a cipher. - */ - struct TALER_DenominationCSPublicRPairP cs_values; + struct GNUNET_CRYPTO_BlindingInputValues *blinding_inputs; +}; - } details; -}; +/** + * Return the alg value singleton for creation of + * blinding secrets for RSA. + * + * @return singleton to use for RSA blinding + */ +const struct TALER_ExchangeWithdrawValues * +TALER_denom_ewv_rsa_singleton (void); /** - * Free internals of @a denom_pub, but not @a denom_pub itself. + * Make a (deep) copy of the given @a bi_src to + * @a bi_dst. * - * @param[in] denom_pub key to free + * @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); /** @@ -1459,7 +1406,7 @@ TALER_planchet_setup_coin_priv ( void TALER_cs_withdraw_nonce_derive ( const struct TALER_PlanchetMasterSecretP *ps, - struct TALER_CsNonce *nonce); + struct GNUNET_CRYPTO_CsSessionNonce *nonce); /** @@ -1474,13 +1421,13 @@ void TALER_cs_refresh_nonce_derive ( const struct TALER_RefreshMasterSecretP *rms, uint32_t idx, - struct TALER_CsNonce *nonce); + 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. * @@ -1493,11 +1440,29 @@ TALER_cs_refresh_nonce_derive ( 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 @@ -1524,6 +1489,8 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); * * @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 @@ -1533,7 +1500,8 @@ TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); */ enum GNUNET_GenericReturnValue TALER_denom_blind (const struct TALER_DenominationPublicKey *dk, - const union TALER_DenominationBlindingKeyP *coin_bks, + 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, const struct TALER_ExchangeWithdrawValues *alg_values, @@ -1572,7 +1540,7 @@ 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); @@ -1607,8 +1575,8 @@ TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, * @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); /** @@ -1619,8 +1587,8 @@ TALER_denom_pub_deep_copy (struct TALER_DenominationPublicKey *denom_dst, * @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); /** @@ -1631,7 +1599,7 @@ TALER_denom_sig_deep_copy (struct TALER_DenominationSignature *denom_dst, * @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); @@ -1687,19 +1655,6 @@ TALER_blinded_planchet_cmp ( /** - * Obtain denomination public key from a denomination private key. - * - * @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 - */ -void -TALER_denom_priv_to_pub (const struct TALER_DenominationPrivateKey *denom_priv, - const struct TALER_AgeMask age_mask, - struct TALER_DenominationPublicKey *denom_pub); - - -/** * Verify signature made with a denomination public key * over a coin. * @@ -1715,6 +1670,51 @@ TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub, /** + * 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); + + +/** * Check if a coin is valid; that is, whether the denomination key exists, * is not expired, and the signature is correct. * @@ -1733,11 +1733,10 @@ TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, * Compute the hash of a blinded coin. * * @param blinded_planchet blinded planchet - * @param denom_hash hash of the denomination publick key + * @param denom_hash hash of the denomination public key * @param[out] bch where to write the hash - * @return #GNUNET_OK when successful, #GNUNET_SYSERR if an internal error occurred */ -enum GNUNET_GenericReturnValue +void TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, const struct TALER_DenominationHashP *denom_hash, struct TALER_BlindedCoinHashP *bch); @@ -1766,6 +1765,7 @@ void TALER_payto_hash (const char *payto, struct TALER_PaytoHashP *h_payto); + /** * Details about a planchet that the customer wants to obtain * a withdrawal authorization. This is the information that @@ -1968,7 +1968,7 @@ void TALER_planchet_blinding_secret_create ( const struct TALER_PlanchetMasterSecretP *ps, const struct TALER_ExchangeWithdrawValues *alg_values, - union TALER_DenominationBlindingKeyP *bks); + union GNUNET_CRYPTO_BlindingSecretP *bks); /** @@ -1977,6 +1977,7 @@ TALER_planchet_blinding_secret_create ( * @param dk denomination key for the coin to be created * @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) @@ -1986,13 +1987,15 @@ TALER_planchet_blinding_secret_create ( * @return #GNUNET_OK on success */ enum GNUNET_GenericReturnValue -TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct TALER_ExchangeWithdrawValues *alg_values, - const union TALER_DenominationBlindingKeyP *bks, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - const struct TALER_AgeCommitmentHash *ach, - struct TALER_CoinPubHashP *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); /** @@ -2032,7 +2035,7 @@ enum GNUNET_GenericReturnValue TALER_planchet_to_coin ( const struct TALER_DenominationPublicKey *dk, const struct TALER_BlindedDenominationSignature *blind_sig, - const union TALER_DenominationBlindingKeyP *bks, + const union GNUNET_CRYPTO_BlindingSecretP *bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, const struct TALER_AgeCommitmentHash *ach, const struct TALER_CoinPubHashP *c_hash, @@ -2233,6 +2236,89 @@ TALER_CRYPTO_contract_decrypt_for_deposit ( 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 **************** */ /** @@ -2253,7 +2339,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. @@ -2265,7 +2351,7 @@ typedef void 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); @@ -2274,6 +2360,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). @@ -2281,6 +2368,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); @@ -2366,9 +2454,9 @@ TALER_CRYPTO_helper_rsa_sign ( enum TALER_ErrorCode TALER_CRYPTO_helper_rsa_batch_sign ( struct TALER_CRYPTO_RsaDenominationHelper *dh, - const struct TALER_CRYPTO_RsaSignRequest *rsrs, unsigned int rsrs_length, - struct TALER_BlindedDenominationSignature *bss); + const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length], + struct TALER_BlindedDenominationSignature bss[static rsrs_length]); /** @@ -2401,6 +2489,7 @@ void TALER_CRYPTO_helper_rsa_disconnect ( struct TALER_CRYPTO_RsaDenominationHelper *dh); + /* **************** Helper-based CS operations **************** */ /** @@ -2421,7 +2510,7 @@ struct TALER_CRYPTO_CsDenominationHelper; * @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 denom_pub the public key itself, NULL if the key was revoked or 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. @@ -2433,7 +2522,7 @@ typedef void struct GNUNET_TIME_Timestamp start_time, struct GNUNET_TIME_Relative validity_duration, const struct TALER_CsPubHashP *h_cs, - const struct TALER_DenominationPublicKey *denom_pub, + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub, const struct TALER_SecurityModulePublicKeyP *sm_pub, const struct TALER_SecurityModuleSignatureP *sm_sig); @@ -2442,6 +2531,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). @@ -2449,6 +2539,7 @@ typedef void 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); @@ -2479,7 +2570,8 @@ struct TALER_CRYPTO_CsSignRequest /** * Blinded planchet containing c and the nonce. */ - const struct TALER_BlindedCsPlanchet *blinded_planchet; + const struct GNUNET_CRYPTO_CsBlindedMessage *blinded_planchet; + }; @@ -2525,10 +2617,10 @@ TALER_CRYPTO_helper_cs_sign ( enum TALER_ErrorCode TALER_CRYPTO_helper_cs_batch_sign ( struct TALER_CRYPTO_CsDenominationHelper *dh, - const struct TALER_CRYPTO_CsSignRequest *reqs, unsigned int reqs_length, + const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length], bool for_melt, - struct TALER_BlindedDenominationSignature *bss); + struct TALER_BlindedDenominationSignature bss[static reqs_length]); /** @@ -2563,9 +2655,9 @@ struct TALER_CRYPTO_CsDeriveRequest const struct TALER_CsPubHashP *h_cs; /** - * Nonce to use. + * Nonce to use for the /csr request. */ - const struct TALER_CsNonce *nonce; + const struct GNUNET_CRYPTO_CsSessionNonce *nonce; }; @@ -2590,7 +2682,7 @@ TALER_CRYPTO_helper_cs_r_derive ( struct TALER_CRYPTO_CsDenominationHelper *dh, const struct TALER_CRYPTO_CsDeriveRequest *cdr, bool for_melt, - struct TALER_DenominationCSPublicRPairP *crp); + struct GNUNET_CRYPTO_CSPublicRPairP *crp); /** @@ -2603,8 +2695,8 @@ TALER_CRYPTO_helper_cs_r_derive ( * differences in the signature counters. Retrying in this case may work. * * @param dh helper to process connection - * @param cdrs array with derivation input data * @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) @@ -2612,10 +2704,10 @@ TALER_CRYPTO_helper_cs_r_derive ( enum TALER_ErrorCode TALER_CRYPTO_helper_cs_r_batch_derive ( struct TALER_CRYPTO_CsDenominationHelper *dh, - const struct TALER_CRYPTO_CsDeriveRequest *cdrs, unsigned int cdrs_length, + const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length], bool for_melt, - struct TALER_DenominationCSPublicRPairP *crps); + struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length]); /** @@ -2661,6 +2753,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). @@ -2668,6 +2761,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); @@ -2816,6 +2910,31 @@ TALER_wallet_purse_create_verify ( /** + * 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 @@ -3188,11 +3307,13 @@ TALER_wallet_reserve_close_verify ( * 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); @@ -3200,12 +3321,14 @@ TALER_wallet_account_setup_sign ( * 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); @@ -3251,6 +3374,7 @@ TALER_wallet_reserve_attest_request_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 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 @@ -3266,6 +3390,7 @@ TALER_wallet_deposit_sign ( const struct TALER_Amount *deposit_fee, 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, @@ -3283,6 +3408,7 @@ 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 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 @@ -3299,6 +3425,7 @@ TALER_wallet_deposit_verify ( const struct TALER_Amount *deposit_fee, 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, @@ -3429,6 +3556,45 @@ TALER_wallet_withdraw_verify ( /** + * 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 @@ -3457,7 +3623,7 @@ TALER_exchange_melt_confirmation_verify ( enum GNUNET_GenericReturnValue TALER_wallet_recoup_verify ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig); @@ -3473,7 +3639,7 @@ TALER_wallet_recoup_verify ( void TALER_wallet_recoup_sign ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig); @@ -3490,7 +3656,7 @@ TALER_wallet_recoup_sign ( enum GNUNET_GenericReturnValue TALER_wallet_recoup_refresh_verify ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig); @@ -3506,7 +3672,7 @@ TALER_wallet_recoup_refresh_verify ( void TALER_wallet_recoup_refresh_sign ( const struct TALER_DenominationHashP *h_denom_pub, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_CoinSpendSignatureP *coin_sig); @@ -3514,63 +3680,59 @@ TALER_wallet_recoup_refresh_sign ( /** * Verify reserve history request signature. * - * @param ts timestamp used - * @param history_fee how much did the wallet say it would pay + * @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 ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_Amount *history_fee, + uint64_t start_off, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig); /** - * Create reserve history request signature. + * Create reserve status request signature. * - * @param ts timestamp used - * @param history_fee how much do we expect to pay + * @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 ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_Amount *history_fee, + uint64_t start_off, const struct TALER_ReservePrivateKeyP *reserve_priv, struct TALER_ReserveSignatureP *reserve_sig); /** - * Verify reserve status request signature. + * Verify coin history request signature. * - * @param ts timestamp used - * @param reserve_pub reserve the status request was for - * @param reserve_sig resulting 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_reserve_status_verify ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig); +TALER_wallet_coin_history_verify ( + uint64_t start_off, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); /** - * Create reserve status request signature. + * Create coin status request signature. * - * @param ts timestamp used - * @param reserve_priv private key of the reserve the status request is for - * @param[out] reserve_sig resulting 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_reserve_status_sign ( - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_ReservePrivateKeyP *reserve_priv, - struct TALER_ReserveSignatureP *reserve_sig); +TALER_wallet_coin_history_sign ( + uint64_t start_off, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); /* ********************* merchant signing ************************** */ @@ -3709,8 +3871,9 @@ typedef enum TALER_ErrorCode * @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 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 @@ -3725,8 +3888,9 @@ TALER_exchange_online_deposit_confirmation_sign ( struct GNUNET_TIME_Timestamp exchange_timestamp, struct GNUNET_TIME_Timestamp wire_deadline, struct GNUNET_TIME_Timestamp refund_deadline, - const struct TALER_Amount *amount_without_fee, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + 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); @@ -3741,8 +3905,9 @@ TALER_exchange_online_deposit_confirmation_sign ( * @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 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 @@ -3756,8 +3921,9 @@ TALER_exchange_online_deposit_confirmation_verify ( struct GNUNET_TIME_Timestamp exchange_timestamp, struct GNUNET_TIME_Timestamp wire_deadline, struct GNUNET_TIME_Timestamp refund_deadline, - const struct TALER_Amount *amount_without_fee, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + 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); @@ -4517,10 +4683,90 @@ TALER_exchange_online_purse_status_verify ( 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 @@ -5117,6 +5363,9 @@ TALER_exchange_offline_global_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 @@ -5124,6 +5373,9 @@ TALER_exchange_offline_global_fee_verify ( void TALER_exchange_offline_wire_add_sign ( const char *payto_uri, + 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); @@ -5133,6 +5385,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 @@ -5141,6 +5396,9 @@ TALER_exchange_offline_wire_add_sign ( enum GNUNET_GenericReturnValue TALER_exchange_offline_wire_add_verify ( const char *payto_uri, + 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); @@ -5183,6 +5441,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 @@ -5190,6 +5451,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); @@ -5198,12 +5462,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); @@ -5267,7 +5537,7 @@ void TALER_merchant_pay_sign ( const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_MerchantPrivateKeyP *merch_priv, - struct GNUNET_CRYPTO_EddsaSignature *merch_sig); + struct TALER_MerchantSignatureP *merch_sig); /** @@ -5449,12 +5719,11 @@ TALER_age_commitment_hash ( * @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 - * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise */ -enum GNUNET_GenericReturnValue +void TALER_age_restriction_commit ( const struct TALER_AgeMask *mask, - const uint8_t age, + uint8_t age, const struct GNUNET_HashCode *seed, struct TALER_AgeCommitmentProof *comm_proof); @@ -5479,7 +5748,7 @@ TALER_age_commitment_derive ( * * @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 applicaple. + * @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 @@ -5494,7 +5763,7 @@ TALER_age_commitment_attest ( * * @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 applicaple. + * @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 @@ -5507,30 +5776,189 @@ TALER_age_commitment_verify ( /** * @brief helper function to free memory of a struct TALER_AgeCommitment * - * @param p the commitment from which all memory should be freed. + * @param ac the commitment from which all memory should be freed. */ void TALER_age_commitment_free ( - struct TALER_AgeCommitment *p); + struct TALER_AgeCommitment *ac); /** * @brief helper function to free memory of a struct TALER_AgeProof * - * @param p the proof of commitment from which all memory should be freed. + * @param ap the proof of commitment from which all memory should be freed. */ void TALER_age_proof_free ( - struct TALER_AgeProof *p); + struct TALER_AgeProof *ap); /** * @brief helper function to free memory of a struct TALER_AgeCommitmentProof * - * @param p the commitment and its proof from which all memory should be freed. + * @param acp the commitment and its proof from which all memory should be freed. */ void TALER_age_commitment_proof_free ( - struct TALER_AgeCommitmentProof *p); + 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 04dc20b9e..f108e6158 100644 --- a/src/include/taler_curl_lib.h +++ b/src/include/taler_curl_lib.h @@ -79,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 d11f7d616..0597799b5 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2022 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 Affero General Public License as published by the Free Software @@ -16,8 +16,11 @@ /** * @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 @@ -29,28 +32,13 @@ #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, - - /** - * 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 +#define TALER_EXCHANGE_API_VERSION 0x00100000 -}; +/* ********************* /keys *********************** */ /** @@ -141,10 +129,18 @@ struct TALER_EXCHANGE_DenomPublicKey struct TALER_DenomFeeSet fees; /** + * 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. + */ + bool lost; + + /** * Set to true if this denomination key has been * revoked by the exchange. */ bool revoked; + }; @@ -249,6 +245,183 @@ struct TALER_EXCHANGE_GlobalFee /** + * 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 @@ -260,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; @@ -280,6 +458,11 @@ struct TALER_EXCHANGE_Keys 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 @@ -293,11 +476,18 @@ struct TALER_EXCHANGE_Keys char *currency; /** - * 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). + * What is the base URL of the exchange that returned + * these keys? */ - struct GNUNET_TIME_Relative reserve_closing_delay; + 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 @@ -306,10 +496,26 @@ struct TALER_EXCHANGE_Keys struct TALER_Amount *wallet_balance_limit_without_kyc; /** - * Length of the @e wallet_balance_limit_without_kyc - * array. + * Array of accounts of the exchange. */ - unsigned int wblwk_length; + 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). + */ + struct GNUNET_TIME_Relative reserve_closing_delay; /** * Timestamp indicating the /keys generation. @@ -317,6 +523,11 @@ struct TALER_EXCHANGE_Keys struct GNUNET_TIME_Timestamp list_issue_date; /** + * When does this keys data expire? + */ + struct GNUNET_TIME_Timestamp key_data_expiration; + + /** * Timestamp indicating the creation time of the last * denomination key in /keys. * Used to fetch /keys incrementally. @@ -329,6 +540,37 @@ struct TALER_EXCHANGE_Keys 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; @@ -358,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; }; @@ -425,6 +677,7 @@ struct TALER_EXCHANGE_HttpResponse * reply (too big, invalid JSON). */ const json_t *reply; + /** * Set to the human-readable 'hint' that is optionally * provided by the exchange together with errors. NULL @@ -453,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_Timestamp 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_Timestamp -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); /** @@ -609,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); /** @@ -654,7 +942,8 @@ TALER_EXCHANGE_get_global_fee ( * 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 ( @@ -663,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 ( @@ -699,124 +989,36 @@ 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. - */ -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 a wire account of the exchange. - */ -struct TALER_EXCHANGE_WireAccount -{ - /** - * payto://-URI of the exchange. - */ - const char *payto_uri; - - /** - * Signature of the exchange over the account (was checked by the API). - */ - struct TALER_MasterSignatureP master_sig; - - /** - * Linked list of wire fees the exchange charges for - * accounts of the wire method matching @e 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. + * Parse array of @a accounts of the exchange into @a was. * - * 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 + * @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_WireHandle; - - -/** - * 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); +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]); /** - * Cancel a wire information request. This function cannot be used - * on a request handle if a response is already served for it. + * Free data within @a was, but not @a was itself. * - * @param wh the wire information request handle + * @param was array of wire account data + * @param was_len length of the @a was array */ void -TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh); +TALER_EXCHANGE_free_accounts ( + unsigned int was_len, + struct TALER_EXCHANGE_WireAccount was[static was_len]); /* ********************* /coins/$COIN_PUB/deposit *********************** */ @@ -869,18 +1071,16 @@ struct TALER_EXCHANGE_DepositContractDetail { /** - * 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). + * Hash of the contact of the merchant with the customer (further details + * are never disclosed to the exchange) */ - struct GNUNET_TIME_Timestamp wire_deadline; + struct TALER_PrivateContractHashP h_contract_terms; /** - * The merchant’s account details, in the payto://-format supported by the - * exchange. + * The public key of the merchant (used to identify the merchant for refund + * requests). */ - const char *merchant_payto_uri; + struct TALER_MerchantPublicKeyP merchant_pub; /** * Salt used to hash the @e merchant_payto_uri. @@ -888,168 +1088,47 @@ struct TALER_EXCHANGE_DepositContractDetail struct TALER_WireSaltP wire_salt; /** - * Hash of the contact of the merchant with the customer (further details - * are never disclosed to the exchange) + * Hash over data provided by the wallet to customize the contract. + * All zero if not used. */ - struct TALER_PrivateContractHashP h_contract_terms; + struct GNUNET_HashCode wallet_data_hash; /** - * Policy extension specific details about the deposit relevant to the exchange. + * 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. */ - json_t *policy_details; + struct GNUNET_TIME_Timestamp refund_deadline; /** - * Timestamp when the contract was finalized, must match approximately the - * current time of the exchange. + * 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 timestamp; + struct GNUNET_TIME_Timestamp wire_deadline; /** - * The public key of the merchant (used to identify the merchant for refund - * requests). + * Timestamp when the contract was finalized, must match approximately the + * current time of the exchange. */ - struct TALER_MerchantPublicKeyP merchant_pub; + struct GNUNET_TIME_Timestamp wallet_timestamp; /** - * 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. + * The merchant’s account details, in the payto://-format supported by the + * exchange. */ - struct GNUNET_TIME_Timestamp refund_deadline; - -}; - - -/** - * @brief A Deposit Handle - */ -struct TALER_EXCHANGE_DepositHandle; - + const char *merchant_payto_uri; -/** - * Structure with information about a deposit - * operation's result. - */ -struct TALER_EXCHANGE_DepositResult -{ /** - * HTTP response data + * Policy extension specific details about the deposit relevant to the exchange. */ - struct TALER_EXCHANGE_HttpResponse hr; - - union - { - - /** - * Information returned if the HTTP status is - * #MHD_HTTP_OK. - */ - struct - { - /** - * Time when the exchange generated the deposit confirmation - */ - struct GNUNET_TIME_Timestamp deposit_timestamp; + const json_t *policy_details; - /** - * signature provided by the exchange - */ - const struct TALER_ExchangeSignatureP *exchange_sig; - - /** - * exchange key used to sign @a exchange_sig. - */ - const struct TALER_ExchangePublicKeyP *exchange_pub; - - /** - * Base URL for looking up wire transfers, or - * NULL to use the default base URL. - */ - const char *transaction_base_url; - - } success; - - /** - * Information returned if the HTTP status is - * #MHD_HTTP_CONFLICT. - */ - struct - { - /* TODO: returning full details is not implemented */ - } conflict; - - } details; }; /** - * Callbacks of this type are used to serve the result of submitting a - * deposit permission request to a exchange. - * - * @param cls closure - * @param dr deposit response details - */ -typedef void -(*TALER_EXCHANGE_DepositResultCallback) ( - void *cls, - const struct TALER_EXCHANGE_DepositResult *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. - * - * We also verify that the @a cdd.coin_sig is valid for this deposit - * request, and that the @a cdd.ub_sig is a valid signature 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 dcd details about the contract the deposit is for - * @param cdd details about the coin 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_EXCHANGE_DepositContractDetail *dcd, - const struct TALER_EXCHANGE_CoinDepositDetail *cdd, - TALER_EXCHANGE_DepositResultCallback cb, - void *cb_cls, - enum TALER_ErrorCode *ec); - - -/** - * Change the chance that our deposit confirmation will be given to the - * auditor to 100%. - * - * @param deposit the deposit permission request handle - */ -void -TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit); - - -/** - * Cancel a 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 - */ -void -TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit); - - -/** * @brief A Batch Deposit Handle */ struct TALER_EXCHANGE_BatchDepositHandle; @@ -1081,9 +1160,9 @@ struct TALER_EXCHANGE_BatchDepositResult struct GNUNET_TIME_Timestamp deposit_timestamp; /** - * Array of signatures provided by the exchange + * Deposit confirmation signature provided by the exchange */ - const struct TALER_ExchangeSignatureP *exchange_sigs; + const struct TALER_ExchangeSignatureP *exchange_sig; /** * exchange key used to sign @a exchange_sig. @@ -1096,12 +1175,7 @@ struct TALER_EXCHANGE_BatchDepositResult */ const char *transaction_base_url; - /** - * Length of the @e exchange_sigs array. - */ - unsigned int num_signatures; - - } success; + } ok; /** * Information returned if the HTTP status is @@ -1109,7 +1183,11 @@ struct TALER_EXCHANGE_BatchDepositResult */ struct { - /* TODO: returning full details is not implemented */ + /** + * The coin that had a conflict. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + } conflict; } details; @@ -1143,7 +1221,9 @@ typedef void * 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 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 @@ -1155,10 +1235,12 @@ typedef void */ struct TALER_EXCHANGE_BatchDepositHandle * TALER_EXCHANGE_batch_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + 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, + const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds], TALER_EXCHANGE_BatchDepositResultCallback cb, void *cb_cls, enum TALER_ErrorCode *ec); @@ -1168,23 +1250,22 @@ TALER_EXCHANGE_batch_deposit ( * Change the chance that our deposit confirmation will be given to the * auditor to 100%. * - * @param deposit the batch deposit permission request handle + * @param[in,out] deposit the batch deposit permission request handle */ void -TALER_EXCHANGE_batch_deposit_force_dc (struct - TALER_EXCHANGE_BatchDepositHandle * - deposit); +TALER_EXCHANGE_batch_deposit_force_dc ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /** * 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_batch_deposit_cancel (struct - TALER_EXCHANGE_BatchDepositHandle *deposit); +TALER_EXCHANGE_batch_deposit_cancel ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /* ********************* /coins/$COIN_PUB/refund *********************** */ @@ -1194,23 +1275,51 @@ TALER_EXCHANGE_batch_deposit_cancel (struct */ 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. @@ -1224,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 @@ -1241,15 +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_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); +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); /** @@ -1303,14 +1416,14 @@ struct TALER_EXCHANGE_CsRMeltResponse * respective coin's withdraw operation. */ const struct TALER_ExchangeWithdrawValues *alg_values; - } success; + } ok; /** * Details if the status is #MHD_HTTP_GONE. */ struct { - /* TODO: returning full details is not implemented */ + /* FIXME: returning full details is not implemented */ } gone; } details; @@ -1351,7 +1464,8 @@ struct TALER_EXCHANGE_NonceKey /** * Get a set of CS R values using a /csr-melt request. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @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 @@ -1362,12 +1476,14 @@ struct TALER_EXCHANGE_NonceKey * In this case, the callback is not called. */ struct TALER_EXCHANGE_CsRMeltHandle * -TALER_EXCHANGE_csr_melt (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_RefreshMasterSecretP *rms, - unsigned int nks_len, - struct TALER_EXCHANGE_NonceKey *nks, - TALER_EXCHANGE_CsRMeltCallback res_cb, - void *res_cb_cls); +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); /** @@ -1415,7 +1531,8 @@ struct TALER_EXCHANGE_CsRWithdrawResponse * respective coin's withdraw operation. */ struct TALER_ExchangeWithdrawValues alg_values; - } success; + + } ok; /** * Details if the status is #MHD_HTTP_GONE. @@ -1445,7 +1562,8 @@ typedef void /** * Get a CS R using a /csr-withdraw request. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @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 @@ -1455,11 +1573,13 @@ typedef void * In this case, the callback is not called. */ struct TALER_EXCHANGE_CsRWithdrawHandle * -TALER_EXCHANGE_csr_withdraw (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_CsNonce *nonce, - TALER_EXCHANGE_CsRWithdrawCallback res_cb, - void *res_cb_cls); +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); /** @@ -1474,6 +1594,329 @@ 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 *********************** */ /** @@ -1493,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, @@ -1503,11 +1951,6 @@ enum TALER_EXCHANGE_ReserveTransactionType TALER_EXCHANGE_RTT_CLOSING, /** - * Reserve history request. - */ - TALER_EXCHANGE_RTT_HISTORY, - - /** * Reserve purse merge operation. */ TALER_EXCHANGE_RTT_MERGE, @@ -1588,6 +2031,28 @@ struct TALER_EXCHANGE_ReserveHistoryEntry } 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. */ @@ -1624,7 +2089,7 @@ struct TALER_EXCHANGE_ReserveHistoryEntry 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; @@ -1657,25 +2122,6 @@ struct TALER_EXCHANGE_ReserveHistoryEntry } close_details; /** - * Information about a history operation of the reserve. - * @e type is #TALER_EXCHANGE_RTT_HISTORY. - */ - struct - { - - /** - * When was the request made. - */ - struct GNUNET_TIME_Timestamp request_timestamp; - - /** - * Signature by the reserve approving the history request. - */ - struct TALER_ReserveSignatureP reserve_sig; - - } history_details; - - /** * Information about a merge operation on the reserve. * @e type is #TALER_EXCHANGE_RTT_MERGE. */ @@ -1869,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) @@ -1880,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, @@ -1899,15 +2347,15 @@ TALER_EXCHANGE_reserves_get_cancel ( /** - * @brief A /reserves/$RID/status Handle + * @brief A /reserves/$RID/history Handle */ -struct TALER_EXCHANGE_ReservesStatusHandle; +struct TALER_EXCHANGE_ReservesHistoryHandle; /** - * @brief Reserve status details. + * @brief Reserve history details. */ -struct TALER_EXCHANGE_ReserveStatus +struct TALER_EXCHANGE_ReserveHistory { /** @@ -1916,14 +2364,14 @@ struct TALER_EXCHANGE_ReserveStatus struct TALER_EXCHANGE_HttpResponse hr; /** - * Details depending on @e hr.http_status. + * Details depending on @e hr.http_history. */ union { /** * Information returned on success, if - * @e hr.http_status is #MHD_HTTP_OK + * @e hr.http_history is #MHD_HTTP_OK */ struct { @@ -1945,122 +2393,11 @@ struct TALER_EXCHANGE_ReserveStatus struct TALER_Amount total_out; /** - * Reserve history. + * Current etag / last entry in the history. + * Useful to filter requests by starting offset. + * Offsets are not necessarily contiguous. */ - 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 status request to a exchange. - * - * @param cls closure - * @param rs HTTP response data - */ -typedef void -(*TALER_EXCHANGE_ReservesStatusCallback) ( - void *cls, - const struct TALER_EXCHANGE_ReserveStatus *rs); - - -/** - * Submit a request to obtain the reserve status. - * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param reserve_priv private key of the reserve to inspect - * @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_ReservesStatusHandle * -TALER_EXCHANGE_reserves_status ( - struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_ReservePrivateKeyP *reserve_priv, - TALER_EXCHANGE_ReservesStatusCallback 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 rsh the reserve request handle - */ -void -TALER_EXCHANGE_reserves_status_cancel ( - struct TALER_EXCHANGE_ReservesStatusHandle *rsh); - - -/** - * @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; - - /** - * Timestamp of when we made the history request - * (client-side). - */ - struct GNUNET_TIME_Timestamp ts; - - /** - * Reserve signature affirming the history request - * (generated as part of the request). - */ - const struct TALER_ReserveSignatureP *reserve_sig; - - /** - * Details depending on @e hr.http_status. - */ - union - { - - /** - * Information returned on success, if - * @e hr.http_status is #MHD_HTTP_OK - */ - struct - { - - /** - * Reserve balance. May not be the difference between - * @e total_in and @e total_out because the @e may be truncated - * due to expiration. - */ - 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; + uint64_t etag; /** * Reserve history. @@ -2095,8 +2432,11 @@ typedef void /** * Submit a request to obtain the reserve history. * - * @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 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. @@ -2104,8 +2444,11 @@ typedef void */ struct TALER_EXCHANGE_ReservesHistoryHandle * TALER_EXCHANGE_reserves_history ( - struct TALER_EXCHANGE_Handle *exchange, + 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); @@ -2121,15 +2464,6 @@ TALER_EXCHANGE_reserves_history_cancel ( struct TALER_EXCHANGE_ReservesHistoryHandle *rsh); -/* ********************* POST /reserves/$RESERVE_PUB/withdraw *********************** */ - - -/** - * @brief A /reserves/$RESERVE_PUB/withdraw Handle - */ -struct TALER_EXCHANGE_WithdrawHandle; - - /** * Information input into the withdraw process per coin. */ @@ -2168,7 +2502,7 @@ struct TALER_EXCHANGE_PrivateCoinDetails * Value used to blind the key for the signature. * Needed for recoup operations. */ - union TALER_DenominationBlindingKeyP bks; + union GNUNET_CRYPTO_BlindingSecretP bks; /** * Signature over the coin. @@ -2184,115 +2518,6 @@ struct TALER_EXCHANGE_PrivateCoinDetails /** - * Details about a response for a withdraw request. - */ -struct TALER_EXCHANGE_WithdrawResponse -{ - /** - * HTTP response data. - */ - struct TALER_EXCHANGE_HttpResponse hr; - - /** - * Details about the response. - */ - union - { - /** - * Details if the status is #MHD_HTTP_OK. - */ - struct TALER_EXCHANGE_PrivateCoinDetails success; - - /** - * 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; - - /** - * Hash of the payto-URI of the account to KYC; - */ - struct TALER_PaytoHashP h_payto; - - } unavailable_for_legal_reasons; - - /** - * Details if the status is #MHD_HTTP_CONFLICT. - */ - struct - { - /* TODO: returning full details is not implemented */ - } conflict; - - /** - * Details if the status is #MHD_HTTP_GONE. - */ - struct - { - /* TODO: returning full details is not implemented */ - } gone; - - } details; -}; - - -/** - * Callbacks of this type are used to serve the result of submitting a - * withdraw request to a exchange. - * - * @param cls closure - * @param wr response details - */ -typedef void -(*TALER_EXCHANGE_WithdrawCallback) ( - void *cls, - const struct TALER_EXCHANGE_WithdrawResponse *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. - * - * 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 reserve_priv private key of the reserve to withdraw from - * @param wci inputs that determine the planchet - * @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_ReservePrivateKeyP *reserve_priv, - const struct TALER_EXCHANGE_WithdrawCoinInput *wci, - TALER_EXCHANGE_WithdrawCallback 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. - * - * @param wh the withdraw handle - */ -void -TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh); - - -/** * @brief A /reserves/$RESERVE_PUB/batch-withdraw Handle */ struct TALER_EXCHANGE_BatchWithdrawHandle; @@ -2328,7 +2553,7 @@ struct TALER_EXCHANGE_BatchWithdrawResponse * Length of the @e coins array. */ unsigned int num_coins; - } success; + } ok; /** * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. @@ -2384,17 +2609,20 @@ typedef void /** * 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. + * 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 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 wcis inputs that determine the planchets * @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 @@ -2403,10 +2631,12 @@ typedef void */ struct TALER_EXCHANGE_BatchWithdrawHandle * TALER_EXCHANGE_batch_withdraw ( - struct TALER_EXCHANGE_Handle *exchange, + 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_EXCHANGE_WithdrawCoinInput *wcis, unsigned int wci_length, + const struct TALER_EXCHANGE_WithdrawCoinInput wcis[static wci_length], TALER_EXCHANGE_BatchWithdrawCallback res_cb, void *res_cb_cls); @@ -2423,18 +2653,45 @@ TALER_EXCHANGE_batch_withdraw_cancel ( /** + * 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); /** @@ -2450,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 @@ -2467,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); /** @@ -2485,20 +2751,67 @@ TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh); /** + * 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 hr HTTP response data - * @param blind_sigs array of blind signatures over the coins, NULL on error - * @param blind_sigs_length length of @a blind_sigs + * @param bw2r response data */ typedef void (*TALER_EXCHANGE_BatchWithdraw2Callback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_BlindedDenominationSignature *blind_sigs, - unsigned int blind_sigs_length); + const struct TALER_EXCHANGE_BatchWithdraw2Response *bw2r); /** @@ -2521,7 +2834,9 @@ struct TALER_EXCHANGE_BatchWithdraw2Handle; * 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 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 @@ -2533,10 +2848,12 @@ struct TALER_EXCHANGE_BatchWithdraw2Handle; */ struct TALER_EXCHANGE_BatchWithdraw2Handle * TALER_EXCHANGE_batch_withdraw2 ( - struct TALER_EXCHANGE_Handle *exchange, + 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_PlanchetDetail *pds, unsigned int pds_length, + const struct TALER_PlanchetDetail pds[static pds_length], TALER_EXCHANGE_BatchWithdraw2Callback res_cb, void *res_cb_cls); @@ -2552,13 +2869,425 @@ 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; + +/** + * @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, 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). + * In this case, the callback is not called. + */ +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. + * one coin in a single request will make those coins linkable, so we only melt + * one coin at a time. */ struct TALER_EXCHANGE_RefreshData { @@ -2567,11 +3296,16 @@ struct TALER_EXCHANGE_RefreshData */ struct TALER_CoinSpendPrivateKeyP melt_priv; - /* - * age commitment and proof and its hash that went into the original coin, + /** + * 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; /** @@ -2667,7 +3401,7 @@ struct TALER_EXCHANGE_MeltResponse * Gamma value chosen by the exchange. */ uint32_t noreveal_index; - } success; + } ok; } details; }; @@ -2697,7 +3431,9 @@ typedef void * 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 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 @@ -2706,11 +3442,14 @@ typedef void * In this case, neither callback will be called. */ struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_RefreshMasterSecretP *rms, - const struct TALER_EXCHANGE_RefreshData *rd, - 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); /** @@ -2745,12 +3484,12 @@ struct TALER_EXCHANGE_RevealedCoinInfo * Age commitment and its hash of the coin, might be NULL. */ struct TALER_AgeCommitmentProof *age_commitment_proof; - struct TALER_AgeCommitmentHash *h_age_commitment; + struct TALER_AgeCommitmentHash h_age_commitment; /** * Blinding keys used to blind the fresh coin. */ - union TALER_DenominationBlindingKeyP bks; + union GNUNET_CRYPTO_BlindingSecretP bks; /** * Signature affirming the validity of the coin. @@ -2793,7 +3532,7 @@ struct TALER_EXCHANGE_RevealResult * Number of coins returned. */ unsigned int num_coins; - } success; + } ok; } details; @@ -2830,7 +3569,8 @@ 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 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 @@ -2845,11 +3585,12 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; */ struct TALER_EXCHANGE_RefreshesRevealHandle * TALER_EXCHANGE_refreshes_reveal ( - struct TALER_EXCHANGE_Handle *exchange, + 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, + const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], uint32_t noreveal_index, TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, void *reveal_cb_cls); @@ -2886,10 +3627,11 @@ struct TALER_EXCHANGE_LinkedCoinInfo struct TALER_CoinSpendPrivateKeyP coin_priv; /** - * Age commitment and its hash, if applicable. Might be NULL. + * Age commitment and its hash, if applicable. */ - struct TALER_AgeCommitmentProof *age_commitment_proof; - struct TALER_AgeCommitmentHash *h_age_commitment; + bool has_age_commitment; + struct TALER_AgeCommitmentProof age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; /** * Master secret of this coin. @@ -2939,7 +3681,7 @@ struct TALER_EXCHANGE_LinkResult * Number of coins returned. */ unsigned int num_coins; - } success; + } ok; } details; @@ -2967,7 +3709,8 @@ 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 @@ -2977,7 +3720,8 @@ typedef void */ struct TALER_EXCHANGE_LinkHandle * TALER_EXCHANGE_link ( - struct TALER_EXCHANGE_Handle *exchange, + 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, @@ -3052,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 @@ -3078,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); @@ -3155,7 +3928,7 @@ struct TALER_EXCHANGE_GetDepositResponse */ struct TALER_Amount coin_contribution; - } success; + } ok; /** * Response if the status was #MHD_HTTP_ACCEPTED @@ -3175,6 +3948,12 @@ struct TALER_EXCHANGE_GetDepositResponse uint64_t requirement_row; /** + * Current AML state for the account. May explain why transfers are + * not happening. + */ + enum TALER_AmlDecisionState aml_decision; + + /** * Set to 'true' if the KYC check is already finished and * the exchange is merely waiting for the @e execution_time. */ @@ -3202,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_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); @@ -3233,72 +4018,44 @@ TALER_EXCHANGE_deposits_get_cancel ( struct TALER_EXCHANGE_DepositGetHandle *dwh); -/** - * Convenience function. Verifies a coin's transaction history as - * returned by the exchange. - * - * @param dk fee structure for the coin - * @param coin_pub public key of the coin - * @param history history of the coin in json encoding - * @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 - */ -enum GNUNET_GenericReturnValue -TALER_EXCHANGE_verify_coin_history ( - const struct TALER_EXCHANGE_DenomPublicKey *dk, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - json_t *history, - struct TALER_Amount *total); +/* ********************* /recoup *********************** */ /** - * Parse history given in JSON format and return it in binary - * format. - * - * @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] total_in set to value of credits to reserve - * @param[out] total_out set to value of debits from reserve - * @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 + * @brief A /recoup Handle */ -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 *total_in, - struct TALER_Amount *total_out, - unsigned int history_length, - struct TALER_EXCHANGE_ReserveHistoryEntry *rhistory); +struct TALER_EXCHANGE_RecoupHandle; /** - * Free memory (potentially) allocated by #TALER_EXCHANGE_parse_reserve_history(). - * - * @param rhistory result to free - * @param len number of entries in @a rhistory + * Response from a recoup request. */ -void -TALER_EXCHANGE_free_reserve_history ( - struct TALER_EXCHANGE_ReserveHistoryEntry *rhistory, - unsigned int len); - +struct TALER_EXCHANGE_RecoupResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; -/* ********************* /recoup *********************** */ + /** + * 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; -/** - * @brief A /recoup Handle - */ -struct TALER_EXCHANGE_RecoupHandle; +}; /** @@ -3308,14 +4065,12 @@ struct TALER_EXCHANGE_RecoupHandle; * reserve that was credited. * * @param cls closure - * @param hr HTTP response data - * @param reserve_pub public key of the reserve receiving the recoup + * @param rr response data */ typedef void (*TALER_EXCHANGE_RecoupResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ReservePublicKeyP *reserve_pub); + const struct TALER_EXCHANGE_RecoupResponse *rr); /** @@ -3323,7 +4078,9 @@ typedef void * the emergency recoup protocol for a given denomination. The value * of the coin will be refunded to the original customer (without fees). * - * @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 exchange_vals contribution from the exchange on the withdraw @@ -3335,13 +4092,16 @@ typedef void * 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_ExchangeWithdrawValues *exchange_vals, - const struct TALER_PlanchetMasterSecretP *ps, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls); +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); /** @@ -3364,18 +4124,47 @@ 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 recoup-refresh request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param old_coin_pub public key of the dirty coin that was credited + * @param rrr response data */ typedef void (*TALER_EXCHANGE_RecoupRefreshResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_CoinSpendPublicKeyP *old_coin_pub); + const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr); /** @@ -3385,7 +4174,9 @@ typedef void * 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 exchange_vals contribution from the exchange on the withdraw @@ -3400,7 +4191,9 @@ typedef void */ struct TALER_EXCHANGE_RecoupRefreshHandle * TALER_EXCHANGE_recoup_refresh ( - struct TALER_EXCHANGE_Handle *exchange, + 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, @@ -3476,8 +4269,16 @@ struct TALER_EXCHANGE_KycStatus */ struct TALER_ExchangeSignatureP exchange_sig; - } success; + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } ok; + /** + * KYC is required. + */ struct { @@ -3488,8 +4289,26 @@ struct TALER_EXCHANGE_KycStatus */ 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; }; @@ -3510,7 +4329,9 @@ typedef void * Run interaction with exchange to check KYC status * of a merchant. * - * @param eh exchange handle to use + * @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 @@ -3520,13 +4341,16 @@ typedef void * @return NULL on error */ struct TALER_EXCHANGE_KycCheckHandle * -TALER_EXCHANGE_kyc_check (struct TALER_EXCHANGE_Handle *eh, - 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); +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); /** @@ -3589,23 +4413,25 @@ struct TALER_EXCHANGE_KycProofHandle; /** * Run interaction with exchange to provide proof of KYC status. * - * @param eh exchange handle to use + * @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 '/' or '?'. + * 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, - const struct TALER_PaytoHashP *h_payto, - const char *logic, - const char *args, - 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); /** @@ -3683,7 +4509,8 @@ 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 @@ -3691,11 +4518,13 @@ typedef void * @return NULL on error */ struct TALER_EXCHANGE_KycWalletHandle * -TALER_EXCHANGE_kyc_wallet (struct TALER_EXCHANGE_Handle *eh, - const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_Amount *balance, - 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); /** @@ -3860,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); /** @@ -3891,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); /** @@ -3974,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); /** @@ -4028,10 +4900,24 @@ TALER_EXCHANGE_post_management_keys_cancel ( */ struct TALER_EXCHANGE_ManagementPostExtensionsData { - json_t *extensions; + 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. * @@ -4041,7 +4927,7 @@ struct TALER_EXCHANGE_ManagementPostExtensionsData typedef void (*TALER_EXCHANGE_ManagementPostExtensionsCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementPostExtensionsResponse *hr); /** * @brief Handle for a POST /management/extensions request. @@ -4064,7 +4950,7 @@ struct TALER_EXCHANGE_ManagementPostExtensionsHandle * TALER_EXCHANGE_management_post_extensions ( struct GNUNET_CURL_Context *ctx, const char *url, - struct TALER_EXCHANGE_ManagementPostExtensionsData *ped, + const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped, TALER_EXCHANGE_ManagementPostExtensionsCallback cb, void *cb_cls); @@ -4080,6 +4966,19 @@ TALER_EXCHANGE_management_post_extensions_cancel ( /** + * 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 @@ -4088,7 +4987,7 @@ TALER_EXCHANGE_management_post_extensions_cancel ( typedef void (*TALER_EXCHANGE_ManagementDrainProfitsCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementDrainResponse *hr); /** @@ -4137,6 +5036,19 @@ TALER_EXCHANGE_management_drain_profits_cancel ( /** + * 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. * * @param cls closure @@ -4145,7 +5057,7 @@ TALER_EXCHANGE_management_drain_profits_cancel ( typedef void (*TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementRevokeDenominationResponse *hr); /** @@ -4186,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 @@ -4194,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); /** @@ -4235,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); /** @@ -4288,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); /** @@ -4341,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); /** @@ -4364,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 @@ -4378,9 +5829,14 @@ TALER_EXCHANGE_management_enable_wire ( struct GNUNET_CURL_Context *ctx, const char *url, const char *payto_uri, + 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); @@ -4396,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); /** @@ -4448,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); /** @@ -4504,15 +5982,27 @@ 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 hr HTTP response data + * @param gfr HTTP response data */ typedef void (*TALER_EXCHANGE_ManagementSetGlobalFeeCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr); + const struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse *gfr); /** @@ -4564,16 +6054,28 @@ TALER_EXCHANGE_management_set_global_fees_cancel ( /** + * 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); /** @@ -4655,7 +6157,7 @@ struct TALER_EXCHANGE_ContractGetResponse */ size_t econtract_size; - } success; + } ok; } details; @@ -4682,7 +6184,8 @@ struct TALER_EXCHANGE_ContractsGetHandle; /** * Request information about a contract from the exchange. * - * @param exchange exchange handle + * @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 @@ -4690,7 +6193,8 @@ struct TALER_EXCHANGE_ContractsGetHandle; */ struct TALER_EXCHANGE_ContractsGetHandle * TALER_EXCHANGE_contract_get ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ContractDiffiePrivateP *contract_priv, TALER_EXCHANGE_ContractGetCallback cb, void *cb_cls); @@ -4726,6 +6230,7 @@ struct TALER_EXCHANGE_PurseGetResponse */ struct { + /** * Time when the purse was merged (or zero if it * was not merged). @@ -4745,7 +6250,12 @@ struct TALER_EXCHANGE_PurseGetResponse */ struct TALER_Amount balance; - } success; + /** + * Time when the purse will expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + } ok; } details; @@ -4773,7 +6283,9 @@ struct TALER_EXCHANGE_PurseGetHandle; /** * Request information about a purse from the exchange. * - * @param exchange exchange handle + * @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 @@ -4783,7 +6295,9 @@ struct TALER_EXCHANGE_PurseGetHandle; */ struct TALER_EXCHANGE_PurseGetHandle * TALER_EXCHANGE_purse_get ( - struct TALER_EXCHANGE_Handle *exchange, + 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, @@ -4835,7 +6349,7 @@ struct TALER_EXCHANGE_PurseCreateDepositResponse struct TALER_ExchangeSignatureP exchange_sig; - } success; + } ok; } details; @@ -4897,7 +6411,9 @@ struct TALER_EXCHANGE_PurseDeposit * Inform the exchange that a purse should be created * and coins deposited into it. * - * @param exchange the exchange to interact with + * @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 @@ -4913,13 +6429,15 @@ struct TALER_EXCHANGE_PurseDeposit */ struct TALER_EXCHANGE_PurseCreateDepositHandle * TALER_EXCHANGE_purse_create_with_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + 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, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], bool upload_contract, TALER_EXCHANGE_PurseCreateDepositCallback cb, void *cb_cls); @@ -4936,6 +6454,67 @@ TALER_EXCHANGE_purse_create_with_deposit_cancel ( /** + * 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 @@ -4975,7 +6554,7 @@ struct TALER_EXCHANGE_AccountMergeResponse */ struct GNUNET_TIME_Timestamp etime; - } success; + } ok; /** * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. @@ -5016,7 +6595,9 @@ struct TALER_EXCHANGE_AccountMergeHandle; * Inform the exchange that a purse should be merged * with a reserve. * - * @param exchange the exchange hosting the purse + * @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 @@ -5032,7 +6613,9 @@ struct TALER_EXCHANGE_AccountMergeHandle; */ struct TALER_EXCHANGE_AccountMergeHandle * TALER_EXCHANGE_account_merge ( - struct TALER_EXCHANGE_Handle *exchange, + 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, @@ -5078,12 +6661,12 @@ struct TALER_EXCHANGE_PurseCreateMergeResponse union { /** - * Detailed returned on #MHD_HTTP_OK. + * Details returned on #MHD_HTTP_OK. */ struct { - } success; + } ok; /** * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. @@ -5124,7 +6707,9 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle; * Inform the exchange that a purse should be created * and merged with a reserve. * - * @param exchange the exchange hosting the 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 @@ -5139,7 +6724,9 @@ struct TALER_EXCHANGE_PurseCreateMergeHandle; */ struct TALER_EXCHANGE_PurseCreateMergeHandle * TALER_EXCHANGE_purse_create_with_merge ( - struct TALER_EXCHANGE_Handle *exchange, + 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, @@ -5203,7 +6790,7 @@ struct TALER_EXCHANGE_PurseDepositResponse */ struct TALER_PrivateContractHashP h_contract_terms; - } success; + } ok; } details; }; @@ -5231,7 +6818,9 @@ struct TALER_EXCHANGE_PurseDepositHandle; * Inform the exchange that a deposit should be made into * a purse. * - * @param exchange the exchange that issued the coins + * @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 @@ -5243,12 +6832,14 @@ struct TALER_EXCHANGE_PurseDepositHandle; */ struct TALER_EXCHANGE_PurseDepositHandle * TALER_EXCHANGE_purse_deposit ( - struct TALER_EXCHANGE_Handle *exchange, + 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, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], TALER_EXCHANGE_PurseDepositCallback cb, void *cb_cls); @@ -5326,6 +6917,18 @@ struct TALER_EXCHANGE_ReserveOpenResult } 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 @@ -5367,7 +6970,9 @@ typedef void /** * Submit a request to open a reserve. * - * @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 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 @@ -5381,11 +6986,14 @@ typedef void */ struct TALER_EXCHANGE_ReservesOpenHandle * TALER_EXCHANGE_reserves_open ( - struct TALER_EXCHANGE_Handle *exchange, + 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, + 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, @@ -5396,7 +7004,7 @@ TALER_EXCHANGE_reserves_open ( * Cancel a reserve status request. This function cannot be used * on a request handle if a response is already served for it. * - * @param roh the reserve open request handle + * @param[in] roh the reserve open request handle */ void TALER_EXCHANGE_reserves_open_cancel ( @@ -5469,7 +7077,8 @@ typedef void /** * Submit a request to get the list of attestable attributes for a reserve. * - * @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 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 @@ -5478,7 +7087,8 @@ typedef void */ struct TALER_EXCHANGE_ReservesGetAttestHandle * TALER_EXCHANGE_reserves_get_attestable ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePublicKeyP *reserve_pub, TALER_EXCHANGE_ReservesGetAttestCallback cb, void *cb_cls); @@ -5530,7 +7140,7 @@ struct TALER_EXCHANGE_ReservePostAttestResult struct GNUNET_TIME_Timestamp exchange_time; /** - * Current expiration time of the reserve. + * Expiration time of the attested attributes. */ struct GNUNET_TIME_Timestamp expiration_time; @@ -5572,7 +7182,9 @@ typedef void /** * Submit a request to attest attributes about the owner of a reserve. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @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 @@ -5583,10 +7195,12 @@ typedef void */ struct TALER_EXCHANGE_ReservesAttestHandle * TALER_EXCHANGE_reserves_attest ( - struct TALER_EXCHANGE_Handle *exchange, + 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 *const*attributes, + const char *attributes[const static attributes_length], TALER_EXCHANGE_ReservesPostAttestCallback cb, void *cb_cls); @@ -5681,7 +7295,8 @@ typedef void /** * Submit a request to close a reserve. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @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 @@ -5691,7 +7306,8 @@ typedef void */ struct TALER_EXCHANGE_ReservesCloseHandle * TALER_EXCHANGE_reserves_close ( - struct TALER_EXCHANGE_Handle *exchange, + struct GNUNET_CURL_Context *ctx, + const char *url, const struct TALER_ReservePrivateKeyP *reserve_priv, const char *target_payto_uri, TALER_EXCHANGE_ReservesCloseCallback cb, diff --git a/src/include/taler_exchangedb_lib.h b/src/include/taler_exchangedb_lib.h index 45889435a..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. diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index a2e3237f9..985664c43 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-2022 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,6 +18,7 @@ * @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 @@ -28,6 +29,73 @@ #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, + + /** + * 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, +}; + +/** + * Per-coin information returned when doing a batch insert. + */ +struct TALER_EXCHANGEDB_CoinInfo +{ + /** + * Row of the coin in the known_coins table. + */ + uint64_t known_coin_id; + + /** + * Hash of the denomination, relevant on @e denom_conflict. + */ + struct TALER_DenominationHashP denom_hash; + + /** + * Hash of the age commitment, relevant on @e age_conflict. + */ + 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. @@ -107,7 +175,25 @@ struct TALER_EXCHANGEDB_DenominationKeyInformation GNUNET_NETWORK_STRUCT_BEGIN /** - * Signature of events signalling a reserve got funding. + * 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; + +}; + +/** + * Events signalling a reserve got funding. */ struct TALER_ReserveEventP { @@ -193,6 +279,7 @@ 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, @@ -212,7 +299,8 @@ 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, @@ -235,6 +323,12 @@ enum TALER_EXCHANGEDB_ReplicatedTable 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, }; @@ -299,6 +393,8 @@ struct TALER_EXCHANGEDB_TableData struct { struct TALER_PaytoHashP h_payto; + struct TALER_ReservePublicKeyP reserve_pub; + bool no_reserve_pub; char *required_checks; } legitimization_requirements; @@ -428,26 +524,33 @@ struct TALER_EXCHANGEDB_TableData struct { uint64_t shard; - uint64_t known_coin_id; - struct TALER_CoinSpendPublicKeyP coin_pub; - struct TALER_Amount amount_with_fee; + struct TALER_MerchantPublicKeyP merchant_pub; 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_MerchantPublicKeyP merchant_pub; struct TALER_PrivateContractHashP h_contract_terms; - struct TALER_CoinSpendSignatureP coin_sig; + 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; - } deposits; + bool no_policy_details; + } batch_deposits; struct { + uint64_t batch_deposit_serial_id; struct TALER_CoinSpendPublicKeyP coin_pub; - uint64_t deposit_serial_id; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_Amount amount_with_fee; + } coin_deposits; + + struct + { + 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; @@ -464,7 +567,7 @@ struct TALER_EXCHANGEDB_TableData struct { - uint64_t deposit_serial_id; + uint64_t batch_deposit_serial_id; struct TALER_WireTransferIdentifierRawP wtid_raw; } aggregation_tracking; @@ -492,7 +595,7 @@ struct TALER_EXCHANGEDB_TableData { 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_Timestamp timestamp; uint64_t reserve_out_serial_id; @@ -503,7 +606,7 @@ struct TALER_EXCHANGEDB_TableData 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_Timestamp timestamp; uint64_t rrc_serial; @@ -660,6 +763,60 @@ struct TALER_EXCHANGEDB_TableData 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; }; @@ -819,6 +976,13 @@ struct TALER_EXCHANGEDB_Reserve struct TALER_EXCHANGEDB_DenominationKeyMetaData { /** + * 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; @@ -1052,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. */ @@ -1067,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 @@ -1121,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 @@ -1169,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 @@ -1485,6 +1722,130 @@ struct TALER_EXCHANGEDB_ReserveHistory /** + * @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 @@ -1527,10 +1888,15 @@ struct TALER_EXCHANGEDB_Deposit 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; + + /** + * 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; /** * Time when this request was generated. Used, for example, to @@ -1573,16 +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; /** - * Hash over the policy data for this deposit (remains unknown to the - * Exchange). Needed for the verification of the deposit's signature + * True if @e wallet_data_hash is not in use. */ - struct TALER_ExtensionPolicyHashP h_policy; + bool no_wallet_data_hash; + }; @@ -1614,6 +1986,11 @@ struct TALER_EXCHANGEDB_DepositListEntry 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_DenominationHashP h_denom_pub; @@ -1625,20 +2002,26 @@ struct TALER_EXCHANGEDB_DepositListEntry struct TALER_AgeCommitmentHash h_age_commitment; /** - * true, if age commitment is not applicable + * Salt used to compute h_wire from the @e receiver_wire_account. */ - bool no_age_commitment; + struct TALER_WireSaltP wire_salt; /** - * Detailed information about the receiver for executing the transaction. - * URL in payto://-format. + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature */ - char *receiver_wire_account; + struct TALER_ExtensionPolicyHashP h_policy; /** - * Salt used to compute h_wire from the @e receiver_wire_account. + * 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_WireSaltP wire_salt; + struct TALER_Amount amount_with_fee; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; /** * Time when this request was generated. Used, for example, to @@ -1671,26 +2054,25 @@ struct TALER_EXCHANGEDB_DepositListEntry 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 a policy was provided with the deposit request + /** + * true, if wallet data hash is not present */ - bool has_policy; + bool no_wallet_data_hash; /** - * Hash over the policy data for this deposit (remains unknown to the - * Exchange). Needed for the verification of the deposit's signature + * True if a policy was provided with the deposit request */ - struct TALER_ExtensionPolicyHashP h_policy; + bool has_policy; /** * Has the deposit been wired? @@ -2067,9 +2449,9 @@ struct TALER_EXCHANGEDB_LinkList struct TALER_CoinSpendSignatureP orig_coin_link_sig; /** - * CS nonce, if cipher is CS. + * Session nonce, if cipher has one. */ - struct TALER_CsNonce nonce; + union GNUNET_CRYPTO_BlindSessionNonce nonce; /** * Offset that generated this coin in the refresh @@ -2245,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. * @@ -2362,29 +2766,6 @@ typedef enum GNUNET_GenericReturnValue /** - * Function called with details about - * history requests that have been made, with - * the goal of auditing the history request execution. - * - * @param cls closure - * @param rowid unique serial ID for the deposit in our DB - * @param history_fee fee paid for the request - * @param ts timestamp of the request - * @param reserve_pub reserve history was requested for - * @param reserve_sig signature approving the @a history_fee - * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop - */ -typedef enum GNUNET_GenericReturnValue -(*TALER_EXCHANGEDB_HistoryRequestCallback)( - void *cls, - uint64_t rowid, - const struct TALER_Amount *history_fee, - const struct GNUNET_TIME_Timestamp ts, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig); - - -/** * Function called with details about purse decisions that have been made, with * the goal of auditing the purse's execution. * @@ -2573,8 +2954,8 @@ struct TALER_EXCHANGEDB_KycStatus struct TALER_EXCHANGEDB_ReserveInInfo { - struct TALER_ReservePublicKeyP reserve_pub; - struct TALER_Amount balance; + 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; @@ -2673,14 +3054,24 @@ 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); /** @@ -2884,7 +3275,7 @@ typedef enum GNUNET_GenericReturnValue 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); /** @@ -2914,7 +3305,7 @@ typedef enum GNUNET_GenericReturnValue 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); /** @@ -3027,32 +3418,43 @@ typedef void uint64_t rowid, const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinSpendSignatureP *coin_sig, - const union TALER_DenominationBlindingKeyP *coin_blind, + 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 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 rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const char *payto_uri, - struct GNUNET_TIME_Timestamp deadline, - bool done); + 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); /** @@ -3101,6 +3503,46 @@ typedef void /** + * 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); + + +/** * @brief The plugin API, returned from the plugin's "init" function. * The argument given to "init" is simply a configuration handle. */ @@ -3415,28 +3857,6 @@ struct TALER_EXCHANGEDB_Plugin /** - * Insert a incoming transaction into reserves. New reserves are - * also created through this function. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param 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 - */ - enum GNUNET_DB_QueryStatus - (*reserves_in_insert)(void *cls, - 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); - - - /** * Insert a batch of incoming transaction into reserves. New reserves are * also created through this function. * @@ -3447,11 +3867,11 @@ struct TALER_EXCHANGEDB_Plugin * set to the status of the */ enum GNUNET_DB_QueryStatus - (*batch_reserves_in_insert)(void *cls, - const struct - TALER_EXCHANGEDB_ReserveInInfo *reserves, - unsigned int reserves_length, - enum GNUNET_DB_QueryStatus *results); + (*reserves_in_insert)( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results); /** @@ -3465,7 +3885,7 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*lock_nonce)(void *cls, - const struct TALER_CsNonce *nonce, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, const struct TALER_DenominationHashP *denom_pub_hash, const union TALER_EXCHANGEDB_NonceLockTargetP *target); @@ -3484,34 +3904,18 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_withdraw_info)(void *cls, const struct TALER_BlindedCoinHashP *bch, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + struct TALER_EXCHANGEDB_CollectableBlindcoin * + collectable); /** - * Perform withdraw operation, checking for sufficient balance - * and possibly persisting the withdrawal details. - * - * @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) - * @param now current time (rounded) - * @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] nonce_ok set to false if the nonce was reused - * @param[out] ruuid set to the reserve's UUID (reserves table row) - * @return query execution status + * 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. */ - enum GNUNET_DB_QueryStatus - (*do_withdraw)( - void *cls, - const struct TALER_CsNonce *nonce, - const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, - struct GNUNET_TIME_Timestamp now, - bool *found, - bool *balance_ok, - bool *nonce_ok, - uint64_t *ruuid); - /** * Perform reserve update as part of a batch withdraw operation, checking @@ -3522,8 +3926,12 @@ struct TALER_EXCHANGEDB_Plugin * @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 */ @@ -3533,8 +3941,12 @@ struct TALER_EXCHANGEDB_Plugin 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); @@ -3555,7 +3967,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*do_batch_withdraw_insert)( void *cls, - const struct TALER_CsNonce *nonce, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, struct GNUNET_TIME_Timestamp now, uint64_t ruuid, @@ -3564,6 +3976,52 @@ struct TALER_EXCHANGEDB_Plugin 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_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 @@ -3603,25 +4061,22 @@ struct TALER_EXCHANGEDB_Plugin * of the coin and possibly persisting the deposit details. * * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param deposit deposit operation details - * @param known_coin_id row of the coin in the known_coins table - * @param h_payto hash of the merchant's payto URI - * @param policy_details_serial_id (pointer to) the row ID of the policy details, maybe NULL + * @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] in_conflict set to true if the deposit conflicted + * @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_Deposit *deposit, - uint64_t known_coin_id, - const struct TALER_PaytoHashP *h_payto, - uint64_t *policy_details_serial_id, + const struct TALER_EXCHANGEDB_BatchDeposit *bd, struct GNUNET_TIME_Timestamp *exchange_timestamp, bool *balance_ok, - bool *in_conflict); + uint32_t *bad_balance_index, + bool *ctr_conflict); /** @@ -3676,7 +4131,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*cs_refreshes_reveal)( void *cls, - const struct TALER_CsNonce *nonce, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, unsigned int num_fresh_coins, struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds); @@ -3729,7 +4184,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, uint64_t reserve_out_serial_id, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t known_coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, @@ -3759,7 +4214,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, uint64_t rrc_serial, - const union TALER_DenominationBlindingKeyP *coin_bks, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, const struct TALER_CoinSpendPublicKeyP *coin_pub, uint64_t known_coin_id, const struct TALER_CoinSpendSignatureP *coin_sig, @@ -3769,11 +4224,18 @@ struct TALER_EXCHANGEDB_Plugin /** - * Get all of the transaction history associated with the specified - * reserve. + * 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 @@ -3781,32 +4243,14 @@ struct TALER_EXCHANGEDB_Plugin 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); /** - * Get truncated transaction history associated with the specified - * reserve. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub public key of the reserve - * @param[out] balance_in set to the total of inbound - * transactions in the returned history - * @param[out] balance_out set to the total of outbound - * transactions in the returned history - * @param[out] rhp set to known transaction history (NULL if reserve is unknown) - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*get_reserve_status)(void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - struct TALER_Amount *balance_in, - struct TALER_Amount *balance_out, - struct TALER_EXCHANGEDB_ReserveHistory **rhp); - - - /** * The current reserve balance of the specified reserve. * * @param cls the @e cls of this struct with the plugin-specific state @@ -3881,9 +4325,20 @@ struct TALER_EXCHANGEDB_Plugin 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 = -4, + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS = -6, + } (*ensure_coin_known)(void *cls, const struct TALER_CoinPublicInfo *coin, @@ -3893,10 +4348,30 @@ struct TALER_EXCHANGEDB_Plugin /** + * 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 @@ -3904,6 +4379,21 @@ 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. @@ -3922,6 +4412,25 @@ struct TALER_EXCHANGEDB_Plugin /** + * 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 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 + (*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); + + + /** * Check if we have the specified deposit already in the database. * * @param cls the `struct PostgresClosure` with the plugin-specific state @@ -3950,21 +4459,6 @@ struct TALER_EXCHANGEDB_Plugin /** - * Insert information about deposited coin into the database. - * Used in tests and for benchmarking. - * - * @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_Timestamp exchange_timestamp, - const struct TALER_EXCHANGEDB_Deposit *deposit); - - - /** * Insert information about refunded coin into the database. * Used in tests and for benchmarking. * @@ -3991,8 +4485,10 @@ struct TALER_EXCHANGEDB_Plugin 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_PrivateContractHashP *h_contract, + const struct + TALER_MerchantPublicKeyP *merchant_pub, + const struct + TALER_PrivateContractHashP *h_contract, TALER_EXCHANGEDB_RefundCoinCallback cb, void *cb_cls); @@ -4018,13 +4514,6 @@ struct TALER_EXCHANGEDB_Plugin char **payto_uri); -/** - * Maximum number of results we return from iterate_matching_deposits(). - * - * Limit on the number of transactions we aggregate at once. - */ -#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000 - /** * Aggregate all matching deposits for @a h_payto and * @a merchant_pub, returning the total amounts. @@ -4222,18 +4711,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[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, - 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); /** @@ -4282,6 +4788,7 @@ 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 @@ -4296,22 +4803,8 @@ struct TALER_EXCHANGEDB_Plugin struct GNUNET_TIME_Timestamp *exec_time, struct TALER_Amount *amount_with_fee, struct TALER_Amount *deposit_fee, - struct TALER_EXCHANGEDB_KycStatus *kyc); - - - /** - * Function called to insert aggregation information into the DB. - * - * @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 - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_aggregation_tracking)( - void *cls, - const struct TALER_WireTransferIdentifierRawP *wtid, - unsigned long long deposit_serial_id); + struct TALER_EXCHANGEDB_KycStatus *kyc, + enum TALER_AmlDecisionState *aml_decision); /** @@ -4481,6 +4974,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 @@ -4496,6 +4990,7 @@ struct TALER_EXCHANGEDB_Plugin 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); @@ -4586,7 +5081,8 @@ struct TALER_EXCHANGEDB_Plugin const struct TALER_ReservePublicKeyP *reserve_pub, 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, uint64_t close_request_row); @@ -4709,10 +5205,10 @@ 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); /** @@ -4788,24 +5284,6 @@ struct TALER_EXCHANGEDB_Plugin /** - * Select history requests 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_history_requests_above_serial_id)( - void *cls, - uint64_t serial_id, - TALER_EXCHANGEDB_HistoryRequestCallback cb, - void *cb_cls); - - - /** * Select purse refunds above @a serial_id in monotonically increasing * order. * @@ -4963,7 +5441,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); /** @@ -5068,10 +5547,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_by_h_blind)(void *cls, - const struct TALER_BlindedCoinHashP *bch, - struct TALER_ReservePublicKeyP *reserve_pub, - uint64_t *reserve_out_serial_id); + (*get_reserve_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id); /** @@ -5085,10 +5565,11 @@ struct TALER_EXCHANGEDB_Plugin * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*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); + (*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); /** @@ -5126,23 +5607,63 @@ struct TALER_EXCHANGEDB_Plugin /** - * 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_Timestamp start_date, - struct GNUNET_TIME_Timestamp 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); /** @@ -5154,9 +5675,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_Timestamp *last_date); + (*lookup_auditor_timestamp)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp *last_date); /** @@ -5170,10 +5692,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); /** @@ -5188,11 +5711,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_Timestamp 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); /** @@ -5208,12 +5732,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_Timestamp 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); /** @@ -5235,17 +5760,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, + 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 struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); /** @@ -5253,15 +5788,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, + 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); @@ -5526,6 +6073,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 @@ -5808,6 +6356,8 @@ struct TALER_EXCHANGEDB_Plugin * @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 @@ -5819,7 +6369,9 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_Amount *amount, struct TALER_Amount *deposited, struct TALER_PrivateContractHashP *h_contract_terms, - struct GNUNET_TIME_Timestamp *merge_timestamp); + struct GNUNET_TIME_Timestamp *merge_timestamp, + bool *purse_deleted, + bool *purse_refunded); /** @@ -5896,6 +6448,7 @@ struct TALER_EXCHANGEDB_Plugin * 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 @@ -5909,10 +6462,32 @@ struct TALER_EXCHANGEDB_Plugin 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. @@ -6028,6 +6603,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 @@ -6037,34 +6613,8 @@ struct TALER_EXCHANGEDB_Plugin struct TALER_PurseMergeSignatureP *merge_sig, struct GNUNET_TIME_Timestamp *merge_timestamp, char **partner_url, - struct TALER_ReservePublicKeyP *reserve_pub); - - - /** - * Function called to persist a signature that - * prove that the client requested an - * account history. Debits the @a history_fee from - * the reserve (if possible). - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param reserve_pub account that the history was requested for - * @param reserve_sig signature affirming the request - * @param request_timestamp when was the request made - * @param history_fee how much should the @a reserve_pub be charged for the request - * @param[out] balance_ok set to TRUE if the reserve balance - * was sufficient - * @param[out] idempotent set to TRUE if the request is already in the DB - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_history_request)( - void *cls, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Timestamp request_timestamp, - const struct TALER_Amount *history_fee, - bool *balance_ok, - bool *idempotent); + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded); /** @@ -6179,6 +6729,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 */ @@ -6187,6 +6738,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, const char *requirements, const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, uint64_t *requirement_row); @@ -6212,6 +6764,23 @@ struct TALER_EXCHANGEDB_Plugin /** + * 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. * @@ -6221,6 +6790,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 */ @@ -6232,6 +6802,7 @@ struct TALER_EXCHANGEDB_Plugin 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); @@ -6241,6 +6812,7 @@ struct TALER_EXCHANGEDB_Plugin * @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 */ @@ -6249,6 +6821,7 @@ struct TALER_EXCHANGEDB_Plugin void *cls, uint64_t requirement_row, char **requirements, + enum TALER_AmlDecisionState *aml_status, struct TALER_PaytoHashP *h_payto); @@ -6391,6 +6964,282 @@ struct TALER_EXCHANGEDB_Plugin 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 a37a7461a..1eb567f72 100644 --- a/src/include/taler_extensions.h +++ b/src/include/taler_extensions.h @@ -22,7 +22,7 @@ #define TALER_EXTENSIONS_H #include <gnunet/gnunet_util_lib.h> -#include "taler_crypto_lib.h" +#include "taler_util.h" #include "taler_json_lib.h" #include "taler_mhd_lib.h" #include "taler_extensions_policy.h" @@ -128,13 +128,13 @@ struct TALER_Extension * @brief Handler to read an extension-specific configuration in JSON * encoding and enable the extension. Must be implemented by the extension. * - * @param ext The extension object. If NULL, the configuration will only be checked. - * @param config A JSON blob + * @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)( - struct TALER_Extension *ext, - json_t *config); + const json_t *config, + struct TALER_Extension *ext); /** * @brief Handler to return the manifest of the extension in JSON encoding. @@ -162,6 +162,7 @@ struct TALER_Extension * (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, @@ -170,6 +171,7 @@ struct TALER_Extension * @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); @@ -219,12 +221,12 @@ struct TALER_Extensions * 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 + * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were found * or any particular configuration couldn't be parsed. */ enum GNUNET_GenericReturnValue @@ -259,13 +261,13 @@ TALER_extensions_parse_manifest ( */ enum GNUNET_GenericReturnValue TALER_extensions_load_manifests ( - json_t *manifests); + const json_t *manifests); /* * @brief Returns the head of the linked list of extensions. */ const struct TALER_Extensions * -TALER_extensions_get_head (); +TALER_extensions_get_head (void); /** * @brief Finds and returns a supported extension by a given type. @@ -323,7 +325,7 @@ TALER_extensions_is_enabled ( */ enum GNUNET_GenericReturnValue TALER_extensions_verify_manifests_signature ( - json_t *manifests, + const json_t *manifests, struct TALER_MasterSignatureP *extensions_sig, struct TALER_MasterPublicKeyP *master_pub); @@ -344,10 +346,6 @@ TALER_extensions_verify_manifests_signature ( * 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_AGE_RESTRICTION_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" @@ -367,7 +365,7 @@ struct TALER_AgeRestrictionConfig * @return age restriction configuration if present, otherwise NULL. */ const struct TALER_AgeRestrictionConfig * -TALER_extensions_get_age_restriction_config (); +TALER_extensions_get_age_restriction_config (void); /** * @brief Check if age restriction is enabled @@ -375,7 +373,7 @@ TALER_extensions_get_age_restriction_config (); * @return true, if age restriction is loaded, configured and enabled; otherwise false. */ bool -TALER_extensions_is_age_restriction_enabled (); +TALER_extensions_is_age_restriction_enabled (void); /** * @brief Return the age mask for age restriction @@ -383,6 +381,6 @@ TALER_extensions_is_age_restriction_enabled (); * @return configured age mask, if age restriction is loaded, configured and enabled; otherwise zero mask. */ struct TALER_AgeMask -TALER_extensions_get_age_restriction_mask (); +TALER_extensions_get_age_restriction_mask (void); #endif diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h index 1072e214b..b10c0d8a2 100644 --- a/src/include/taler_extensions_policy.h +++ b/src/include/taler_extensions_policy.h @@ -22,30 +22,35 @@ #define TALER_EXTENSIONS_POLICY_H #include <gnunet/gnunet_util_lib.h> -#include "taler_crypto_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 = 0, + TALER_PolicyFulfillmentFailure = 1, /* The policy is not yet ready due to insufficient funding. More deposits are * necessary for it to become ready . */ - TALER_PolicyFulfillmentInsufficient = 1, + TALER_PolicyFulfillmentInsufficient = 2, /* The policy is funded and ready, pending */ - TALER_PolicyFulfillmentReady = 2, + TALER_PolicyFulfillmentReady = 3, /* Policy is provably fulfilled. */ - TALER_PolicyFulfillmentSuccess = 3, + TALER_PolicyFulfillmentSuccess = 4, /* Policy fulfillment has timed out */ - TALER_PolicyFulfillmentTimeout = 4, + TALER_PolicyFulfillmentTimeout = 5, TALER_PolicyFulfillmentStateCount = TALER_PolicyFulfillmentTimeout + 1 }; @@ -68,7 +73,7 @@ struct TALER_PolicyDetails /* Content of the policy in its original JSON form */ json_t *policy_json; - /* When the deadline is meat and the policy is still in "Ready" state, + /* 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 @@ -143,6 +148,7 @@ struct TALER_PolicyFulfillmentTransactionData /* * @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 @@ -151,6 +157,7 @@ struct TALER_PolicyFulfillmentTransactionData */ enum GNUNET_GenericReturnValue TALER_extensions_create_policy_details ( + const char *currency, const json_t *policy_options, struct TALER_PolicyDetails *details, const char **error_hint); diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 7f17df030..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, 2022 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 @@ -28,6 +28,10 @@ #include "taler_util.h" #include "taler_error_codes.h" +/** + * Version of this API, for compatibility tests. + */ +#define TALER_JSON_LIB_VERSION 0x00020000 /** * Details about an encrypted contract. @@ -55,7 +59,6 @@ struct TALER_EncryptedContract */ size_t econtract_size; - }; @@ -92,18 +95,6 @@ TALER_JSON_pack_time_abs_human (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 @@ -191,19 +182,6 @@ TALER_JSON_pack_amount (const char *name, /** * Generate packer instruction for a JSON field of type - * amount. - * - * @param name name of the field to add to the object - * @param amount valid amount to pack - * @return json pack specification - */ -struct GNUNET_JSON_PackSpec -TALER_JSON_pack_amount_nbo (const char *name, - const struct TALER_AmountNBO *amount); - - -/** - * Generate packer instruction for a JSON field of type * encrypted contract. * * @param name name of the field to add to the object @@ -239,16 +217,6 @@ TALER_JSON_from_amount (const struct TALER_Amount *amount); /** - * Convert a TALER amount to a JSON object. - * - * @param amount the amount - * @return a json object describing the amount - */ -json_t * -TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO *amount); - - -/** * Provide specification to parse given JSON object to an amount. * The @a currency must be a valid pointer while the * parsing is done, a copy is not made. @@ -265,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); /** @@ -317,17 +284,33 @@ struct GNUNET_JSON_Specification TALER_JSON_spec_age_commitment (const char *name, struct TALER_AgeCommitment *age_commitment); + /** - * Provide specification to parse given JSON object to an amount - * in any currency in network byte order. + * 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 amount field in the JSON - * @param[out] r_amount where the amount has to be written - * @return spec for parsing an amount + * @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_otp_key (const char *name, + const char **otp_key); + + +/** + * 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 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_amount_any_nbo (const char *name, - struct TALER_AmountNBO *r_amount); +TALER_JSON_spec_otp_type (const char *name, + enum TALER_MerchantConfirmationAlgorithm *mca); /** @@ -380,26 +363,6 @@ TALER_JSON_spec_amount_any_nbo (const char *name, TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \ TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse) -/** - * 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 -{ - enum TALER_DenominationCipher cipher; - struct TALER_Amount value; - struct TALER_DenomFeeSet fees; - struct TALER_AgeMask age_mask; - - // hash is/should be the XOR of all SHA-512 hashes of the public keys in this - // group - struct GNUNET_HashCode hash; -}; /** * Generate a parser for a group of denominations. @@ -425,6 +388,97 @@ struct GNUNET_JSON_Specification TALER_JSON_spec_denom_pub (const char *field, struct TALER_DenominationPublicKey *pk); + +/** + * 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. @@ -435,9 +489,10 @@ TALER_JSON_spec_denom_pub (const char *field, * @return corresponding field spec */ struct GNUNET_JSON_Specification -TALER_JSON_spec_denom_pub_cipher (const char *field, - const enum TALER_DenominationCipher cipher, - struct TALER_DenominationPublicKey *pk); +TALER_JSON_spec_denom_pub_cipher ( + const char *field, + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, + struct TALER_DenominationPublicKey *pk); /** @@ -553,16 +608,18 @@ TALER_JSON_contract_hash (const json_t *json, /** - * 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); /** @@ -675,33 +732,6 @@ TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s, /** - * 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); - - -/** * Extract a string from @a object under the field @a field, but respecting * the Taler i18n rules and the language preferences expressed in @a * language_pattern. diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h index 60a7c23d2..4d0c18fa4 100644 --- a/src/include/taler_kyclogic_lib.h +++ b/src/include/taler_kyclogic_lib.h @@ -73,8 +73,12 @@ enum TALER_KYCLOGIC_KycTriggerEvent /** * Reserve is being closed by force. */ - TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 4 + TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 4, + /** + * Customer withdraws coins via age-withdraw. + */ + TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW = 5, }; @@ -214,43 +218,48 @@ typedef enum GNUNET_DB_QueryStatus * amounts involved in this type of operation * at the given account * @param ai_cls closure for @a ai - * @return NULL if no check is needed, + * @param[out] required set to NULL if no check is needed, * otherwise space-separated list of required checks + * @return transaction status */ -const char * +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); + void *ai_cls, + char **required); /** * Check if the @a requirements are now satsified for * @a h_payto account. * - * @param requirements space-spearated list of requirements + * @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 - * @return true if the KYC check was satisfied + * @param[out] satisfied set to true if the KYC check was satisfied + * @return transaction status (from @a ki) */ -bool -TALER_KYCLOGIC_check_satisfied (const char *requirements, +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); + void *ki_cls, + bool *satisfied); /** * Iterate over all thresholds that are applicable * to a particular type of @a event * - * @param event tresholds to look up + * @param event thresholds to look up * @param it function to call on each * @param it_cls closure for @a it */ @@ -293,6 +302,29 @@ TALER_KYCLOGIC_kyc_get_details ( /** + * 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 @@ -310,27 +342,6 @@ TALER_KYCLOGIC_requirements_to_logic (const char *requirements, /** - * Obtain attributes we collected about a user from a - * provider. - * - * @param provider_section configuration section of a - * provider that triggered KYC process for a user - * @param provider_user_id user ID of the user at the provider - * @param legitimization_id legitimizatin ID of a process - * of that user at the provider - * @param[out] attr_expiration set to when the @a attrs expire - * @param[out] attrs attributes we have about the user - * @return error code, #TALER_EC_NONE on success - */ -enum TALER_ErrorCode -TALER_KYCLOGIC_user_to_attributes (const char *provider_section, - const char *provider_user_id, - const char *legitimization_id, - struct GNUNET_TIME_Timestamp *attr_expiration, - json_t **attrs); - - -/** * Obtain the provider logic for a given @a name. * * @param name name of the logic or provider section @@ -346,4 +357,18 @@ TALER_KYCLOGIC_lookup_logic (const char *name, 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 index 8d86078dd..a9a4dd97a 100644 --- a/src/include/taler_kyclogic_plugin.h +++ b/src/include/taler_kyclogic_plugin.h @@ -77,8 +77,6 @@ enum TALER_KYCLOGIC_KycStatus * The provider is still checking. */ TALER_KYCLOGIC_STATUS_PROVIDER_PENDING - - = TALER_KYCLOGIC_STATUS_PROVIDER | TALER_KYCLOGIC_STATUS_PENDING, @@ -101,7 +99,13 @@ enum TALER_KYCLOGIC_KycStatus * Return code set to not update the KYC status * at all. */ - TALER_KYCLOGIC_STATUS_KEEP = 16 + TALER_KYCLOGIC_STATUS_KEEP = 16, + + /** + * We had an internal logic failure. + */ + TALER_KYCLOGIC_STATUS_INTERNAL_ERROR = 32 + }; @@ -158,6 +162,7 @@ typedef void * @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 @@ -169,6 +174,7 @@ typedef void 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); @@ -187,6 +193,7 @@ typedef void * @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 */ @@ -200,6 +207,7 @@ typedef void 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); @@ -303,7 +311,6 @@ struct TALER_KYCLOGIC_Plugin * * @param cls the @e cls of this struct with the plugin-specific state * @param pd provider configuration details - * @param url_path rest of the URL after `/kyc-webhook/$H_PAYTO/$LOGIC` * @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 @@ -316,7 +323,6 @@ struct TALER_KYCLOGIC_Plugin struct TALER_KYCLOGIC_ProofHandle * (*proof)(void *cls, const struct TALER_KYCLOGIC_ProviderDetails *pd, - const char *const url_path[], struct MHD_Connection *connection, const struct TALER_PaytoHashP *account_id, uint64_t process_row, diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index b64231352..d93bc1e14 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -27,6 +27,7 @@ #include <jansson.h> #include <microhttpd.h> #include "taler_error_codes.h" +#include "taler_util.h" #include <gnunet/gnunet_mhd_compat.h> @@ -437,7 +438,179 @@ 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) + + +/** + * Extract fixed-size base32crockford encoded data from request argument. * * Queues an error response to the connection if the parameter is missing or * invalid. @@ -446,16 +619,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) /** diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index fdc17ca55..6fae8562a 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -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); /** @@ -127,21 +140,115 @@ TALER_PQ_query_param_json (const json_t *x); /** - * Currency amount expected. + * 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 public_key pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_blind_sign_pub ( + const struct GNUNET_CRYPTO_BlindSignPublicKey *public_key); + + +/** + * Generate query parameter for a blind sign private key of variable size. + * + * @param private_key pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_blind_sign_priv ( + const struct GNUNET_CRYPTO_BlindSignPrivateKey *private_key); + + +/** + * 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 @@ -229,6 +336,117 @@ TALER_PQ_result_spec_json (const char *name, json_t **jp); +/** + * Array of blinded denomination signature expected + * + * @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_sigs where to store the result + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_array_blinded_denom_sig ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct TALER_BlindedDenominationSignature **denom_sigs); + + +/** + * 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] 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_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); + + +/** + * Blind sign public key expected. + * + * @param name name of the field in the table + * @param[out] public_key where to store the denomination signature + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blind_sign_pub ( + const char *name, + struct GNUNET_CRYPTO_BlindSignPublicKey *public_key); + + +/** + * Blind sign private key expected. + * + * @param name name of the field in the table + * @param[out] private_key where to store the denomination signature + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blind_sign_priv ( + const char *name, + struct GNUNET_CRYPTO_BlindSignPrivateKey *private_key); + #endif /* TALER_PQ_LIB_H_ */ /* end of include/taler_pq_lib.h */ diff --git a/src/include/taler_templating_lib.h b/src/include/taler_templating_lib.h index e4f3f1f1c..6af6db715 100644 --- a/src/include/taler_templating_lib.h +++ b/src/include/taler_templating_lib.h @@ -22,6 +22,23 @@ #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); /** @@ -74,6 +91,26 @@ TALER_TEMPLATING_reply (struct MHD_Connection *connection, 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. * diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index aa475bd33..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-2022 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,157 +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 - * @param age_restricted must the denomination be age restricted? - * @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, - bool age_restricted); +#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 - */ -enum GNUNET_GenericReturnValue -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); +enum TALER_TESTING_BankSystem +{ + TALER_TESTING_BS_FAKEBANK = 1, + TALER_TESTING_BS_IBAN = 2 +}; /** - * Wait for an HTTPD service 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 exchange - * 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_httpd_ready (const char *base_url); - - -/** - * Wait for the auditor 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 auditor - * to be running at - * @return 0 on success - */ -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); /** @@ -216,65 +219,17 @@ TALER_TESTING_cleanup_files_cfg (void *cls, /** - * 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 - */ -enum GNUNET_GenericReturnValue -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 - */ -enum GNUNET_GenericReturnValue -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 - */ -enum GNUNET_GenericReturnValue -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 - */ -enum GNUNET_GenericReturnValue -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 */ -enum GNUNET_GenericReturnValue -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); /** @@ -287,194 +242,13 @@ 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 - */ -enum GNUNET_GenericReturnValue -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; /** @@ -495,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, @@ -504,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); /** @@ -578,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. @@ -599,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. @@ -623,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 @@ -687,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 @@ -715,261 +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 */ enum GNUNET_GenericReturnValue -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); +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 */ -enum GNUNET_GenericReturnValue -TALER_TESTING_auditor_setup (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_filename); +int +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 */ -enum GNUNET_GenericReturnValue -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 */ -enum GNUNET_GenericReturnValue -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 */ -enum GNUNET_GenericReturnValue -TALER_TESTING_setup_with_auditor_and_exchange_cfg ( - void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg); +int +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 */ enum GNUNET_GenericReturnValue -TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_file); +TALER_TESTING_parse_coin_reference ( + const char *coin_reference, + char **cref, + unsigned int *idx); -/** - * Start the (Python) bank process. Assume the port - * is available and the database is clean. Use the "prepare - * bank" function to do such tasks. - * - * @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. - */ -struct GNUNET_OS_Process * -TALER_TESTING_run_bank (const char *config_filename, - const char *bank_url); +/* ************** Specific interpreter commands ************ */ + /** - * 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. + * Create command array terminator. * - * @param bc bank configuration of the bank - * @return the process, or NULL if the process could not - * be started. + * @return a end-command. */ -struct TALER_TESTING_LibeufinServices -TALER_TESTING_run_libeufin (const struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_end (void); /** - * Runs the Fakebank by guessing / extracting the portnumber - * from the base URL. + * Set variable to command as side-effect of + * running a command. * - * @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 name name of the variable to set + * @param cmd command to set to variable when run + * @return modified command */ -struct TALER_FAKEBANK_Handle * -TALER_TESTING_run_fakebank (const char *bank_url, - const char *currency); +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_var (const char *name, + struct TALER_TESTING_Command cmd); /** - * Prepare the bank execution. Check if the port is available - * and reset database. + * Launch GNU Taler setup. * - * @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 config_file configuration file to use + * @param ... NULL-terminated (const char *) arguments to pass to taler-benchmark-setup.sh + * @return the command. */ -enum GNUNET_GenericReturnValue -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_system_start ( + const char *label, + const char *config_file, + ...); -/** - * Prepare the Nexus execution. Check if the port is available - * and delete old database. - * - * @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. - */ -enum GNUNET_GenericReturnValue -TALER_TESTING_prepare_nexus (const char *config_filename, - int reset_db, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); /** - * Look for substring in a programs' name. + * Connects to the exchange. * - * @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 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. */ -enum GNUNET_GenericReturnValue -TALER_TESTING_has_in_name (const char *prog, - const char *marker); +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); /** - * Parse reference to a coin. + * Connects to the auditor. * - * @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 + * @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. */ -enum GNUNET_GenericReturnValue -TALER_TESTING_parse_coin_reference ( - const char *coin_reference, - char **cref, - unsigned int *idx); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_auditor ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + bool load_auditor_keys); /** - * Compare @a h1 and @a h2. + * Runs the Fakebank in-process by guessing / extracting the portnumber + * from the base URL. * - * @param h1 a history entry - * @param h2 a history entry - * @return 0 if @a h1 and @a h2 are equal + * @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_history_entry_cmp ( - const struct TALER_EXCHANGE_ReserveHistoryEntry *h1, - const struct TALER_EXCHANGE_ReserveHistoryEntry *h2); - - -/* ************** 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); /** @@ -1086,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); /** @@ -1119,46 +833,6 @@ TALER_TESTING_cmd_deposit_confirmation_with_retry ( /** - * 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); - - -/** * Create /admin/add-incoming command. * * @param label command label. @@ -1225,6 +899,32 @@ 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. @@ -1345,10 +1045,39 @@ TALER_TESTING_cmd_withdraw_amount (const char *label, /** + * 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 @@ -1359,14 +1088,57 @@ TALER_TESTING_cmd_withdraw_amount (const char *label, * @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_batch_withdraw (const char *label, - const char *reserve_reference, - uint8_t age, - unsigned int expected_response_code, - const char *amount, - ...); +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 @@ -1379,7 +1151,7 @@ TALER_TESTING_cmd_batch_withdraw (const char *label, * @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. @@ -1426,24 +1198,6 @@ TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd); /** - * Create a "wire" 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. - * @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); - - -/** * Create a GET "reserves" command. * * @param label the command label. @@ -1493,7 +1247,7 @@ TALER_TESTING_cmd_reserve_poll_finish (const char *label, /** - * Create a POST "/reserves/$RID/history" command. + * Create a GET "/reserves/$RID/history" command. * * @param label the command label. * @param reserve_reference reference to the reserve to check. @@ -1509,19 +1263,19 @@ TALER_TESTING_cmd_reserve_history (const char *label, /** - * Create a POST "/reserves/$RID/status" command. + * Create a GET "/coins/$COIN_PUB/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 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_reserve_status (const char *label, - const char *reserve_reference, - const char *expected_balance, - unsigned int expected_response_code); +TALER_TESTING_cmd_coin_history (const char *label, + const char *coin_reference, + const char *expected_balance, + unsigned int expected_response_code); /** @@ -2065,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. @@ -2144,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. @@ -2173,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 @@ -2213,7 +1894,7 @@ 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_Timestamp exchange_timestamp, @@ -2238,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; @@ -2517,7 +2198,6 @@ TALER_TESTING_cmd_check_kyc_get (const char *label, * @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 */ @@ -2527,20 +2207,31 @@ TALER_TESTING_cmd_proof_kyc_oauth2 ( const char *payment_target_reference, const char *logic_section, const char *code, - const char *state, unsigned int expected_response_code); /** * Starts a fake OAuth 2.0 service on @a port for testing - * KYC processes. + * 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 (const char *label, - uint16_t port); +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 + * KYC processes. + * + * @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 ****************** */ @@ -2568,6 +2259,21 @@ TALER_TESTING_cmd_purse_create_with_deposit ( /** + * 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). * @@ -2679,6 +2385,114 @@ TALER_TESTING_cmd_purse_deposit_coins ( ...); +/** + * 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 ********* */ @@ -2835,6 +2649,15 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, */ #define TALER_TESTING_SIMPLE_TRAITS(op) \ op (bank_row, const uint64_t) \ + 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) \ @@ -2850,56 +2673,61 @@ TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, 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 (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 (legi_requirement_row, 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 (batch_cmds, struct TALER_TESTING_Command *) \ + op (batch_cmds, struct TALER_TESTING_Command) \ op (uuid, const struct GNUNET_Uuid) \ 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 (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) \ +#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 (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 (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 TALER_DenominationBlindingKeyP) - + 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 1580f3dca..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). @@ -191,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 @@ -222,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 @@ -243,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 @@ -278,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 @@ -362,6 +501,20 @@ TALER_payto_get_method (const char *payto_uri); /** + * 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 input a payto://-URI + * @return normalized URI, or NULL if @a input was not well-formed + */ +char * +TALER_payto_normalize (const char *input); + + +/** * Obtain the account name from a payto URL. * * @param payto an x-taler-bank payto URL @@ -493,6 +646,33 @@ 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 @@ -529,17 +709,35 @@ 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, allocated by GNUNET_malloc. + * @return String representation of the age mask. * Can be used as value in the TALER config. */ -char * +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" }. * @@ -551,4 +749,81 @@ 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 |