diff options
Diffstat (limited to 'src/include')
29 files changed, 22882 insertions, 8475 deletions
diff --git a/src/include/.gitignore b/src/include/.gitignore new file mode 100644 index 000000000..beba883b6 --- /dev/null +++ b/src/include/.gitignore @@ -0,0 +1 @@ +taler_signatures.h diff --git a/src/include/Makefile.am b/src/include/Makefile.am index b8ea0d175..45d74ab8e 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -2,25 +2,34 @@ talerincludedir = $(includedir)/taler talerinclude_HEADERS = \ - platform.h \ + 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 \ taler_crypto_lib.h \ taler_curl_lib.h \ + taler_dbevents.h \ taler_error_codes.h \ taler_exchange_service.h \ taler_exchangedb_lib.h \ taler_exchangedb_plugin.h \ + taler_extensions.h \ + taler_extensions_policy.h \ taler_fakebank_lib.h \ + taler_kyclogic_lib.h \ + taler_kyclogic_plugin.h \ taler_json_lib.h \ taler_testing_lib.h \ taler_util.h \ taler_mhd_lib.h \ taler_pq_lib.h \ - taler_signatures.h + taler_signatures.h \ + taler_sq_lib.h \ + taler_templating_lib.h \ + taler_twister_testing_lib.h EXTRA_DIST = \ backoff.h \ diff --git a/src/include/gettext.h b/src/include/gettext.h new file mode 100644 index 000000000..458512657 --- /dev/null +++ b/src/include/gettext.h @@ -0,0 +1,71 @@ +/* Convenience header for conditional use of GNU <libintl.h>. + Copyright Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +#include <libintl.h> + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of <locale.h> a NOP. We don't include <libintl.h> + as well because people using "gettext.h" will not include <libintl.h>, + and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> + is GNUNET_OK. */ +#if defined(__sun) +#include <locale.h> +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +#define gettext(Msgid) ((const char *) (Msgid)) +#define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +#define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +#define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +#define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +#define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +/* slight modification here to avoid warnings: generate GNUNET_NO code, + not even the cast... */ +#define textdomain(Domainname) +#define bindtextdomain(Domainname, Dirname) +#define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/src/include/platform.h b/src/include/platform.h index ec2f70768..db04cb972 100644 --- a/src/include/platform.h +++ b/src/include/platform.h @@ -20,18 +20,21 @@ * 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 + #if (GNUNET_EXTRA_LOGGING >= 1) #define VERBOSE(cmd) cmd @@ -42,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 @@ -63,6 +63,237 @@ is needed for performance reasons. */ #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 + +#ifndef EXIT_NOTRUNNING +#define EXIT_NOTRUNNING 7 +#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 63c5dba40..937238d15 100644 --- a/src/include/taler_amount_lib.h +++ b/src/include/taler_amount_lib.h @@ -18,9 +18,16 @@ * @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 +#include <stdint.h> +#include "gnunet/gnunet_common.h" + #ifdef __cplusplus extern "C" { @@ -64,6 +71,11 @@ extern "C" */ #define TALER_AMOUNT_FRAC_LEN 8 +/** + * Maximum legal 'value' for an amount, based on IEEE double (for JavaScript compatibility). + */ +#define TALER_AMOUNT_MAX_VALUE (1LLU << 52) + GNUNET_NETWORK_STRUCT_BEGIN @@ -116,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 @@ -123,7 +145,7 @@ struct TALER_Amount * @return #GNUNET_OK if the string is a valid monetary amount specification, * #GNUNET_SYSERR if it is invalid. */ -int +enum GNUNET_GenericReturnValue TALER_string_to_amount (const char *str, struct TALER_Amount *amount); @@ -137,7 +159,7 @@ TALER_string_to_amount (const char *str, * @return #GNUNET_OK if the string is a valid amount specification, * #GNUNET_SYSERR if it is invalid. */ -int +enum GNUNET_GenericReturnValue TALER_string_to_amount_nbo (const char *str, struct TALER_AmountNBO *amount_nbo); @@ -150,22 +172,45 @@ TALER_string_to_amount_nbo (const char *str, * @return #GNUNET_OK if @a cur is a valid currency specification, * #GNUNET_SYSERR if it is invalid. */ -int -TALER_amount_get_zero (const char *cur, +enum GNUNET_GenericReturnValue +TALER_amount_set_zero (const char *cur, struct TALER_Amount *amount); /** + * Test if the given @a amount is zero. + * + * @param amount amount to compare to zero + * @return true if the amount is zero, + * false if it is non-zero or invalid + */ +bool +TALER_amount_is_zero (const struct TALER_Amount *amount); + + +/** * Test if the given amount is valid. * * @param amount amount to check * @return #GNUNET_OK if @a amount is valid */ -int +enum GNUNET_GenericReturnValue TALER_amount_is_valid (const struct TALER_Amount *amount); /** + * Test if the given amount is in the given currency + * + * @param amount amount to check + * @param currency currency to check for + * @return #GNUNET_OK if @a amount is in @a currency + */ +enum GNUNET_GenericReturnValue +TALER_amount_is_currency (const struct TALER_Amount *amount, + const char *currency); + + +/** * Convert amount from host to network representation. * * @param[out] res where to store amount in network representation @@ -206,6 +251,24 @@ TALER_amount_cmp (const struct TALER_Amount *a1, /** + * Compare the value/fraction of two amounts. Does not compare the currency. + * Comparing amounts of different currencies will cause the program to abort(). + * If unsure, check with #TALER_amount_cmp_currency() first to be sure that + * the currencies of the two amounts are identical. NBO variant. + * + * @param a1 first amount + * @param a2 second amount + * @return result of the comparison + * -1 if `a1 < a2` + * 1 if `a1 > a2` + * 0 if `a1 == a2`. + */ +int +TALER_amount_cmp_nbo (const struct TALER_AmountNBO *a1, + const struct TALER_AmountNBO *a2); + + +/** * Test if @a a1 and @a a2 are the same currency. * * @param a1 amount to test @@ -214,7 +277,7 @@ TALER_amount_cmp (const struct TALER_Amount *a1, * #GNUNET_NO if the currencies are different * #GNUNET_SYSERR if either amount is invalid */ -int +enum GNUNET_GenericReturnValue TALER_amount_cmp_currency (const struct TALER_Amount *a1, const struct TALER_Amount *a2); @@ -228,7 +291,7 @@ TALER_amount_cmp_currency (const struct TALER_Amount *a1, * #GNUNET_NO if the currencies are different * #GNUNET_SYSERR if either amount is invalid */ -int +enum GNUNET_GenericReturnValue TALER_amount_cmp_currency_nbo (const struct TALER_AmountNBO *a1, const struct TALER_AmountNBO *a2); @@ -314,6 +377,32 @@ TALER_amount_divide (struct TALER_Amount *result, const struct TALER_Amount *dividend, uint32_t divisor); +/** + * Divide one amount by another. Note that this function + * may introduce a rounding error. It rounds down. + * + * @param dividend amount to divide + * @param divisor by what to divide, must be positive + * @return @a dividend / @a divisor, rounded down. -1 on currency mismatch, + * INT_MAX for division by zero + */ +int +TALER_amount_divide2 (const struct TALER_Amount *dividend, + const struct TALER_Amount *divisor); + + +/** + * Multiply an @a amount by a @ factor. + * + * @param[out] result where to store @a amount * @a factor + * @param amount amount to multiply + * @param factor factor by which to multiply + */ +enum TALER_AmountArithmeticResult +TALER_amount_multiply (struct TALER_Amount *result, + const struct TALER_Amount *amount, + uint32_t factor); + /** * Normalize the given amount. @@ -323,7 +412,7 @@ TALER_amount_divide (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); @@ -361,7 +450,7 @@ TALER_amount2s (const struct TALER_Amount *amount); * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary, * #GNUNET_SYSERR if the amount or currency or @a round_unit was invalid */ -int +enum GNUNET_GenericReturnValue TALER_amount_round_down (struct TALER_Amount *amount, const struct TALER_Amount *round_unit); 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 27959a889..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-2020 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,19 +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 timestamp timestamp when the contract was finalized, must not be too far in the future + * @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 @@ -253,20 +310,25 @@ typedef void */ struct TALER_AUDITOR_DepositConfirmationHandle * TALER_AUDITOR_deposit_confirmation ( - struct TALER_AUDITOR_Handle *auditor, - const struct GNUNET_HashCode *h_wire, - const struct GNUNET_HashCode *h_contract_terms, - struct GNUNET_TIME_Absolute timestamp, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_Amount *amount_without_fee, - const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendPublicKeyP *coin_pubs[static num_coins], + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_ExchangePublicKeyP *exchange_pub, const struct TALER_ExchangeSignatureP *exchange_sig, const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute ep_start, - struct GNUNET_TIME_Absolute ep_expire, - struct GNUNET_TIME_Absolute ep_end, + struct GNUNET_TIME_Timestamp ep_start, + struct GNUNET_TIME_Timestamp ep_expire, + struct GNUNET_TIME_Timestamp ep_end, const struct TALER_MasterSignatureP *master_sig, TALER_AUDITOR_DepositConfirmationResultCallback cb, void *cb_cls); @@ -283,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 /exchagnes. - * - * @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 9a7f6ed7a..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-2018 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,43 +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_denomination_info() - * - * @param cls closure - * @param issue issuing information with value, fees and other info about the denomination. - * - * @return sets the return value of select_denomination_info(), - * #GNUNET_OK to continue, - * #GNUNET_NO to stop processing further rows - * #GNUNET_SYSERR or other values on error. - */ -typedef int -(*TALER_AUDITORDB_DenominationInfoDataCallback)( - void *cls, - const struct TALER_DenominationKeyValidityPS *issue); - - -/** * Function called with the results of select_historic_denom_revenue() * * @param cls closure @@ -76,11 +45,11 @@ typedef int * #GNUNET_NO to stop processing further rows * #GNUNET_SYSERR or other values on error. */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_AUDITORDB_HistoricDenominationRevenueDataCallback)( void *cls, - const struct GNUNET_HashCode *denom_pub_hash, - struct GNUNET_TIME_Absolute revenue_timestamp, + const struct TALER_DenominationHashP *denom_pub_hash, + struct GNUNET_TIME_Timestamp revenue_timestamp, const struct TALER_Amount *revenue_balance, const struct TALER_Amount *loss_balance); @@ -98,262 +67,210 @@ typedef int * #GNUNET_NO to stop processing further rows * #GNUNET_SYSERR or other values on error. */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_AUDITORDB_HistoricReserveRevenueDataCallback)( void *cls, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, const struct TALER_Amount *reserve_profits); /** - * Structure for remembering the wire auditor's progress over the - * various tables and (auditor) transactions. - */ -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_Absolute last_timestamp; - - /** - * reserves_close uuid until which we have checked - * reserve closures. - */ - uint64_t last_reserve_close_uuid; -}; - - -/** - * Structure for remembering the wire auditor's progress over the - * various tables and (auditor) transactions per wire account. + * Information about a signing key of an exchange. */ -struct TALER_AUDITORDB_WireAccountProgressPoint +struct TALER_AUDITORDB_ExchangeSigningKey { - /** - * 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 + * When does @e exchange_pub start to be used? */ - uint64_t last_wire_out_serial_id; + struct GNUNET_TIME_Timestamp ep_start; -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing reserves. - */ -struct TALER_AUDITORDB_ProgressPointReserve -{ /** - * serial ID of the last reserve_in transfer the auditor processed + * When will the exchange stop signing with @e exchange_pub? */ - uint64_t last_reserve_in_serial_id; + struct GNUNET_TIME_Timestamp ep_expire; /** - * serial ID of the last reserve_out the auditor processed + * When does the signing key expire (for legal disputes)? */ - uint64_t last_reserve_out_serial_id; + struct GNUNET_TIME_Timestamp ep_end; /** - * serial ID of the last recoup entry the auditor processed when - * considering reserves. + * What is the public offline signing key this is all about? */ - uint64_t last_reserve_recoup_serial_id; + struct TALER_ExchangePublicKeyP exchange_pub; /** - * serial ID of the last reserve_close - * entry the auditor processed. + * Signature by the offline master key affirming the above. */ - uint64_t last_reserve_close_serial_id; - + struct TALER_MasterSignatureP master_sig; }; /** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing reserves. + * Information about a deposit confirmation we received from + * a merchant. */ -struct TALER_AUDITORDB_ProgressPointDepositConfirmation +struct TALER_AUDITORDB_DepositConfirmation { + /** - * serial ID of the last deposit_confirmation the auditor processed + * Hash over the contract for which this deposit is made. */ - uint64_t last_deposit_confirmation_serial_id; - - -}; - - -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing aggregations. - */ -struct TALER_AUDITORDB_ProgressPointAggregation -{ + struct TALER_PrivateContractHashP h_contract_terms; /** - * serial ID of the last prewire transfer the auditor processed + * Hash over the policy extension for the deposit. */ - uint64_t last_wire_out_serial_id; -}; - + struct TALER_ExtensionPolicyHashP h_policy; -/** - * Structure for remembering the auditor's progress over the various - * tables and (auditor) transactions when analyzing coins. - */ -struct TALER_AUDITORDB_ProgressPointCoin -{ /** - * serial ID of the last withdraw the auditor processed + * Hash over the wiring information of the merchant. */ - uint64_t last_withdraw_serial_id; + struct TALER_MerchantWireHashP h_wire; /** - * serial ID of the last deposit the auditor processed + * Time when this deposit confirmation was generated by the exchange. */ - uint64_t last_deposit_serial_id; + struct GNUNET_TIME_Timestamp exchange_timestamp; /** - * serial ID of the last refresh the auditor processed + * How much time does the @e merchant have to issue a refund + * request? Zero if refunds are not allowed. After this time, the + * coin cannot be refunded. Note that the wire transfer will not be + * performed by the exchange until the refund deadline. This value + * is taken from the original deposit request. */ - uint64_t last_melt_serial_id; + struct GNUNET_TIME_Timestamp refund_deadline; /** - * serial ID of the last refund the auditor processed + * How much time does the @e exchange have to wire the funds? */ - uint64_t last_refund_serial_id; + struct GNUNET_TIME_Timestamp wire_deadline; /** - * Serial ID of the last recoup operation the auditor processed. + * Amount to be deposited, excluding fee. Calculated from the + * amount with fee and the fee from the deposit request. */ - uint64_t last_recoup_serial_id; + struct TALER_Amount total_without_fee; /** - * Serial ID of the last recoup-of-refresh operation the auditor processed. + * Length of the @e coin_pubs and @e coin_sigs arrays. */ - uint64_t last_recoup_refresh_serial_id; - -}; + unsigned int num_coins; - -/** - * Information about a signing key of an exchange. - */ -struct TALER_AUDITORDB_ExchangeSigningKey -{ /** - * Public master key of the exchange that certified @e master_sig. + * Array of the coin public keys involved in the + * batch deposit operation. */ - struct TALER_MasterPublicKeyP master_public_key; + const struct TALER_CoinSpendPublicKeyP *coin_pubs; /** - * When does @e exchange_pub start to be used? + * Array of coin deposit signatures from the deposit operation. */ - struct GNUNET_TIME_Absolute ep_start; + const struct TALER_CoinSpendSignatureP *coin_sigs; /** - * When will the exchange stop signing with @e exchange_pub? + * The Merchant's public key. Allows the merchant to later refund + * the transaction or to inquire about the wire transfer identifier. */ - struct GNUNET_TIME_Absolute ep_expire; + struct TALER_MerchantPublicKeyP merchant; /** - * When does the signing key expire (for legal disputes)? + * Signature from the exchange of type + * #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. */ - struct GNUNET_TIME_Absolute ep_end; + struct TALER_ExchangeSignatureP exchange_sig; /** - * What is the public offline signing key this is all about? + * Public signing key from the exchange matching @e exchange_sig. */ struct TALER_ExchangePublicKeyP exchange_pub; /** - * Signature by the offline master key affirming the above. + * Exchange master signature over @e exchange_sig. */ struct TALER_MasterSignatureP master_sig; + }; /** - * Information about a deposit confirmation we received from - * a merchant. + * Balance values for a reserve (or all reserves). */ -struct TALER_AUDITORDB_DepositConfirmation +struct TALER_AUDITORDB_ReserveFeeBalance { - /** - * Hash over the contract for which this deposit is made. + * Remaining funds. */ - struct GNUNET_HashCode h_contract_terms; + struct TALER_Amount reserve_balance; /** - * Hash over the wiring information of the merchant. + * Losses from operations that should not have + * happened (e.g. negative balance). */ - struct GNUNET_HashCode h_wire; + struct TALER_Amount reserve_loss; /** - * Time when this confirmation was generated. + * Fees charged for withdraw. */ - struct GNUNET_TIME_Absolute timestamp; + struct TALER_Amount withdraw_fee_balance; /** - * How much time does the @e merchant have to issue a refund - * request? Zero if refunds are not allowed. After this time, the - * coin cannot be refunded. Note that the wire transfer will not be - * performed by the exchange until the refund deadline. This value - * is taken from the original deposit request. + * Fees charged for closing. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct TALER_Amount close_fee_balance; /** - * Amount to be deposited, excluding fee. Calculated from the - * amount with fee and the fee from the deposit request. + * Fees charged for purse creation. */ - struct TALER_Amount amount_without_fee; + struct TALER_Amount purse_fee_balance; /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). + * Opening fees charged. */ - struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_Amount open_fee_balance; /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. + * History fees charged. */ - struct TALER_MerchantPublicKeyP merchant; + struct TALER_Amount history_fee_balance; +}; + +/** + * Balance data for denominations in circulation. + */ +struct TALER_AUDITORDB_DenominationCirculationData +{ /** - * Signature from the exchange of type - * #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. + * Amount of outstanding coins in circulation. */ - struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_Amount denom_balance; /** - * Public signing key from the exchange matching @e exchange_sig. + * Amount lost due coins illicitly accepted (effectively, a + * negative @a denom_balance). */ - struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_Amount denom_loss; /** - * Exchange master signature over @e exchange_sig. + * Total amount that could still be theoretically lost in the future due to + * recoup operations. (Total put into circulation minus @e recoup_loss). */ - struct TALER_MasterSignatureP master_sig; + struct TALER_Amount denom_risk; /** - * Master public key of the exchange corresponding to @e master_sig. - * Identifies the exchange this is about. + * Amount lost due to recoups. */ - struct TALER_MasterPublicKeyP master_public_key; + struct TALER_Amount recoup_loss; + /** + * Number of coins of this denomination that the exchange signed into + * existence. + */ + uint64_t num_issued; }; @@ -364,8 +281,9 @@ struct TALER_AUDITORDB_DepositConfirmation * @param cls closure * @param serial_id location of the @a dc in the database * @param dc the deposit confirmation itself + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop iterating */ -typedef void +typedef enum GNUNET_GenericReturnValue (*TALER_AUDITORDB_DepositConfirmationCallback)( void *cls, uint64_t serial_id, @@ -373,9 +291,39 @@ typedef void /** - * Handle for one session with the database. + * Function called on deposits that are past their due date + * and have not yet seen a wire transfer. + * + * @param cls closure + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline + */ +typedef void +(*TALER_AUDITORDB_WireMissingCallback)( + void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline); + + +/** + * Function called on expired purses. + * + * @param cls closure + * @param purse_pub public key of the purse + * @param balance amount of money in the purse + * @param expiration_date when did the purse expire? + * @return #GNUNET_OK to continue to iterate */ -struct TALER_AUDITORDB_Session; +typedef enum GNUNET_GenericReturnValue +(*TALER_AUDITORDB_ExpiredPurseCallback)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp expiration_date); /** @@ -400,14 +348,58 @@ struct TALER_AUDITORDB_Plugin char *library_name; /** - * Get the thread-local database-handle. - * Connect to the db if the connection does not exist yet. + * Fully connect to the db if the connection does not exist yet + * and check that there is no transaction currently running. * * @param cls the @e cls of this struct with the plugin-specific state - * @param the database connection, or NULL on error + * @return #GNUNET_OK on success + * #GNUNET_NO if we rolled back an earlier transaction + * #GNUNET_SYSERR if we have no DB connection */ - struct TALER_AUDITORDB_Session * - (*get_session) (void *cls); + enum GNUNET_GenericReturnValue + (*preflight)(void *cls); + + + /** + * 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); /** @@ -421,54 +413,52 @@ struct TALER_AUDITORDB_Plugin * used when restarting the auditor * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ - int - (*drop_tables) (void *cls, - int drop_exchangelist); + enum GNUNET_GenericReturnValue + (*drop_tables)(void *cls, + bool drop_exchangelist); /** * Create the necessary tables if they are not present * * @param cls the @e cls of this struct with the plugin-specific state + * @param support_partitions true to support partitioning + * @param num_partitions number of partitions to use * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ - int - (*create_tables) (void *cls); + enum GNUNET_GenericReturnValue + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); /** * Start a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @return #GNUNET_OK on success */ - int - (*start) (void *cls, - struct TALER_AUDITORDB_Session *session); + enum GNUNET_GenericReturnValue + (*start)(void *cls); /** * Commit a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*commit)(void *cls, - struct TALER_AUDITORDB_Session *session); + (*commit)(void *cls); /** * Abort/rollback a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use */ void - (*rollback) (void *cls, - struct TALER_AUDITORDB_Session *session); + (*rollback) (void *cls); /** @@ -479,263 +469,26 @@ struct TALER_AUDITORDB_Plugin * @return #GNUNET_OK on success, * #GNUNET_SYSERR on DB errors */ - int - (*gc) (void *cls); - - - /** - * Insert information about an exchange this auditor will be auditing. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @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, - struct TALER_AUDITORDB_Session *session, - 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 session connection to the database - * @param master_pub master public key of the exchange - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*delete_exchange)(void *cls, - struct TALER_AUDITORDB_Session *session, - 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 session connection to the database - * @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, - struct TALER_AUDITORDB_Session *session, - 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 session connection to the database - * @param sk signing key information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_exchange_signkey)( - void *cls, - struct TALER_AUDITORDB_Session *session, - 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 session connection to the database - * @param dc deposit confirmation information to store - * @return query result status - */ - enum GNUNET_DB_QueryStatus - (*insert_deposit_confirmation)( - void *cls, - struct TALER_AUDITORDB_Session *session, - 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 session connection to the database - * @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, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_public_key, - uint64_t start_id, - TALER_AUDITORDB_DepositConfirmationCallback cb, - void *cb_cls); - - - /** - * Insert information about a denomination key and in particular - * the properties (value, fees, expiration times) the coins signed - * with this key have. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param issue issuing information with value, fees and other info about the denomination - * @return status of database operation - */ - enum GNUNET_DB_QueryStatus - (*insert_denomination_info)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_DenominationKeyValidityPS *issue); - - - /** - * Get information about denomination keys of a particular exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param cb function to call with the results - * @param cb_cls closure for @a cb - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*select_denomination_info)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - TALER_AUDITORDB_DenominationInfoDataCallback 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 session connection to use - * @param master_pub master key of the exchange - * @param ppc where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_coin)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); - - - /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param ppc where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_coin)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointCoin *ppc); - - - /** - * Get information about the progress of the auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param[out] ppc set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_auditor_progress_coin)(void *cls, - struct TALER_AUDITORDB_Session *session, - 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 session connection to use - * @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, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointReserve *ppr); - + enum GNUNET_GenericReturnValue + (*gc)(void *cls); - /** - * 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 session connection to use - * @param master_pub master key of the exchange - * @param ppr where is the auditor in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_auditor_progress_reserve)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointReserve *ppr); - - - /** - * Get information about the progress of the auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @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, - struct TALER_AUDITORDB_Session *session, - 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 session connection to use - * @param master_pub master key of the exchange - * @param ppdc where is the auditor in processing + * @param progress_key name of the progress indicator + * @param progress_offset offset until which we have made progress + * @param ... NULL terminated list of additional key-value pairs to insert * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_deposit_confirmation)( + (*insert_auditor_progress)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + const char *progress_key, + uint64_t progress_offset, + ...); /** @@ -743,213 +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 session connection to use - * @param master_pub master key of the exchange - * @param ppdc where is the auditor in processing + * @param progress_key name of the progress indicator + * @param progress_offset offset until which we have made progress + * @param ... NULL terminated list of additional key-value pairs to update * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_auditor_progress_deposit_confirmation)( + (*update_auditor_progress)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + const char *progress_key, + uint64_t progress_offset, + ...); /** * Get information about the progress of the auditor. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param[out] ppdc set to where the auditor is in processing + * @param progress_key name of the progress indicator + * @param[out] progress_offset set to offset until which we have made progress, set to 0 if key was not found + * @param ... NULL terminated list of additional key-value pairs to fetch * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_auditor_progress_deposit_confirmation)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointDepositConfirmation *ppdc); + (*get_auditor_progress)(void *cls, + const char *progress_key, + uint64_t *progress_offset, + ...); /** - * Insert information about the auditor's progress with an exchange's - * data. + * Insert information about a balance tracked by the auditor. There must not be an + * existing record. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param ppa where is the auditor in processing + * @param balance_key key of the balance to store + * @param balance_value value to store + * @param ... NULL terminated list of additional key-value pairs to insert * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_auditor_progress_aggregation)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointAggregation *ppa); + (*insert_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_value, + ...); /** - * Update information about the progress of the auditor. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @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, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_ProgressPointAggregation *ppa); - - - /** - * Get information about the progress of the auditor. + * Insert information about a balance tracked by the auditor. Destructively updates an + * existing record, which must already exist. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param[out] ppa set to where the auditor is in processing + * @param balance_key key of the balance to store + * @param balance_amount value to store + * @param ... NULL terminated list of additional key-value pairs to update * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_auditor_progress_aggregation)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_ProgressPointAggregation *ppa); + (*update_balance)(void *cls, + const char *balance_key, + const struct TALER_Amount *balance_amount, + ...); /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * Get summary information about balance tracked by the auditor. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @param in_wire_off how far are we in the incoming wire transaction history - * @param out_wire_off how far are we in the outgoing wire transaction history + * @param balance_key key of the balance to store + * @param[out] balance_value set to amount stored under @a balance_key, set to invalid amount (all zero) if key was not found + * @param ... NULL terminated list of additional key-value pairs to fetch * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_auditor_account_progress)( - void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t in_wire_off, - uint64_t out_wire_off); + (*get_balance)(void *cls, + const char *balance_key, + struct TALER_Amount *balance_value, + ...); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * Insert information about a signing key of the exchange. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @param in_wire_off how far are we in the incoming wire transaction history - * @param out_wire_off how far are we in the outgoing wire transaction history - * @return transaction status code + * @param sk signing key information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*update_wire_auditor_account_progress)( + (*insert_exchange_signkey)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - const struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t in_wire_off, - uint64_t out_wire_off); + const struct TALER_AUDITORDB_ExchangeSigningKey *sk); /** - * Get information about the progress of the wire auditor. + * Insert information about a deposit confirmation into the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param[out] pp where is the auditor in processing - * @param[out] in_wire_off how far are we in the incoming wire transaction history - * @param[out] out_wire_off how far are we in the outgoing wire transaction history - * @return transaction status code + * @param dc deposit confirmation information to store + * @return query result status */ enum GNUNET_DB_QueryStatus - (*get_wire_auditor_account_progress)( + (*insert_deposit_confirmation)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const char *account_name, - struct TALER_AUDITORDB_WireAccountProgressPoint *pp, - uint64_t *in_wire_off, - uint64_t *out_wire_off); + const struct TALER_AUDITORDB_DepositConfirmation *dc); /** - * Insert information about the wire auditor's progress with an exchange's - * data. + * Get information about deposit confirmations from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @return transaction status code + * @param start_id row/serial ID where to start the iteration (0 from + * the start, exclusive, i.e. serial_ids must start from 1) + * @param return_suppressed should suppressed rows be returned anyway? + * @param cb function to call with results + * @param cb_cls closure for @a cb + * @return query result status */ enum GNUNET_DB_QueryStatus - (*insert_wire_auditor_progress)( + (*get_deposit_confirmations)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_WireProgressPoint *pp); + uint64_t start_id, + bool return_suppressed, + TALER_AUDITORDB_DepositConfirmationCallback cb, + void *cb_cls); /** - * Update information about the progress of the wire auditor. There - * must be an existing record for the exchange. + * Delete information about a deposit confirmation from the database. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param pp where is the auditor in processing - * @return transaction status code + * @param row_id row to delete + * @return query result status */ enum GNUNET_DB_QueryStatus - (*update_wire_auditor_progress)( + (*delete_deposit_confirmation)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_AUDITORDB_WireProgressPoint *pp); - - - /** - * Get information about the progress of the wire auditor. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param account_name name of the wire account we are auditing - * @param[out] pp set to where the auditor is in processing - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_wire_auditor_progress)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_AUDITORDB_WireProgressPoint *pp); + uint64_t row_id); /** @@ -957,25 +639,19 @@ struct TALER_AUDITORDB_Plugin * existing record for the reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param rfb balance amounts for the reserve * @param expiration_date expiration date of the reserve * @param origin_account where did the money in the reserve originally come from * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_reserve_info)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute expiration_date, - const char *origin_account); + (*insert_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp expiration_date, + const char *origin_account); /** @@ -983,352 +659,241 @@ struct TALER_AUDITORDB_Plugin * existing record, which must already exist. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param rfb balance amounts for the reserve * @param expiration_date expiration date of the reserve * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_reserve_info)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute expiration_date); + (*update_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp expiration_date); /** * Get information about a reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param reserve_pub public key of the reserve - * @param master_pub master public key of the exchange * @param[out] rowid which row did we get the information from - * @param[out] reserve_balance amount stored in the reserve - * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param[out] rfb set to balances associated with the reserve * @param[out] expiration_date expiration date of the reserve * @param[out] sender_account from where did the money in the reserve originally come from * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_info)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub, - uint64_t *rowid, - struct TALER_Amount *reserve_balance, - struct TALER_Amount *withdraw_fee_balance, - struct GNUNET_TIME_Absolute *expiration_date, - char **sender_account); + (*get_reserve_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *rowid, + struct TALER_AUDITORDB_ReserveFeeBalance *rfb, + struct GNUNET_TIME_Timestamp *expiration_date, + char **sender_account); /** * Delete information about a reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @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, - struct TALER_AUDITORDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_MasterPublicKeyP *master_pub); + const struct TALER_ReservePublicKeyP *reserve_pub); /** - * Insert information about all reserves. There must not be an - * existing record for the @a master_pub. + * Insert new row into the pending deposits table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the requested wire transfer deadline * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_reserve_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance); + (*insert_pending_deposit)( + void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_PaytoHashP *wire_target_h_payto, + const struct TALER_Amount *total_amount, + struct GNUNET_TIME_Timestamp deadline); /** - * Update information about all reserves. Destructively updates an - * existing record, which must already exist. + * Delete a row from the pending deposit table. + * Usually done when the respective wire transfer + * was finally detected. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param reserve_balance amount stored in the reserve - * @param withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param batch_deposit_serial_id which entry to delete * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_reserve_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *reserve_balance, - const struct TALER_Amount *withdraw_fee_balance); + (*delete_pending_deposit)( + void *cls, + uint64_t batch_deposit_serial_id); /** - * Get summary information about all reserves. + * Return (batch) deposits for which we have not yet + * seen the required wire transfer. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param[out] reserve_balance amount stored in the reserve - * @param[out] withdraw_fee_balance amount the exchange gained in withdraw fees - * due to withdrawals from this reserve + * @param deadline only return up to this deadline + * @param cb function to call on each entry + * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *reserve_balance, - struct TALER_Amount *withdraw_fee_balance); + (*select_pending_deposits)( + void *cls, + struct GNUNET_TIME_Absolute deadline, + TALER_AUDITORDB_WireMissingCallback cb, + void *cb_cls); /** - * Insert information about exchange's wire fee balance. There must not be an - * existing record for the same @a master_pub. + * Insert information about a purse. There must not be an + * existing record for the purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param wire_fee_balance amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param balance balance of the purse + * @param expiration_date expiration date of the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_fee_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *wire_fee_balance); + (*insert_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp expiration_date); /** - * Insert information about exchange's wire fee balance. Destructively updates an + * Update information about a purse. Destructively updates an * existing record, which must already exist. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param wire_fee_balance amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param balance new balance for the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_wire_fee_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *wire_fee_balance); + (*update_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); /** - * Get summary information about an exchanges wire fee balance. + * Get information about a purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master public key of the exchange - * @param[out] wire_fee_balance set amount the exchange gained in wire fees + * @param purse_pub public key of the purse + * @param[out] rowid which row did we get the information from + * @param[out] balance set to balance of the purse + * @param[out] expiration_date expiration date of the purse * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_wire_fee_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *wire_fee_balance); + (*get_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + uint64_t *rowid, + struct TALER_Amount *balance, + struct GNUNET_TIME_Timestamp *expiration_date); /** - * Insert information about a denomination key's balances. There - * must not be an existing record for the denomination key. + * Delete information about a purse. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param denom_pub_hash hash of the denomination public key - * @param denom_balance value of coins outstanding with this denomination key - * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param denom_risk value of coins issued with this denomination key - * @param denom_recoup value of coins paid back if this denomination key was revoked - * @param num_issued how many coins of this denomination did the exchange blind-sign + * @param purse_pub public key of the reserve * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_denomination_balance)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *denom_loss, - const struct TALER_Amount *denom_risk, - const struct TALER_Amount *recoup_loss, - uint64_t num_issued); + (*delete_purse_info)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub); /** - * Update information about a denomination key's balances. There - * must be an existing record for the denomination key. + * Get information about expired purses. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param denom_pub_hash hash of the denomination public key - * @param denom_balance value of coins outstanding with this denomination key - * @param denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param denom_risk value of coins issued with this denomination key - * @param denom_recoup value of coins paid back if this denomination key was revoked - * @param num_issued how many coins of this denomination did the exchange blind-sign + * @param cb function to call on expired purses + * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_denomination_balance)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *denom_loss, - const struct TALER_Amount *denom_risk, - const struct TALER_Amount *recoup_loss, - uint64_t num_issued); + (*select_purse_expired)( + void *cls, + TALER_AUDITORDB_ExpiredPurseCallback cb, + void *cb_cls); /** - * Get information about a denomination key's balances. + * Insert information about a denomination key's balances. There + * must not be an existing record for the denomination key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param denom_pub_hash hash of the denomination public key - * @param[out] denom_balance value of coins outstanding with this denomination key - * @param[out] denom_loss value of coins redeemed that were not outstanding (effectively, negative @a denom_balance) - * @param[out] denom_risk value of coins issued with this denomination key - * @param[out] denom_recoup value of coins paid back if this denomination key was revoked - * @param[out] num_issued how many coins of this denomination did the exchange blind-sign + * @param dcd denomination circulation data to store * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_denomination_balance)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, - struct TALER_Amount *denom_balance, - struct TALER_Amount *denom_loss, - struct TALER_Amount *denom_risk, - struct TALER_Amount *recoup_loss, - uint64_t *num_issued); + (*insert_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** - * Delete information about a denomination key's balances. + * Update information about a denomination key's balances. There + * must be an existing record for the denomination key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param denom_pub_hash hash of the denomination public key + * @param dcd denomination circulation data to store * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*del_denomination_balance)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash); - - - /** - * Insert information about an exchange's denomination balances. There - * must not be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param denom_balance value of coins outstanding with this denomination key - * @param deposit_fee_balance total deposit fees collected for this DK - * @param melt_fee_balance total melt fees collected for this DK - * @param refund_fee_balance total refund fees collected for this DK - * @param risk maximum risk exposure of the exchange - * @param recoup_loss actual losses from recoup (actualized @a risk) - * @param irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_balance_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *deposit_fee_balance, - const struct TALER_Amount *melt_fee_balance, - const struct TALER_Amount *refund_fee_balance, - const struct TALER_Amount *risk, - const struct TALER_Amount *recoup_loss, - const struct TALER_Amount *irregular_recoups); - + (*update_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + const struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** - * Update information about an exchange's denomination balances. There - * must be an existing record for the exchange. + * Delete information about a denomination key's balances. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param denom_balance value of coins outstanding with this denomination key - * @param deposit_fee_balance total deposit fees collected for this DK - * @param melt_fee_balance total melt fees collected for this DK - * @param refund_fee_balance total refund fees collected for this DK - * @param risk maximum risk exposure of the exchange - * @param recoup_loss actual losses from recoup (actualized @a risk) - * @param irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) + * @param denom_pub_hash hash of the denomination public key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*update_balance_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *denom_balance, - const struct TALER_Amount *deposit_fee_balance, - const struct TALER_Amount *melt_fee_balance, - const struct TALER_Amount *refund_fee_balance, - const struct TALER_Amount *risk, - const struct TALER_Amount *recoup_loss, - const struct TALER_Amount *irregular_recoups); + (*del_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash); /** - * Get information about an exchange's denomination balances. + * Get information about a denomination key's balances. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param[out] denom_balance value of coins outstanding with this denomination key - * @param[out] deposit_fee_balance total deposit fees collected for this DK - * @param[out] melt_fee_balance total melt fees collected for this DK - * @param[out] refund_fee_balance total refund fees collected for this DK - * @param[out] risk maximum risk exposure of the exchange - * @param[out] recoup_loss actual losses from recoup (actualized @a risk) - * @param[out] irregular_recoups recoups made of non-revoked coins (reduces - * risk, but should never happen) + * @param denom_pub_hash hash of the denomination public key + * @param[out] dcd denomination circulation data to initialize * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_balance_summary)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *denom_balance, - struct TALER_Amount *deposit_fee_balance, - struct TALER_Amount *melt_fee_balance, - struct TALER_Amount *refund_fee_balance, - struct TALER_Amount *risk, - struct TALER_Amount *recoup_loss, - struct TALER_Amount *irregular_recoup); + (*get_denomination_balance)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_AUDITORDB_DenominationCirculationData *dcd); /** @@ -1336,8 +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 session connection to use - * @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 @@ -1349,21 +912,16 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_denom_revenue)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct GNUNET_HashCode *denom_pub_hash, - struct GNUNET_TIME_Absolute revenue_timestamp, + const struct TALER_DenominationHashP *denom_pub_hash, + struct GNUNET_TIME_Timestamp revenue_timestamp, const struct TALER_Amount *revenue_balance, const struct TALER_Amount *recoup_loss_balance); /** - * Obtain all of the historic denomination key revenue - * of the given @a master_pub. + * Obtain all of the historic denomination key revenue. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @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 @@ -1371,8 +929,6 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*select_historic_denom_revenue)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, TALER_AUDITORDB_HistoricDenominationRevenueDataCallback cb, void *cb_cls); @@ -1381,8 +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 session connection to use - * @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 @@ -1391,10 +945,8 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*insert_historic_reserve_revenue)( void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct GNUNET_TIME_Absolute start_time, - struct GNUNET_TIME_Absolute end_time, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, const struct TALER_Amount *reserve_profits); @@ -1402,8 +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 session connection to use - * @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 @@ -1411,62 +961,9 @@ struct TALER_AUDITORDB_Plugin enum GNUNET_DB_QueryStatus (*select_historic_reserve_revenue)( void *cls, - struct TALER_AUDITORDB_Session *session, - 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 session connection to use - * @param master_pub master key of the exchange - * @param balance what the bank account balance of the exchange should show - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*insert_predicted_result)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance); - - - /** - * Update information about an exchange's predicted balance. There - * must be an existing record for the exchange. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param balance what the bank account balance of the exchange should show - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*update_predicted_result)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - const struct TALER_Amount *balance); - - - /** - * Get an exchange's predicted balance. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use - * @param master_pub master key of the exchange - * @param[out] balance expected bank account balance of the exchange - * @return transaction status code - */ - enum GNUNET_DB_QueryStatus - (*get_predicted_balance)(void *cls, - struct TALER_AUDITORDB_Session *session, - const struct TALER_MasterPublicKeyP *master_pub, - struct TALER_Amount *balance); - - }; diff --git a/src/include/taler_bank_service.h b/src/include/taler_bank_service.h index 0212e61f1..e8e32947b 100644 --- a/src/include/taler_bank_service.h +++ b/src/include/taler_bank_service.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015-2020 Taler Systems SA + Copyright (C) 2015-2021 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 @@ -100,24 +100,64 @@ struct TALER_BANK_AdminAddIncomingHandle; /** + * Response details for a history request. + */ +struct TALER_BANK_AdminAddIncomingResponse +{ + + /** + * HTTP status. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + /** + * unique ID of the wire transfer in the bank's records + */ + uint64_t serial_id; + + /** + * time when the transaction was made. + */ + struct GNUNET_TIME_Timestamp timestamp; + + } ok; + + } details; + +}; + +/** * Callbacks of this type are used to return the result of submitting * a request to transfer funds to the exchange. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol) - * @param ec detailed error code - * @param serial_id unique ID of the wire transfer in the bank's records; UINT64_MAX on error - * @param timestamp time when the transaction was made. - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON + * @param air response details */ typedef void -(*TALER_BANK_AdminAddIncomingCallback) (void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - struct GNUNET_TIME_Absolute timestamp, - const json_t *json); +(*TALER_BANK_AdminAddIncomingCallback) ( + void *cls, + const struct TALER_BANK_AdminAddIncomingResponse *air); /** @@ -190,20 +230,64 @@ struct TALER_BANK_TransferHandle; /** + * Response details for a history request. + */ +struct TALER_BANK_TransferResponse +{ + + /** + * HTTP status. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + + /** + * unique ID of the wire transfer in the bank's records + */ + uint64_t row_id; + + /** + * when did the transaction go into effect + */ + struct GNUNET_TIME_Timestamp timestamp; + + } ok; + } details; +}; + + +/** * Function called with the result from the execute step. * * @param cls closure - * @param response_code HTTP status code - * @param ec taler error code - * @param row_id unique ID of the wire transfer in the bank's records - * @param timestamp when did the transaction go into effect + * @param tr response details */ typedef void -(*TALER_BANK_TransferCallback)(void *cls, - unsigned int response_code, - enum TALER_ErrorCode ec, - uint64_t row_id, - struct GNUNET_TIME_Absolute timestamp); +(*TALER_BANK_TransferCallback)( + void *cls, + const struct TALER_BANK_TransferResponse *tr); /** @@ -259,6 +343,11 @@ struct TALER_BANK_CreditHistoryHandle; struct TALER_BANK_CreditDetails { /** + * Serial ID of the wire transfer. + */ + uint64_t serial_id; + + /** * Amount that was transferred */ struct TALER_Amount amount; @@ -266,25 +355,75 @@ struct TALER_BANK_CreditDetails /** * Time of the the transfer */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** - * Reserve public key encoded in the wire - * transfer subject. + * Reserve public key encoded in the wire transfer subject. */ struct TALER_ReservePublicKeyP reserve_pub; /** - * payto://-URL of the source account that - * send the funds. + * payto://-URL of the source account that send the funds. + */ + const char *debit_account_uri; + +}; + + +/** + * Response details for a history request. + */ +struct TALER_BANK_CreditHistoryResponse +{ + + /** + * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both + * successful replies, but @e details will only contain @e success information + * if this is set to #MHD_HTTP_OK. + */ + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. */ - const char *debit_account_url; + enum TALER_ErrorCode ec; /** - * payto://-URL of the target account that - * received the funds. + * Full response, NULL if body was not in JSON format. */ - const char *credit_account_url; + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + /** + * payto://-URL of the target account that received the funds. + */ + const char *credit_account_uri; + + /** + * Array of transactions received. + */ + const struct TALER_BANK_CreditDetails *details; + + /** + * Length of the @e details array. + */ + unsigned int details_length; + + } ok; + + } details; + }; @@ -293,25 +432,12 @@ struct TALER_BANK_CreditDetails * the bank for the credit transaction history. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol), - * #MHD_HTTP_NO_CONTENT if there are no more results; on success the - * last callback is always of this status (even if `abs(num_results)` were - * already returned). - * @param ec detailed error code - * @param serial_id monotonically increasing counter corresponding to the transaction - * @param details details about the wire transfer - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration + * @param reply details about the response */ -typedef int -(*TALER_BANK_CreditHistoryCallback) ( +typedef void +(*TALER_BANK_CreditHistoryCallback)( void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - const struct TALER_BANK_CreditDetails *details, - const json_t *json); + const struct TALER_BANK_CreditHistoryResponse *reply); /** @@ -323,6 +449,8 @@ typedef int * @param num_results how many results do we want; negative numbers to go into the past, * positive numbers to go into the future starting at @a start_row; * must not be zero. + * @param timeout how long the client is willing to wait for more results + * (only useful if @a num_results is positive) * @param hres_cb the callback to call with the transaction history * @param hres_cb_cls closure for the above callback * @return NULL @@ -330,12 +458,14 @@ typedef int * In this case, the callback is not called. */ struct TALER_BANK_CreditHistoryHandle * -TALER_BANK_credit_history (struct GNUNET_CURL_Context *ctx, - const struct TALER_BANK_AuthenticationData *auth, - uint64_t start_row, - int64_t num_results, - TALER_BANK_CreditHistoryCallback hres_cb, - void *hres_cb_cls); +TALER_BANK_credit_history ( + struct GNUNET_CURL_Context *ctx, + const struct TALER_BANK_AuthenticationData *auth, + uint64_t start_row, + int64_t num_results, + struct GNUNET_TIME_Relative timeout, + TALER_BANK_CreditHistoryCallback hres_cb, + void *hres_cb_cls); /** @@ -364,6 +494,11 @@ struct TALER_BANK_DebitHistoryHandle; struct TALER_BANK_DebitDetails { /** + * Serial ID of the wire transfer. + */ + uint64_t serial_id; + + /** * Amount that was transferred */ struct TALER_Amount amount; @@ -371,7 +506,7 @@ struct TALER_BANK_DebitDetails /** * Time of the the transfer */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Wire transfer identifier used by the exchange. @@ -384,16 +519,66 @@ struct TALER_BANK_DebitDetails const char *exchange_base_url; /** - * payto://-URL of the source account that - * send the funds. + * payto://-URI of the target account that received the funds. */ - const char *debit_account_url; + const char *credit_account_uri; + +}; + + +/** + * Response details for a history request. + */ +struct TALER_BANK_DebitHistoryResponse +{ /** - * payto://-URL of the target account that - * received the funds. + * HTTP status. Note that #MHD_HTTP_OK and #MHD_HTTP_NO_CONTENT are both + * successful replies, but @e details will only contain @e success information + * if this is set to #MHD_HTTP_OK. */ - const char *credit_account_url; + unsigned int http_status; + + /** + * Taler error code, #TALER_EC_NONE on success. + */ + enum TALER_ErrorCode ec; + + /** + * Full response, NULL if body was not in JSON format. + */ + const json_t *response; + + /** + * Details returned depending on the @e http_status. + */ + union + { + + /** + * Details if status was #MHD_HTTP_OK + */ + struct + { + + /** + * payto://-URI of the source account that send the funds. + */ + const char *debit_account_uri; + + /** + * Array of transactions initiated. + */ + const struct TALER_BANK_DebitDetails *details; + + /** + * Length of the @e details array. + */ + unsigned int details_length; + + } ok; + + } details; }; @@ -403,25 +588,12 @@ struct TALER_BANK_DebitDetails * the bank for the debit transaction history. * * @param cls closure - * @param http_status HTTP response code, #MHD_HTTP_OK (200) for successful status request - * 0 if the bank's reply is bogus (fails to follow the protocol), - * #MHD_HTTP_NO_CONTENT if there are no more results; on success the - * last callback is always of this status (even if `abs(num_results)` were - * already returned). - * @param ec detailed error code - * @param serial_id monotonically increasing counter corresponding to the transaction - * @param details details about the wire transfer - * @param json detailed response from the HTTPD, or NULL if reply was not in JSON - * @return #GNUNET_OK to continue, #GNUNET_SYSERR to abort iteration + * @param reply details about the response */ -typedef int -(*TALER_BANK_DebitHistoryCallback) ( +typedef void +(*TALER_BANK_DebitHistoryCallback)( void *cls, - unsigned int http_status, - enum TALER_ErrorCode ec, - uint64_t serial_id, - const struct TALER_BANK_DebitDetails *details, - const json_t *json); + const struct TALER_BANK_DebitHistoryResponse *reply); /** @@ -433,6 +605,8 @@ typedef int * @param num_results how many results do we want; negative numbers to go into the past, * positive numbers to go into the future starting at @a start_row; * must not be zero. + * @param timeout how long the client is willing to wait for more results + * (only useful if @a num_results is positive) * @param hres_cb the callback to call with the transaction history * @param hres_cb_cls closure for the above callback * @return NULL @@ -444,6 +618,7 @@ TALER_BANK_debit_history (struct GNUNET_CURL_Context *ctx, const struct TALER_BANK_AuthenticationData *auth, uint64_t start_row, int64_t num_results, + struct GNUNET_TIME_Relative timeout, TALER_BANK_DebitHistoryCallback hres_cb, void *hres_cb_cls); @@ -471,7 +646,7 @@ TALER_BANK_debit_history_cancel (struct TALER_BANK_DebitHistoryHandle *hh); * @param[out] auth set to the configuration data found * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_BANK_auth_parse_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, struct TALER_BANK_AuthenticationData *auth); diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 3c5358144..b941316b5 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2018 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,14 +18,88 @@ * @brief taler-specific crypto functions * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff <christian@grothoff.org> + * @author Özgür Kesim <oec-taler@kesim.org> */ +#if ! defined (__TALER_UTIL_LIB_H_INSIDE__) +#error "Only <taler_util.h> can be included directly." +#endif + #ifndef TALER_CRYPTO_LIB_H #define TALER_CRYPTO_LIB_H #include <gnunet/gnunet_util_lib.h> -#include "taler_util.h" - +#include "taler_error_codes.h" #include <gcrypt.h> +#include <jansson.h> + + +/** + * Maximum number of coins we allow per operation. + */ +#define TALER_MAX_FRESH_COINS 256 + +/** + * Cut-and-choose size for refreshing. Client looses the gamble (of + * unaccountable transfers) with probability 1/TALER_CNC_KAPPA. Refresh cost + * increases linearly with TALER_CNC_KAPPA, and 3 is sufficient up to a + * income/sales tax of 66% of total transaction value. As there is + * no good reason to change this security parameter, we declare it + * fixed and part of the protocol. + */ +#define TALER_CNC_KAPPA 3 +#define TALER_CNC_KAPPA_MINUS_ONE_STR "2" + + +/** + * Possible AML decision states. + */ +enum TALER_AmlDecisionState +{ + + /** + * All AML requirements are currently satisfied. + */ + TALER_AML_NORMAL = 0, + + /** + * An AML investigation is pending. + */ + TALER_AML_PENDING = 1, + + /** + * An AML decision has concluded that the funds must be frozen. + */ + TALER_AML_FROZEN = 2, + + /** + * Maximum allowed numeric value for AML status. + */ + TALER_AML_MAX = 2 +}; + + +/** + * Possible algorithms for confirmation code generation. + */ +enum TALER_MerchantConfirmationAlgorithm +{ + + /** + * No purchase confirmation. + */ + TALER_MCA_NONE = 0, + + /** + * Purchase confirmation without payment + */ + TALER_MCA_WITHOUT_PRICE = 1, + + /** + * Purchase confirmation with payment + */ + TALER_MCA_WITH_PRICE = 2 + +}; /* ****************** Coin crypto primitives ************* */ @@ -33,6 +107,64 @@ GNUNET_NETWORK_STRUCT_BEGIN /** + * @brief Type of public keys for Taler security modules (software or hardware). + * Note that there are usually at least two security modules (RSA and EdDSA), + * each with its own private key. + */ +struct TALER_SecurityModulePublicKeyP +{ + /** + * Taler uses EdDSA for security modules. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + +/** + * @brief Set of the public keys of the security modules + */ +struct TALER_SecurityModulePublicKeySetP +{ + /** + * Public key of the RSA security module + */ + struct TALER_SecurityModulePublicKeyP rsa; + + /** + * Public key of the CS security module + */ + struct TALER_SecurityModulePublicKeyP cs; + + /** + * Public key of the eddsa security module + */ + struct TALER_SecurityModulePublicKeyP eddsa; +}; + +/** + * @brief Type of private keys for Taler security modules (software or hardware). + */ +struct TALER_SecurityModulePrivateKeyP +{ + /** + * Taler uses EdDSA for security modules. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures used for Taler security modules (software or hardware). + */ +struct TALER_SecurityModuleSignatureP +{ + /** + * Taler uses EdDSA for security modules. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** * @brief Type of public keys for Taler reserves. */ struct TALER_ReservePublicKeyP @@ -69,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. @@ -122,7 +266,7 @@ struct TALER_TransferPublicKeyP /** - * @brief Type of transfer public keys used during refresh + * @brief Type of transfer private keys used during refresh * operations. */ struct TALER_TransferPrivateKeyP @@ -135,6 +279,32 @@ struct TALER_TransferPrivateKeyP /** + * @brief Type of public keys used for contract + * encryption. + */ +struct TALER_ContractDiffiePublicP +{ + /** + * Taler uses ECDHE for contract encryption. + */ + struct GNUNET_CRYPTO_EcdhePublicKey ecdhe_pub; +}; + + +/** + * @brief Type of private keys used for contract + * encryption. + */ +struct TALER_ContractDiffiePrivateP +{ + /** + * Taler uses ECDHE for contract encryption. + */ + struct GNUNET_CRYPTO_EcdhePrivateKey ecdhe_priv; +}; + + +/** * @brief Type of online public keys used by the exchange to sign * messages. */ @@ -185,50 +355,62 @@ struct TALER_MasterPublicKeyP /** - * @brief Type of the public key used by the auditor. + * @brief Type of the offline master public keys used by the exchange. */ -struct TALER_AuditorPublicKeyP +struct TALER_MasterPrivateKeyP { /** - * Taler uses EdDSA for the auditor's signing key. + * Taler uses EdDSA for the long-term offline master key. */ - struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; }; /** - * @brief Type of signatures used by the auditor. + * @brief Type of signatures by the offline master public key used by the exchange. */ -struct TALER_AuditorSignatureP +struct TALER_MasterSignatureP { /** - * Taler uses EdDSA signatures for auditors. + * Taler uses EdDSA for the long-term offline master key. */ - struct GNUNET_CRYPTO_EddsaSignature eddsa_sig; + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; }; /** - * @brief Type of the offline master public keys used by the exchange. + * @brief Type of the private key used by the auditor. */ -struct TALER_MasterPrivateKeyP +struct TALER_AuditorPrivateKeyP { /** - * Taler uses EdDSA for the long-term offline master key. + * Taler uses EdDSA for the auditor's signing key. */ struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; }; /** - * @brief Type of signatures by the offline master public key used by the exchange. + * @brief Type of the public key used by the auditor. */ -struct TALER_MasterSignatureP +struct TALER_AuditorPublicKeyP { /** - * Taler uses EdDSA for the long-term offline master key. + * Taler uses EdDSA for the auditor's signing key. */ - struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of signatures used by the auditor. + */ +struct TALER_AuditorSignatureP +{ + /** + * Taler uses EdDSA signatures for auditors. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_sig; }; @@ -258,7 +440,6 @@ struct TALER_CoinSpendPrivateKeyP struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; }; - /** * @brief Type of signatures made with Taler coins. */ @@ -272,14 +453,163 @@ struct TALER_CoinSpendSignatureP /** - * @brief Type of blinding keys for Taler. + * @brief Type of private keys for age commitment in coins. + */ +struct TALER_AgeCommitmentPrivateKeyP +{ +#ifdef AGE_RESTRICTION_WITH_ECDSA + /** + * Taler uses EcDSA for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_EcdsaPrivateKey priv; +#else + /** + * Taler uses Edx25519 for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_Edx25519PrivateKey priv; +#endif +}; + + +/** + * @brief Type of public keys for age commitment in coins. + */ +struct TALER_AgeCommitmentPublicKeyP +{ +#ifdef AGE_RESTRICTION_WITH_ECDSA + /** + * Taler uses EcDSA for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_EcdsaPublicKey pub; +#else + /** + * Taler uses Edx25519 for coins when signing age verification attestation. + */ + struct GNUNET_CRYPTO_Edx25519PublicKey pub; +#endif +}; + + +/* + * @brief Hash to represent the commitment to n*kappa blinded keys during a + * age-withdrawal. It is the running SHA512 hash over the hashes of the blinded + * envelopes of n*kappa coins. + */ +struct TALER_AgeWithdrawCommitmentHashP +{ + struct GNUNET_HashCode hash; +}; + + +/** + * @brief Type of online public keys used by the wallet to establish a purse and the associated contract meta data. */ -struct TALER_DenominationBlindingKeyP +struct TALER_PurseContractPublicKeyP { /** - * Taler uses RSA for blind signatures. + * Taler uses EdDSA for purse message signing. */ - struct GNUNET_CRYPTO_RsaBlindingKeySecret bks; + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of online private keys used by the wallet to + * bind a purse to a particular contract (and other meta data). + */ +struct TALER_PurseContractPrivateKeyP +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures used by the wallet to sign purse creation messages online. + */ +struct TALER_PurseContractSignatureP +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * @brief Type of online public keys used by the wallet to + * sign a merge of a purse into an account. + */ +struct TALER_PurseMergePublicKeyP +{ + /** + * Taler uses EdDSA for purse message signing. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of online private keys used by the wallet to + * sign a merge of a purse into an account. + */ +struct TALER_PurseMergePrivateKeyP +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures used by the wallet to sign purse merge requests online. + */ +struct TALER_PurseMergeSignatureP +{ + /** + * Taler uses EdDSA for online signatures sessions. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; +}; + + +/** + * @brief Type of online public keys used by AML officers. + */ +struct TALER_AmlOfficerPublicKeyP +{ + /** + * Taler uses EdDSA for AML decision signing. + */ + struct GNUNET_CRYPTO_EddsaPublicKey eddsa_pub; +}; + + +/** + * @brief Type of online private keys used to identify + * AML officers. + */ +struct TALER_AmlOfficerPrivateKeyP +{ + /** + * Taler uses EdDSA for AML decision signing. + */ + struct GNUNET_CRYPTO_EddsaPrivateKey eddsa_priv; +}; + + +/** + * @brief Type of signatures used by AML officers. + */ +struct TALER_AmlOfficerSignatureP +{ + /** + * Taler uses EdDSA for AML decision signing. + */ + struct GNUNET_CRYPTO_EddsaSignature eddsa_signature; }; @@ -296,30 +626,635 @@ 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. + */ +struct TALER_ClaimTokenP +{ + /** + * The token is a 128-bit UUID. + */ + struct GNUNET_Uuid token; +}; + + +/** + * Salt used to hash a merchant's payto:// URI to + * compute the "h_wire" (say for deposit requests). + */ +struct TALER_WireSaltP +{ + /** + * Actual 128-bit salt value. + */ + uint32_t salt[4]; +}; + + +/** + * Hash used to represent an CS public key. Does not include age + * restrictions and is ONLY for CS. Used ONLY for interactions with the CS + * security module. + */ +struct TALER_CsPubHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent an RSA public key. Does not include age + * restrictions and is ONLY for RSA. Used ONLY for interactions with the RSA + * security module. + */ +struct TALER_RsaPubHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Master key material for the deriviation of + * private coins and blinding factors during + * withdraw or refresh. + */ +struct TALER_PlanchetMasterSecretP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; + + +/** + * Master key material for the deriviation of + * private coins and blinding factors. + */ +struct TALER_RefreshMasterSecretP +{ + + /** + * Key material. + */ + uint32_t key_data[8]; + +}; + + +/** + * Hash used to represent a denomination public key + * and associated age restrictions (if any). + */ +struct TALER_DenominationHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent the private part + * of a contract between merchant and consumer. + */ +struct TALER_PrivateContractHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent the policy extension to a deposit + */ +struct TALER_ExtensionPolicyHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent the salted hash of a + * merchant's bank account. + */ +struct TALER_MerchantWireHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent the unsalted hash of a + * payto:// URI representing a bank account. + */ +struct TALER_PaytoHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_ShortHashCode hash; +}; + + +/** + * Hash used to represent a commitment to a blinded + * coin, i.e. the hash of the envelope. + */ +struct TALER_BlindedCoinHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Hash used to represent the hash of the public + * key of a coin (without blinding). + */ +struct TALER_CoinPubHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * @brief Value that uniquely identifies a reward. + */ +struct TALER_RewardIdentifierP +{ + /** + * The tip identifier is a SHA-512 hash code. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * @brief Value that uniquely identifies a tip pick up operation. + */ +struct TALER_PickupIdentifierP +{ + /** + * The pickup identifier is a SHA-512 hash code. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * @brief Salted hash over the JSON object representing the manifests of + * extensions. + */ +struct TALER_ExtensionManifestsHashP +{ + /** + * Actual hash value. + */ + struct GNUNET_HashCode hash; +}; + + +/** + * Set of the fees applying to a denomination. + */ +struct TALER_DenomFeeSetNBOP +{ + + /** + * The fee the exchange charges when a coin of this type is withdrawn. + * (can be zero). + */ + struct TALER_AmountNBO withdraw; + + /** + * The fee the exchange charges when a coin of this type is deposited. + * (can be zero). + */ + struct TALER_AmountNBO deposit; + + /** + * The fee the exchange charges when a coin of this type is refreshed. + * (can be zero). + */ + struct TALER_AmountNBO refresh; + + /** + * The fee the exchange charges when a coin of this type is refunded. + * (can be zero). Note that refund fees are charged to the customer; + * if a refund is given, the deposit fee is also refunded. + */ + struct TALER_AmountNBO refund; + +}; + + +/** + * Set of the fees applying for a given + * time-range and wire method. + */ +struct TALER_WireFeeSetNBOP +{ + + /** + * The fee the exchange charges for wiring funds + * to a merchant. + */ + struct TALER_AmountNBO wire; + + /** + * The fee the exchange charges for closing a reserve + * and wiring the funds back to the origin account. + */ + struct TALER_AmountNBO closing; + +}; + + +/** + * Set of the fees applying globally for a given + * time-range. + */ +struct TALER_GlobalFeeSetNBOP +{ + + /** + * The fee the exchange charges for returning the history of a reserve or + * account. + */ + struct TALER_AmountNBO history; + + /** + * The fee the exchange charges for keeping an account or reserve open for a + * year. + */ + struct TALER_AmountNBO account; + + /** + * The fee the exchange charges if a purse is abandoned and this was not + * covered by the account limit. + */ + struct TALER_AmountNBO purse; +}; + + GNUNET_NETWORK_STRUCT_END /** + * 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 +{ + + /** + * The fee the exchange charges when a coin of this type is withdrawn. + * (can be zero). + */ + struct TALER_Amount withdraw; + + /** + * The fee the exchange charges when a coin of this type is deposited. + * (can be zero). + */ + struct TALER_Amount deposit; + + /** + * The fee the exchange charges when a coin of this type is refreshed. + * (can be zero). + */ + struct TALER_Amount refresh; + + /** + * The fee the exchange charges when a coin of this type is refunded. + * (can be zero). Note that refund fees are charged to the customer; + * if a refund is given, the deposit fee is also refunded. + */ + struct TALER_Amount refund; + +}; + + +/** + * Set of the fees applying for a given time-range and wire method. + */ +struct TALER_WireFeeSet +{ + + /** + * The fee the exchange charges for wiring funds to a merchant. + */ + struct TALER_Amount wire; + + /** + * The fee the exchange charges for closing a reserve + * and wiring the funds back to the origin account. + */ + struct TALER_Amount closing; + +}; + + +/** + * Set of the fees applying globally for a given + * time-range. + */ +struct TALER_GlobalFeeSet +{ + + /** + * The fee the exchange charges for returning the + * history of a reserve or account. + */ + struct TALER_Amount history; + + /** + * The fee the exchange charges for keeping + * an account or reserve open for a year. + */ + struct TALER_Amount account; + + /** + * The fee the exchange charges if a purse + * is abandoned and this was not covered by + * the account limit. + */ + struct TALER_Amount purse; +}; + + +/** + * Convert fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert + */ +void +TALER_denom_fee_set_hton (struct TALER_DenomFeeSetNBOP *nbo, + const struct TALER_DenomFeeSet *fees); + + +/** + * Convert fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_denom_fee_set_ntoh (struct TALER_DenomFeeSet *fees, + const struct TALER_DenomFeeSetNBOP *nbo); + + +/** + * Convert global fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert + */ +void +TALER_global_fee_set_hton (struct TALER_GlobalFeeSetNBOP *nbo, + const struct TALER_GlobalFeeSet *fees); + + +/** + * Convert global fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_global_fee_set_ntoh (struct TALER_GlobalFeeSet *fees, + const struct TALER_GlobalFeeSetNBOP *nbo); + + +/** + * Compare global fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_global_fee_set_cmp (const struct TALER_GlobalFeeSet *f1, + const struct TALER_GlobalFeeSet *f2); + + +/** + * Convert wire fee set from host to network byte order. + * + * @param[out] nbo where to write the result + * @param fees fee set to convert + */ +void +TALER_wire_fee_set_hton (struct TALER_WireFeeSetNBOP *nbo, + const struct TALER_WireFeeSet *fees); + + +/** + * Convert wire fee set from network to host network byte order. + * + * @param[out] fees where to write the result + * @param nbo fee set to convert + */ +void +TALER_wire_fee_set_ntoh (struct TALER_WireFeeSet *fees, + const struct TALER_WireFeeSetNBOP *nbo); + + +/** + * Compare wire fee sets. + * + * @param f1 first set to compare + * @param f2 second set to compare + * @return 0 if sets are equal + */ +int +TALER_wire_fee_set_cmp (const struct TALER_WireFeeSet *f1, + const struct TALER_WireFeeSet *f2); + + +/** + * Hash @a rsa. + * + * @param rsa key to hash + * @param[out] h_rsa where to write the result + */ +void +TALER_rsa_pub_hash (const struct GNUNET_CRYPTO_RsaPublicKey *rsa, + struct TALER_RsaPubHashP *h_rsa); + + +/** + * Hash @a cs. + * + * @param cs key to hash + * @param[out] h_cs where to write the result + */ +void +TALER_cs_pub_hash (const struct GNUNET_CRYPTO_CsPublicKey *cs, + struct TALER_CsPubHashP *h_cs); + + +/** * @brief Type of (unblinded) coin signatures for Taler. */ struct TALER_DenominationSignature { /** - * Taler uses RSA for blinding. + * Denominations use blind signatures. */ - struct GNUNET_CRYPTO_RsaSignature *rsa_signature; + struct GNUNET_CRYPTO_UnblindedSignature *unblinded_sig; +}; + + +/** + * @brief Type for *blinded* denomination signatures for Taler. + * Must be unblinded before it becomes valid. + */ +struct TALER_BlindedDenominationSignature +{ + /** + * Denominations use blind signatures. + */ + struct GNUNET_CRYPTO_BlindedSignature *blinded_sig; +}; + + +/* *************** Age Restriction *********************************** */ + +/* + * @brief Type of a list of age groups, represented as bit mask. + * + * The bits set in the mask mark the edges at the beginning of a next age + * group. F.e. for the age groups + * 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-21, 21-* + * the following bits are set: + * + * 31 24 16 8 0 + * | | | | | + * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + * + * A value of 0 means that the exchange does not support the extension for + * age-restriction. + * + * For a non-0 age mask, the 0th bit always must be set, otherwise the age + * mask is considered invalid. + */ +struct TALER_AgeMask +{ + uint32_t bits; +}; + +/** + * @brief Age commitment of a coin. + */ +struct TALER_AgeCommitmentHash +{ + /** + * The commitment is a SHA-256 hash code. + */ + struct GNUNET_ShortHashCode shash; +}; + +/** + * @brief Signature of an age with the private key for the corresponding age group of an age commitment. + */ +struct TALER_AgeAttestation +{ +#ifdef AGE_RESTRICTION_WITH_ECDSA + struct GNUNET_CRYPTO_EcdsaSignature signature; +#else + struct GNUNET_CRYPTO_Edx25519Signature signature; +#endif }; +#define TALER_AgeCommitmentHash_isNullOrZero(ph) ((NULL == ph) || \ + GNUNET_is_zero (ph)) /** * @brief Type of public signing keys for verifying blindly signed coins. */ struct TALER_DenominationPublicKey { + /** - * Taler uses RSA for signing coins. + * Age restriction mask used for the key. */ - struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key; + struct TALER_AgeMask age_mask; + + /** + * Type of the public key. + */ + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub_key; + }; @@ -328,10 +1263,22 @@ struct TALER_DenominationPublicKey */ struct TALER_DenominationPrivateKey { + + struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv_key; + +}; + + +/** + * @brief Blinded planchet send to exchange for blind signing. + */ +struct TALER_BlindedPlanchet +{ /** - * Taler uses RSA for signing coins. + * A blinded message. */ - struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key; + struct GNUNET_CRYPTO_BlindedMessage *blinded_message; + }; @@ -351,7 +1298,18 @@ struct TALER_CoinPublicInfo * Hash of the public key representing the denomination of the coin that is * being deposited. */ - struct GNUNET_HashCode denom_pub_hash; + struct TALER_DenominationHashP denom_pub_hash; + + /** + * Hash of the age commitment. If no age commitment was provided, it must be + * set to all zeroes. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * True, if age commitment is not applicable. + */ + bool no_age_commitment; /** * (Unblinded) signature over @e coin_pub with @e denom_pub, @@ -370,7 +1328,7 @@ struct TALER_TrackTransferDetails /** * Hash of the proposal data. */ - struct GNUNET_HashCode h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Which coin was deposited? @@ -378,19 +1336,391 @@ struct TALER_TrackTransferDetails struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Value of the deposit (including fee). + * Value of the deposit (including fee), after refunds. */ struct TALER_Amount coin_value; /** - * Fee charged by the exchange for the deposit. + * Fee charged by the exchange for the deposit, + * possibly reduced (or waived) due to refunds. */ struct TALER_Amount coin_fee; + /** + * Total amount of refunds applied to this coin. + */ + struct TALER_Amount refund_total; + +}; + + +/** + * @brief Inputs needed from the exchange for blind signing. + */ +struct TALER_ExchangeWithdrawValues +{ + + /** + * Input values. + */ + struct GNUNET_CRYPTO_BlindingInputValues *blinding_inputs; }; /** + * Return the alg value singleton for creation of + * blinding secrets for RSA. + * + * @return singleton to use for RSA blinding + */ +const struct TALER_ExchangeWithdrawValues * +TALER_denom_ewv_rsa_singleton (void); + + +/** + * Make a (deep) copy of the given @a bi_src to + * @a bi_dst. + * + * @param[out] bi_dst target to copy to + * @param bi_src blinding input values to copy + */ +void +TALER_denom_ewv_copy ( + struct TALER_ExchangeWithdrawValues *bi_dst, + const struct TALER_ExchangeWithdrawValues *bi_src); + + +/** + * Create private key for a Taler coin. + * @param ps planchet secret to derive coin priv key + * @param alg_values includes algorithm specific values + * @param[out] coin_priv private key to initialize + */ +void +TALER_planchet_setup_coin_priv ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_CoinSpendPrivateKeyP *coin_priv); + + +/** + * @brief Method to derive withdraw /csr nonce + * + * @param ps planchet secrets of the coin + * @param[out] nonce withdraw nonce included in the request to generate R_0 and R_1 + */ +void +TALER_cs_withdraw_nonce_derive ( + const struct TALER_PlanchetMasterSecretP *ps, + struct GNUNET_CRYPTO_CsSessionNonce *nonce); + + +/** + * @brief Method to derive /csr nonce + * to be used during refresh/melt operation. + * + * @param rms secret input for the refresh operation + * @param idx index of the fresh coin + * @param[out] nonce set to nonce included in the request to generate R_0 and R_1 + */ +void +TALER_cs_refresh_nonce_derive ( + const struct TALER_RefreshMasterSecretP *rms, + uint32_t idx, + struct GNUNET_CRYPTO_CsSessionNonce *nonce); + + +/** + * Initialize denomination public-private key pair. + * + * For #GNUNET_CRYPTO_BSA_RSA, an additional "unsigned int" + * argument with the number of bits for 'n' (e.g. 2048) must + * be passed. + * + * @param[out] denom_priv where to write the private key + * @param[out] denom_pub where to write the public key + * @param cipher which type of cipher to use + * @param ... RSA key size (eg. 2048/3072/4096) + * @return #GNUNET_OK on success, #GNUNET_NO if parameters were invalid + */ +enum GNUNET_GenericReturnValue +TALER_denom_priv_create (struct TALER_DenominationPrivateKey *denom_priv, + struct TALER_DenominationPublicKey *denom_pub, + enum 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 + */ +void +TALER_denom_priv_free (struct TALER_DenominationPrivateKey *denom_priv); + + +/** + * Free internals of @a denom_sig, but not @a denom_sig itself. + * + * @param[in] denom_sig signature to free + */ +void +TALER_denom_sig_free (struct TALER_DenominationSignature *denom_sig); + + +/** + * Blind coin for blind signing with @a dk using blinding secret @a coin_bks. + * + * NOTE: As a particular oddity, the @a blinded_planchet is only partially + * initialized by this function in the case of CS-denominations. Here, the + * 'nonce' must be initialized separately! + * + * @param dk denomination public key to blind for + * @param coin_bks blinding secret to use + * @param nonce nonce used to derive session values, + * could be NULL for ciphers that do not use it + * @param age_commitment_hash hash of the age commitment to be used for the coin. NULL if no commitment is made. + * @param coin_pub public key of the coin to blind + * @param alg_values algorithm specific values to blind the planchet + * @param[out] c_hash resulting hashed coin + * @param[out] blinded_planchet planchet data to initialize + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_denom_blind (const struct TALER_DenominationPublicKey *dk, + 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, + struct TALER_CoinPubHashP *c_hash, + struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * Create blinded signature. + * + * @param[out] denom_sig where to write the signature + * @param denom_priv private key to use for signing + * @param for_melt true to use the HKDF for melt + * @param blinded_planchet the planchet already blinded + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_denom_sign_blinded (struct TALER_BlindedDenominationSignature *denom_sig, + const struct TALER_DenominationPrivateKey *denom_priv, + bool for_melt, + const struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * Unblind blinded signature. + * + * @param[out] denom_sig where to write the unblinded signature + * @param bdenom_sig the blinded signature + * @param bks blinding secret to use + * @param c_hash hash of the coin's public key for verification of the signature + * @param alg_values algorithm specific values + * @param denom_pub public key used for signing + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_denom_sig_unblind ( + struct TALER_DenominationSignature *denom_sig, + const struct TALER_BlindedDenominationSignature *bdenom_sig, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Free internals of @a denom_sig, but not @a denom_sig itself. + * + * @param[in] denom_sig signature to free + */ +void +TALER_blinded_denom_sig_free ( + struct TALER_BlindedDenominationSignature *denom_sig); + + +/** + * Compute the hash of the given @a denom_pub. + * + * @param denom_pub public key to hash + * @param[out] denom_hash resulting hash value + */ +void +TALER_denom_pub_hash (const struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationHashP *denom_hash); + + +/** + * Make a (deep) copy of the given @a denom_src to + * @a denom_dst. + * + * @param[out] denom_dst target to copy to + * @param denom_src public key to copy + */ +void +TALER_denom_pub_copy (struct TALER_DenominationPublicKey *denom_dst, + const struct TALER_DenominationPublicKey *denom_src); + + +/** + * Make a (deep) copy of the given @a denom_src to + * @a denom_dst. + * + * @param[out] denom_dst target to copy to + * @param denom_src public key to copy + */ +void +TALER_denom_sig_copy (struct TALER_DenominationSignature *denom_dst, + const struct TALER_DenominationSignature *denom_src); + + +/** + * Make a (deep) copy of the given @a denom_src to + * @a denom_dst. + * + * @param[out] denom_dst target to copy to + * @param denom_src public key to copy + */ +void +TALER_blinded_denom_sig_copy ( + struct TALER_BlindedDenominationSignature *denom_dst, + const struct TALER_BlindedDenominationSignature *denom_src); + + +/** + * Compare two denomination public keys. + * + * @param denom1 first key + * @param denom2 second key + * @return 0 if the keys are equal, otherwise -1 or 1 + */ +int +TALER_denom_pub_cmp (const struct TALER_DenominationPublicKey *denom1, + const struct TALER_DenominationPublicKey *denom2); + + +/** + * Compare two denomination signatures. + * + * @param sig1 first signature + * @param sig2 second signature + * @return 0 if the keys are equal, otherwise -1 or 1 + */ +int +TALER_denom_sig_cmp (const struct TALER_DenominationSignature *sig1, + const struct TALER_DenominationSignature *sig2); + + +/** + * Compare two blinded denomination signatures. + * + * @param sig1 first signature + * @param sig2 second signature + * @return 0 if the keys are equal, otherwise -1 or 1 + */ +int +TALER_blinded_denom_sig_cmp ( + const struct TALER_BlindedDenominationSignature *sig1, + const struct TALER_BlindedDenominationSignature *sig2); + + +/** + * Compare two blinded planchets. + * + * @param bp1 first blinded planchet + * @param bp2 second blinded planchet + * @return 0 if the keys are equal, otherwise -1 or 1 + */ +int +TALER_blinded_planchet_cmp ( + const struct TALER_BlindedPlanchet *bp1, + const struct TALER_BlindedPlanchet *bp2); + + +/** + * Verify signature made with a denomination public key + * over a coin. + * + * @param denom_pub public denomination key + * @param denom_sig signature made with the private key + * @param c_hash hash over the coin + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_denom_pub_verify (const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_CoinPubHashP *c_hash); + + +/** + * Encrypts KYC attributes for storage in the database. + * + * @param key encryption key to use + * @param attr set of attributes to encrypt + * @param[out] enc_attr encrypted attribute data + * @param[out] enc_attr_size number of bytes in @a enc_attr + */ +void +TALER_CRYPTO_kyc_attributes_encrypt ( + const struct TALER_AttributeEncryptionKeyP *key, + const json_t *attr, + void **enc_attr, + size_t *enc_attr_size); + + +/** + * Encrypts KYC attributes for storage in the database. + * + * @param key encryption key to use + * @param enc_attr encrypted attribute data + * @param enc_attr_size number of bytes in @a enc_attr + * @return set of decrypted attributes, NULL on failure + */ +json_t * +TALER_CRYPTO_kyc_attributes_decrypt ( + const struct TALER_AttributeEncryptionKeyP *key, + const void *enc_attr, + size_t enc_attr_size); + + +/** + * Takes a set of KYC attributes and extracts key + * data that we use to detect similar / duplicate + * entries in the database. + * + * @param attr set of KYC attributes + * @param[out] kyc_prox set to the proximity hash + */ +void +TALER_CRYPTO_attributes_to_kyc_prox ( + const json_t *attr, + struct GNUNET_ShortHashCode *kyc_prox); + + +/** * Check if a coin is valid; that is, whether the denomination key exists, * is not expired, and the signature is correct. * @@ -400,36 +1730,46 @@ struct TALER_TrackTransferDetails * #GNUNET_NO if it is invalid * #GNUNET_SYSERR if an internal error occurred */ -int +enum GNUNET_GenericReturnValue TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info, const struct TALER_DenominationPublicKey *denom_pub); -GNUNET_NETWORK_STRUCT_BEGIN - /** - * Header for serializations of coin-specific information about the - * fresh coins we generate. These are the secrets that arise during - * planchet generation, which is the first stage of creating a new - * coin. + * Compute the hash of a blinded coin. + * + * @param blinded_planchet blinded planchet + * @param denom_hash hash of the denomination public key + * @param[out] bch where to write the hash */ -struct TALER_PlanchetSecretsP -{ - - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; +void +TALER_coin_ev_hash (const struct TALER_BlindedPlanchet *blinded_planchet, + const struct TALER_DenominationHashP *denom_hash, + struct TALER_BlindedCoinHashP *bch); - /** - * The blinding key. - */ - struct TALER_DenominationBlindingKeyP blinding_key; -}; +/** + * Compute the hash of a coin. + * + * @param coin_pub public key of the coin + * @param age_commitment_hash hash of the age commitment vector. NULL, if no age commitment was set + * @param[out] coin_h where to write the hash + */ +void +TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_AgeCommitmentHash *age_commitment_hash, + struct TALER_CoinPubHashP *coin_h); -GNUNET_NETWORK_STRUCT_END +/** + * Compute the hash of a payto URI. + * + * @param payto URI to hash + * @param[out] h_payto where to write the hash + */ +void +TALER_payto_hash (const char *payto, + struct TALER_PaytoHashP *h_payto); /** @@ -443,17 +1783,12 @@ struct TALER_PlanchetDetail /** * Hash of the denomination public key. */ - struct GNUNET_HashCode denom_pub_hash; + struct TALER_DenominationHashP denom_pub_hash; /** - * Blinded coin (see GNUNET_CRYPTO_rsa_blind()). Note: is malloc()'ed! + * The blinded planchet */ - void *coin_ev; - - /** - * Number of bytes in @a coin_ev. - */ - size_t coin_ev_size; + struct TALER_BlindedPlanchet blinded_planchet; }; @@ -475,6 +1810,10 @@ struct TALER_FreshCoin */ struct TALER_CoinSpendPrivateKeyP coin_priv; + /** + * Optional hash of an age commitment bound to this coin, maybe NULL. + */ + const struct TALER_AgeCommitmentHash *h_age_commitment; }; @@ -529,6 +1868,19 @@ struct TALER_WireTransferIdentifierRawP /** + * Raw value of a wire transfer subject for a wad. + */ +struct TALER_WadIdentifierP +{ + + /** + * Wad identifier, in binary encoding. + */ + uint8_t raw[24]; +}; + + +/** * Binary information encoded in Crockford's Base32 in wire transfer * subjects of transfers from Taler to a merchant. The actual value * is chosen by the exchange and has no particular semantics, other than @@ -554,44 +1906,121 @@ GNUNET_NETWORK_STRUCT_END /** - * Setup information for a fresh coin, deriving the coin private key - * and the blinding factor from the @a secret_seed with a KDF salted - * by the @a coin_num_salt. + * Setup information for a fresh coin, deriving the coin planchet secrets from + * which we will later derive the private key and the blinding factor. The + * planchet secrets derivation is based on the @a secret_seed with a KDF + * salted by the @a coin_num_salt. * * @param secret_seed seed to use for KDF to derive coin keys * @param coin_num_salt number of the coin to include in KDF * @param[out] ps value to initialize */ void -TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed, - uint32_t coin_num_salt, - struct TALER_PlanchetSecretsP *ps); +TALER_transfer_secret_to_planchet_secret ( + const struct TALER_TransferSecretP *secret_seed, + uint32_t coin_num_salt, + struct TALER_PlanchetMasterSecretP *ps); + + +/** + * Derive the @a coin_num transfer private key @a tpriv from a refresh from + * the @a rms seed and the @a old_coin_pub of the refresh operation. The + * transfer private key derivation is based on the @a ps with a KDF salted by + * the @a coin_num. + * + * @param rms seed to use for KDF to derive transfer keys + * @param old_coin_priv private key of the old coin + * @param cnc_num cut and choose number to include in KDF + * @param[out] tpriv value to initialize + */ +void +TALER_planchet_secret_to_transfer_priv ( + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, + uint32_t cnc_num, + struct TALER_TransferPrivateKeyP *tpriv); /** - * Setup information for a fresh coin. + * Setup secret seed information for fresh coins to be + * withdrawn. * * @param[out] ps value to initialize */ void -TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps); +TALER_planchet_master_setup_random ( + struct TALER_PlanchetMasterSecretP *ps); /** - * Prepare a planchet for tipping. Creates and blinds a coin. + * Setup secret seed for fresh coins to be refreshed. + * + * @param[out] rms value to initialize + */ +void +TALER_refresh_master_setup_random ( + struct TALER_RefreshMasterSecretP *rms); + + +/** + * Create a blinding secret @a bks given the client's @a ps and the alg_values + * from the exchange. + * + * @param ps secret to derive blindings from + * @param alg_values withdraw values containing cipher and additional CS values + * @param[out] bks blinding secrets + */ +void +TALER_planchet_blinding_secret_create ( + const struct TALER_PlanchetMasterSecretP *ps, + const struct TALER_ExchangeWithdrawValues *alg_values, + union GNUNET_CRYPTO_BlindingSecretP *bks); + + +/** + * Prepare a planchet for withdrawal. Creates and blinds a coin. * * @param dk denomination key for the coin to be created - * @param ps secret planchet internals (for #TALER_planchet_to_coin) + * @param alg_values algorithm specific values + * @param bks blinding secrets + * @param nonce session nonce used to get @a alg_values + * @param coin_priv coin private key + * @param ach hash of age commitment to bind to this coin, maybe NULL * @param[out] c_hash set to the hash of the public key of the coin (needed later) * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and - * other withdraw operations + * other withdraw operations, `pd->blinded_planchet.cipher` will be set + * to cipher from @a dk * @return #GNUNET_OK on success */ -int -TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, - const struct TALER_PlanchetSecretsP *ps, - struct GNUNET_HashCode *c_hash, - struct TALER_PlanchetDetail *pd); +enum GNUNET_GenericReturnValue +TALER_planchet_prepare ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_ExchangeWithdrawValues *alg_values, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + struct TALER_CoinPubHashP *c_hash, + struct TALER_PlanchetDetail *pd); + + +/** + * Frees blinded message inside blinded planchet depending on `blinded_planchet->cipher`. + * Does not free the @a blinded_planchet itself! + * + * @param[in] blinded_planchet blinded planchet + */ +void +TALER_blinded_planchet_free (struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * Frees blinded message inside planchet detail @a pd. + * + * @param[in] pd planchet detail to free + */ +void +TALER_planchet_detail_free (struct TALER_PlanchetDetail *pd); /** @@ -600,20 +2029,36 @@ TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk, * * @param dk denomination key, must match what was given to #TALER_planchet_prepare() * @param blind_sig blind signature from the exchange - * @param ps secrets from #TALER_planchet_prepare() + * @param bks blinding key secret + * @param coin_priv private key of the coin + * @param ach hash of age commitment that is bound to this coin, maybe NULL * @param c_hash hash of the coin's public key for verification of the signature + * @param alg_values values obtained from the exchange for the withdrawal * @param[out] coin set to the details of the fresh coin * @return #GNUNET_OK on success */ -int -TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig, - const struct TALER_PlanchetSecretsP *ps, - const struct GNUNET_HashCode *c_hash, - struct TALER_FreshCoin *coin); +enum GNUNET_GenericReturnValue +TALER_planchet_to_coin ( + const struct TALER_DenominationPublicKey *dk, + const struct TALER_BlindedDenominationSignature *blind_sig, + const union GNUNET_CRYPTO_BlindingSecretP *bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentHash *ach, + const struct TALER_CoinPubHashP *c_hash, + const struct TALER_ExchangeWithdrawValues *alg_values, + struct TALER_FreshCoin *coin); -/* ****************** Refresh crypto primitives ************* */ +/** + * Add the hash of the @a bp (in some canonicalized form) + * to the @a hash_context. + * + * @param bp blinded planchet to hash + * @param[in,out] hash_context hash context to use + */ +void +TALER_blinded_planchet_hash_ (const struct TALER_BlindedPlanchet *bp, + struct GNUNET_HashContext *hash_context); /** @@ -676,14 +2121,9 @@ struct TALER_RefreshCoinData const struct TALER_DenominationPublicKey *dk; /** - * The envelope with the blinded coin. + * The blinded planchet (details depend on cipher). */ - void *coin_ev; - - /** - * Number of bytes in @a coin_ev - */ - size_t coin_ev_size; + struct TALER_BlindedPlanchet blinded_planchet; }; @@ -711,6 +2151,7 @@ struct TALER_RefreshCommitmentEntry * * @param[out] rc set to the value the wallet must commit to * @param kappa number of transfer public keys involved (must be #TALER_CNC_KAPPA) + * @param rms refresh master secret to include, can be NULL! * @param num_new_coins number of new coins to be created * @param rcs array of @a kappa commitments * @param coin_pub public key of the coin to be melted @@ -719,38 +2160,3306 @@ struct TALER_RefreshCommitmentEntry void TALER_refresh_get_commitment (struct TALER_RefreshCommitmentP *rc, uint32_t kappa, + const struct TALER_RefreshMasterSecretP *rms, uint32_t num_new_coins, const struct TALER_RefreshCommitmentEntry *rcs, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *amount_with_fee); +/** + * Encrypt contract for transmission to a party that will + * merge it into a reserve. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param merge_priv merge capability to include + * @param contract_terms contract terms to encrypt + * @param[out] econtract set to encrypted contract + * @param[out] econtract_size set to number of bytes in @a econtract + */ +void +TALER_CRYPTO_contract_encrypt_for_merge ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const json_t *contract_terms, + void **econtract, + size_t *econtract_size); + + +/** + * Decrypt contract for the party that will + * merge it into a reserve. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param[out] merge_priv set to merge capability + * @return decrypted contract terms, or NULL on failure + */ +json_t * +TALER_CRYPTO_contract_decrypt_for_merge ( + const struct TALER_ContractDiffiePrivateP *contract_priv, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const void *econtract, + size_t econtract_size, + struct TALER_PurseMergePrivateKeyP *merge_priv); + + +/** + * Encrypt contract for transmission to a party that will + * pay for it. + * + * @param purse_pub public key of the purse + * @param contract_priv private key of the contract + * @param contract_terms contract terms to encrypt + * @param[out] econtract set to encrypted contract + * @param[out] econtract_size set to number of bytes in @a econtract + */ +void +TALER_CRYPTO_contract_encrypt_for_deposit ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + void **econtract, + size_t *econtract_size); + + +/** + * Decrypt contract for the party that will pay for it. + * + * @param contract_priv private key of the contract + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @return decrypted contract terms, or NULL on failure + */ +json_t * +TALER_CRYPTO_contract_decrypt_for_deposit ( + const struct TALER_ContractDiffiePrivateP *contract_priv, + const void *econtract, + size_t econtract_size); + + +/* **************** AML officer signatures **************** */ + +/** + * Sign AML query. Simple authentication, doesn't actually + * sign anything. + * + * @param officer_priv private key of AML officer + * @param[out] officer_sig where to write the signature + */ +void +TALER_officer_aml_query_sign ( + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Verify AML query authorization. + * + * @param officer_pub public key of AML officer + * @param officer_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_officer_aml_query_verify ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Sign AML decision. + * + * @param justification human-readable justification + * @param decision_time when was the decision made + * @param new_threshold at what monthly amount threshold + * should a revision be triggered + * @param h_payto payto URI hash of the account the + * decision is about + * @param new_state updated AML state + * @param kyc_requirements additional KYC requirements to + * impose, can be NULL + * @param officer_priv private key of AML officer + * @param[out] officer_sig where to write the signature + */ +void +TALER_officer_aml_decision_sign ( + const char *justification, + struct GNUNET_TIME_Timestamp decision_time, + const struct TALER_Amount *new_threshold, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState new_state, + const json_t *kyc_requirements, + const struct TALER_AmlOfficerPrivateKeyP *officer_priv, + struct TALER_AmlOfficerSignatureP *officer_sig); + + +/** + * Verify AML decision. + * + * @param justification human-readable justification + * @param decision_time when was the decision made + * @param new_threshold at what monthly amount threshold + * should a revision be triggered + * @param h_payto payto URI hash of the account the + * decision is about + * @param new_state updated AML state + * @param kyc_requirements additional KYC requirements to + * impose, can be NULL + * @param officer_pub public key of AML officer + * @param officer_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_officer_aml_decision_verify ( + const char *justification, + struct GNUNET_TIME_Timestamp decision_time, + const struct TALER_Amount *new_threshold, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState new_state, + const json_t *kyc_requirements, + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const struct TALER_AmlOfficerSignatureP *officer_sig); + + +/* **************** Helper-based RSA operations **************** */ + +/** + * Handle for talking to an Denomination key signing helper. + */ +struct TALER_CRYPTO_RsaDenominationHelper; + +/** + * Function called with information about available keys for signing. Usually + * only called once per key upon connect. Also called again in case a key is + * being revoked, in that case with an @a end_time of zero. + * + * @param cls closure + * @param section_name name of the denomination type in the configuration; + * NULL if the key has been revoked or purged + * @param start_time when does the key become available for signing; + * zero if the key has been revoked or purged + * @param validity_duration how long does the key remain available for signing; + * zero if the key has been revoked or purged + * @param h_rsa hash of the RSA @a denom_pub that is available (or was 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. + */ +typedef void +(*TALER_CRYPTO_RsaDenominationKeyStatusCallback)( + void *cls, + const char *section_name, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Relative validity_duration, + const struct TALER_RsaPubHashP *h_rsa, + struct GNUNET_CRYPTO_BlindSignPublicKey *bs_pub, + const struct TALER_SecurityModulePublicKeyP *sm_pub, + const struct TALER_SecurityModuleSignatureP *sm_sig); + + +/** + * Initiate connection to an denomination key helper. + * + * @param cfg configuration to use + * @param section configuration section prefix to use, usually 'taler' or 'donau' + * @param dkc function to call with key information + * @param dkc_cls closure for @a dkc + * @return NULL on error (such as bad @a cfg). + */ +struct TALER_CRYPTO_RsaDenominationHelper * +TALER_CRYPTO_helper_rsa_connect ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + TALER_CRYPTO_RsaDenominationKeyStatusCallback dkc, + void *dkc_cls); + + +/** + * Function to call to 'poll' for updates to the available key material. + * Should be called whenever it is important that the key material status is + * current, like when handling a "/keys" request. This function basically + * briefly checks if there are messages from the helper announcing changes to + * denomination keys. + * + * @param dh helper process connection + */ +void +TALER_CRYPTO_helper_rsa_poll (struct TALER_CRYPTO_RsaDenominationHelper *dh); + + +/** + * Information needed for an RSA signature request. + */ +struct TALER_CRYPTO_RsaSignRequest +{ + /** + * Hash of the RSA public key. + */ + const struct TALER_RsaPubHashP *h_rsa; + + /** + * Message to be (blindly) signed. + */ + const void *msg; + + /** + * Number of bytes in @e msg. + */ + size_t msg_size; +}; + + +/** + * Request helper @a dh to sign message in @a rsr using the public key + * corresponding to the key in @a rsr. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper process connection + * @param rsr details about the requested signature + * @param[out] bs set to the blind signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_rsa_sign ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + const struct TALER_CRYPTO_RsaSignRequest *rsr, + struct TALER_BlindedDenominationSignature *bs); + + +/** + * Request helper @a dh to batch sign messages in @a rsrs using the public key + * corresponding to the keys in @a rsrs. + * + * This operation will block until all the signatures have been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * Note that in case of errors, the @a bss array may still have been partially + * filled with signatures, which in this case must be freed by the caller + * (this is in contrast to the #TALER_CRYPTO_helper_rsa_sign() API which never + * returns any signatures if there was an error). + * + * @param dh helper process connection + * @param rsrs array with details about the requested signatures + * @param rsrs_length length of the @a rsrs array + * @param[out] bss array set to the blind signatures, must be of length @a rsrs_length! + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_rsa_batch_sign ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + unsigned int rsrs_length, + const struct TALER_CRYPTO_RsaSignRequest rsrs[static rsrs_length], + struct TALER_BlindedDenominationSignature bss[static rsrs_length]); + + +/** + * Ask the helper to revoke the public key associated with @a h_denom_pub. + * Will cause the helper to tell all clients that the key is now unavailable, + * and to create a replacement key. + * + * This operation will block until the revocation request has been + * transmitted. Should this process receive a signal (that is not ignored) + * while the operation is pending, the operation may fail. If the key is + * unknown, this function will also appear to have succeeded. To be sure that + * the revocation worked, clients must watch the denomination key status + * callback. + * + * @param dh helper to process connection + * @param h_rsa hash of the RSA public key to revoke + */ +void +TALER_CRYPTO_helper_rsa_revoke ( + struct TALER_CRYPTO_RsaDenominationHelper *dh, + const struct TALER_RsaPubHashP *h_rsa); + + +/** + * Close connection to @a dh. + * + * @param[in] dh connection to close + */ +void +TALER_CRYPTO_helper_rsa_disconnect ( + struct TALER_CRYPTO_RsaDenominationHelper *dh); + + +/* **************** Helper-based CS operations **************** */ + +/** + * Handle for talking to an Denomination key signing helper. + */ +struct TALER_CRYPTO_CsDenominationHelper; + +/** + * Function called with information about available keys for signing. Usually + * only called once per key upon connect. Also called again in case a key is + * being revoked, in that case with an @a end_time of zero. + * + * @param cls closure + * @param section_name name of the denomination type in the configuration; + * NULL if the key has been revoked or purged + * @param start_time when does the key become available for signing; + * zero if the key has been revoked or purged + * @param validity_duration how long does the key remain available for signing; + * zero if the key has been revoked or purged + * @param h_cs hash of the CS @a denom_pub that is available (or was purged) + * @param bsign_pub the public key itself, NULL if the key was revoked or purged + * @param sm_pub public key of the security module, NULL if the key was revoked or purged + * @param sm_sig signature from the security module, NULL if the key was revoked or purged + * The signature was already verified against @a sm_pub. + */ +typedef void +(*TALER_CRYPTO_CsDenominationKeyStatusCallback)( + void *cls, + const char *section_name, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Relative validity_duration, + const struct TALER_CsPubHashP *h_cs, + struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub, + const struct TALER_SecurityModulePublicKeyP *sm_pub, + const struct TALER_SecurityModuleSignatureP *sm_sig); + + +/** + * Initiate connection to an denomination key helper. + * + * @param cfg configuration to use + * @param section configuration section prefix to use, usually 'taler' or 'donau' + * @param dkc function to call with key information + * @param dkc_cls closure for @a dkc + * @return NULL on error (such as bad @a cfg). + */ +struct TALER_CRYPTO_CsDenominationHelper * +TALER_CRYPTO_helper_cs_connect ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *section, + TALER_CRYPTO_CsDenominationKeyStatusCallback dkc, + void *dkc_cls); + + +/** + * Function to call to 'poll' for updates to the available key material. + * Should be called whenever it is important that the key material status is + * current, like when handling a "/keys" request. This function basically + * briefly checks if there are messages from the helper announcing changes to + * denomination keys. + * + * @param dh helper process connection + */ +void +TALER_CRYPTO_helper_cs_poll (struct TALER_CRYPTO_CsDenominationHelper *dh); + + +/** + * Information about what we should sign over. + */ +struct TALER_CRYPTO_CsSignRequest +{ + /** + * Hash of the CS public key to use to sign. + */ + const struct TALER_CsPubHashP *h_cs; + + /** + * Blinded planchet containing c and the nonce. + */ + const struct GNUNET_CRYPTO_CsBlindedMessage *blinded_planchet; + +}; + + +/** + * Request helper @a dh to sign @a req. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper process connection + * @param req information about the key to sign with and the value to sign + * @param for_melt true if for melt operation + * @param[out] bs set to the blind signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_sign ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CRYPTO_CsSignRequest *req, + bool for_melt, + struct TALER_BlindedDenominationSignature *bs); + + +/** + * Request helper @a dh to sign batch of @a reqs requests. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper process connection + * @param reqs information about the keys to sign with and the values to sign + * @param reqs_length length of the @a reqs array + * @param for_melt true if this is for a melt operation + * @param[out] bss array set to the blind signatures, must be of length @a reqs_length! + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_batch_sign ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + unsigned int reqs_length, + const struct TALER_CRYPTO_CsSignRequest reqs[static reqs_length], + bool for_melt, + struct TALER_BlindedDenominationSignature bss[static reqs_length]); + + +/** + * Ask the helper to revoke the public key associated with @a h_cs. + * Will cause the helper to tell all clients that the key is now unavailable, + * and to create a replacement key. + * + * This operation will block until the revocation request has been + * transmitted. Should this process receive a signal (that is not ignored) + * while the operation is pending, the operation may fail. If the key is + * unknown, this function will also appear to have succeeded. To be sure that + * the revocation worked, clients must watch the denomination key status + * callback. + * + * @param dh helper to process connection + * @param h_cs hash of the CS public key to revoke + */ +void +TALER_CRYPTO_helper_cs_revoke ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CsPubHashP *h_cs); + + +/** + * Information about what we should derive for. + */ +struct TALER_CRYPTO_CsDeriveRequest +{ + /** + * Hash of the CS public key to use to sign. + */ + const struct TALER_CsPubHashP *h_cs; + + /** + * Nonce to use for the /csr request. + */ + const struct GNUNET_CRYPTO_CsSessionNonce *nonce; +}; + + +/** + * Ask the helper to derive R using the information + * from @a cdr. + * + * This operation will block until the R has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper to process connection + * @param cdr derivation input data + * @param for_melt true if this is for a melt operation + * @param[out] crp set to the pair of R values + * @return set to the error code (or #TALER_EC_NONE on success) + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_r_derive ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + const struct TALER_CRYPTO_CsDeriveRequest *cdr, + bool for_melt, + struct GNUNET_CRYPTO_CSPublicRPairP *crp); + + +/** + * Ask the helper to derive R using the information from @a cdrs. + * + * This operation will block until the R has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param dh helper to process connection + * @param cdrs_length length of the @a cdrs array + * @param cdrs array with derivation input data + * @param for_melt true if this is for a melt operation + * @param[out] crps array set to the pair of R values, must be of length @a cdrs_length + * @return set to the error code (or #TALER_EC_NONE on success) + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_cs_r_batch_derive ( + struct TALER_CRYPTO_CsDenominationHelper *dh, + unsigned int cdrs_length, + const struct TALER_CRYPTO_CsDeriveRequest cdrs[static cdrs_length], + bool for_melt, + struct GNUNET_CRYPTO_CSPublicRPairP crps[static cdrs_length]); + + +/** + * Close connection to @a dh. + * + * @param[in] dh connection to close + */ +void +TALER_CRYPTO_helper_cs_disconnect ( + struct TALER_CRYPTO_CsDenominationHelper *dh); + +/** + * Handle for talking to an online key signing helper. + */ +struct TALER_CRYPTO_ExchangeSignHelper; + +/** + * Function called with information about available keys for signing. Usually + * only called once per key upon connect. Also called again in case a key is + * being revoked, in that case with an @a end_time of zero. + * + * @param cls closure + * @param start_time when does the key become available for signing; + * zero if the key has been revoked or purged + * @param validity_duration how long does the key remain available for signing; + * zero if the key has been revoked or purged + * @param exchange_pub the public key itself, NULL if the key was revoked or purged + * @param sm_pub public key of the security module, NULL if the key was revoked or purged + * @param sm_sig signature from the security module, NULL if the key was revoked or purged + * The signature was already verified against @a sm_pub. + */ +typedef void +(*TALER_CRYPTO_ExchangeKeyStatusCallback)( + void *cls, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Relative validity_duration, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_SecurityModulePublicKeyP *sm_pub, + const struct TALER_SecurityModuleSignatureP *sm_sig); + + +/** + * 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). + */ +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); + + +/** + * Function to call to 'poll' for updates to the available key material. + * Should be called whenever it is important that the key material status is + * current, like when handling a "/keys" request. This function basically + * briefly checks if there are messages from the helper announcing changes to + * exchange online signing keys. + * + * @param esh helper process connection + */ +void +TALER_CRYPTO_helper_esign_poll (struct TALER_CRYPTO_ExchangeSignHelper *esh); + + +/** + * Request helper @a esh to sign @a msg using the current online + * signing key. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param esh helper process connection + * @param purpose message to sign (must extend beyond the purpose) + * @param[out] exchange_pub set to the public key used for the signature upon success + * @param[out] exchange_sig set to the signature upon success + * @return the error code (or #TALER_EC_NONE on success) + */ +enum TALER_ErrorCode +TALER_CRYPTO_helper_esign_sign_ ( + struct TALER_CRYPTO_ExchangeSignHelper *esh, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_ExchangeSignatureP *exchange_sig); + + +/** + * Request helper @a esh to sign @a msg using the current online + * signing key. + * + * This operation will block until the signature has been obtained. Should + * this process receive a signal (that is not ignored) while the operation is + * pending, the operation will fail. Note that the helper may still believe + * that it created the signature. Thus, signals may result in a small + * differences in the signature counters. Retrying in this case may work. + * + * @param esh helper process connection + * @param ps message to sign (MUST begin with a purpose) + * @param[out] epub set to the public key used for the signature upon success + * @param[out] esig set to the signature upon success + * @return the error code (or #TALER_EC_NONE on success) + */ +#define TALER_CRYPTO_helper_esign_sign(esh,ps,epub,esig) ( \ + /* check size is set correctly */ \ + GNUNET_assert (ntohl ((ps)->purpose.size) == sizeof (*ps)), \ + /* check 'ps' begins with the purpose */ \ + GNUNET_static_assert (((void*) (ps)) == \ + ((void*) &(ps)->purpose)), \ + TALER_CRYPTO_helper_esign_sign_ (esh, \ + &(ps)->purpose, \ + epub, \ + esig) ) + + +/** + * Ask the helper to revoke the public key @a exchange_pub . + * Will cause the helper to tell all clients that the key is now unavailable, + * and to create a replacement key. + * + * This operation will block until the revocation request has been + * transmitted. Should this process receive a signal (that is not ignored) + * while the operation is pending, the operation may fail. If the key is + * unknown, this function will also appear to have succeeded. To be sure that + * the revocation worked, clients must watch the signing key status callback. + * + * @param esh helper to process connection + * @param exchange_pub the public key to revoke + */ +void +TALER_CRYPTO_helper_esign_revoke ( + struct TALER_CRYPTO_ExchangeSignHelper *esh, + const struct TALER_ExchangePublicKeyP *exchange_pub); + + +/** + * Close connection to @a esh. + * + * @param[in] esh connection to close + */ +void +TALER_CRYPTO_helper_esign_disconnect ( + struct TALER_CRYPTO_ExchangeSignHelper *esh); + + +/* ********************* wallet signing ************************** */ + + +/** + * Sign a request to create a purse. + * + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param merge_pub public key defining the merge capability + * @param min_age age restriction to apply for deposits into the purse + * @param amount total amount in the purse (including fees) + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_create_sign ( + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PurseMergePublicKeyP *merge_pub, + uint32_t min_age, + const struct TALER_Amount *amount, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse creation request. + * + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param merge_pub public key defining the merge capability + * @param min_age age restriction to apply for deposits into the purse + * @param amount total amount in the purse (including fees) + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_create_verify ( + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_PurseMergePublicKeyP *merge_pub, + uint32_t min_age, + const struct TALER_Amount *amount, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to delete a purse. + * + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_delete_sign ( + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse deletion request. + * + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_DELETE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_delete_verify ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to upload an encrypted contract. + * + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param contract_pub public key for the DH-encryption + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_econtract_upload_sign ( + const void *econtract, + size_t econtract_size, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a signature over encrypted contract. + * + * @param econtract encrypted contract + * @param econtract_size number of bytes in @a econtract + * @param contract_pub public key for the DH-encryption + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_econtract_upload_verify ( + const void *econtract, + size_t econtract_size, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a signature over encrypted contract. + * + * @param h_econtract hashed encrypted contract + * @param contract_pub public key for the DH-encryption + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_CREATE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_econtract_upload_verify2 ( + const struct GNUNET_HashCode *h_econtract, + const struct TALER_ContractDiffiePublicP *contract_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to inquire about a purse's status. + * + * @param purse_priv key identifying the purse + * @param[out] purse_sig resulting signature + */ +void +TALER_wallet_purse_status_sign ( + const struct TALER_PurseContractPrivateKeyP *purse_priv, + struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Verify a purse status request signature. + * + * @param purse_pub purse’s public key + * @param purse_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_STATUS + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_status_verify ( + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig); + + +/** + * Sign a request to deposit a coin into a purse. + * + * @param exchange_base_url URL of the exchange hosting the purse + * @param purse_pub purse’s public key + * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment + * @param coin_priv key identifying the coin to be deposited + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_purse_deposit_sign ( + const char *exchange_base_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify a purse deposit request. + * + * @param exchange_base_url URL of the exchange hosting the purse + * @param purse_pub purse’s public key + * @param amount amount of the coin's value to transfer to the purse + * @param h_denom_pub hash of the coin's denomination + * @param h_age_commitment hash of the coin's age commitment + * @param coin_pub key identifying the coin that is being deposited + * @param[out] coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_deposit_verify ( + const char *exchange_base_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *amount, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign a request by a purse to merge it into an account. + * + * @param reserve_uri identifies the location of the reserve + * @param merge_timestamp time when the merge happened + * @param purse_pub key identifying the purse + * @param merge_priv key identifying the merge capability + * @param[out] merge_sig resulting signature + */ +void +TALER_wallet_purse_merge_sign ( + const char *reserve_uri, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + struct TALER_PurseMergeSignatureP *merge_sig); + + +/** + * Verify a purse merge request. + * + * @param reserve_uri identifies the location of the reserve + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param merge_pub public key of the merge capability + * @param merge_sig the signature made with purpose #TALER_SIGNATURE_WALLET_PURSE_MERGE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_purse_merge_verify ( + const char *reserve_uri, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + const struct TALER_PurseMergeSignatureP *merge_sig); + + +/** + * Flags for a merge signature. + */ +enum TALER_WalletAccountMergeFlags +{ + + /** + * A mode must be set. None is not a legal mode! + */ + TALER_WAMF_MODE_NONE = 0, + + /** + * We are merging a fully paid-up purse into a reserve. + */ + TALER_WAMF_MODE_MERGE_FULLY_PAID_PURSE = 1, + + /** + * We are creating a fresh purse, from the contingent + * of free purses that our account brings. + */ + TALER_WAMF_MODE_CREATE_FROM_PURSE_QUOTA = 2, + + /** + * The account owner is willing to pay the purse_fee for the purse to be + * created from the account balance. + */ + TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE = 3, + + /** + * Bitmask to AND the full flags with to get the mode. + */ + TALER_WAMF_MERGE_MODE_MASK = 3 + +}; + + +/** + * Sign a request by an account to merge a purse. + * + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param amount total amount in the purse (including fees) + * @param purse_fee purse fee the reserve will pay, + * only used if @a flags is #TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE + * @param min_age age restriction to apply for deposits into the purse + * @param flags flags for the operation + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_account_merge_sign ( + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *purse_fee, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify an account's request to merge a purse. + * + * @param merge_timestamp time when the merge happened + * @param purse_pub public key of the purse to merge + * @param purse_expiration when should the purse expire + * @param h_contract_terms contract the two parties agree on + * @param amount total amount in the purse (including fees) + * @param purse_fee purse fee the reserve will pay, + * only used if @a flags is #TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE + * @param min_age age restriction to apply for deposits into the purse + * @param flags flags for the operation + * @param reserve_pub account’s public key + * @param reserve_sig the signature made with purpose #TALER_SIGNATURE_WALLET_ACCOUNT_MERGE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_account_merge_verify ( + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_Amount *amount, + const struct TALER_Amount *purse_fee, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign a request to keep a reserve open. + * + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_open_sign ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify a request to keep a reserve open. + * + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_pub key identifying the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_open_verify ( + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign to deposit coin to pay for keeping a reserve open. + * + * @param coin_contribution how much the coin should contribute + * @param reserve_sig signature over the reserve open operation + * @param coin_priv private key of the coin + * @param[out] coin_sig signature by the coin + */ +void +TALER_wallet_reserve_open_deposit_sign ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify signature that deposits coin to pay for keeping a reserve open. + * + * @param coin_contribution how much the coin should contribute + * @param reserve_sig signature over the reserve open operation + * @param coin_pub public key of the coin + * @param coin_sig signature by the coin + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_open_deposit_verify ( + const struct TALER_Amount *coin_contribution, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign a request to close a reserve. + * + * @param request_timestamp when was the request created + * @param h_payto where to send the funds (NULL allowed to send + * to origin of the reserve) + * @param reserve_priv key identifying the reserve + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_close_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify wallet request to close an account. + * + * @param request_timestamp when was the request created + * @param h_payto where to send the funds (NULL/all zeros + * allowed to send to origin of the reserve) + * @param reserve_pub account’s public key + * @param reserve_sig the signature made with purpose #TALER_SIGNATURE_WALLET_RESERVE_CLOSE + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_close_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign a request by a wallet to perform a KYC check. + * + * @param reserve_priv key identifying the wallet/account + * @param balance_threshold the balance threshold the wallet is about to cross + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_account_setup_sign ( + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *balance_threshold, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify account setup request. + * + * @param reserve_pub reserve the setup request was for + * @param balance_threshold the balance threshold the wallet is about to cross + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_account_setup_verify ( + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *balance_threshold, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign request to the exchange to confirm certain + * @a details about the owner of a reserve. + * + * @param request_timestamp when was the request created + * @param details which attributes are requested + * @param reserve_priv private key of the reserve + * @param[out] reserve_sig where to store the signature + */ +void +TALER_wallet_reserve_attest_request_sign ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify request to the exchange to confirm certain + * @a details about the owner of a reserve. + * + * @param request_timestamp when was the request created + * @param details which attributes are requested + * @param reserve_pub public key of the reserve + * @param reserve_sig where to store the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_attest_request_verify ( + struct GNUNET_TIME_Timestamp request_timestamp, + const json_t *details, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign a deposit permission. Function for wallets. + * + * @param amount the amount to be deposited + * @param deposit_fee the deposit fee we expect to pay + * @param h_wire hash of the merchant’s account details + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param wallet_data_hash hash over wallet inputs into the contract (maybe NULL) + * @param h_age_commitment hash over the age commitment, if applicable to the denomination (maybe NULL) + * @param h_policy hash over the policy extension + * @param h_denom_pub hash of the coin denomination's public key + * @param coin_priv coin’s private key + * @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param[out] coin_sig set to the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT + */ +void +TALER_wallet_deposit_sign ( + const struct TALER_Amount *amount, + 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, + struct GNUNET_TIME_Timestamp wallet_timestamp, + const struct TALER_MerchantPublicKeyP *merchant_pub, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify a deposit permission. + * + * @param amount the amount to be deposited + * @param deposit_fee the deposit fee we expect to pay + * @param h_wire hash of the merchant’s account details + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param wallet_data_hash hash over wallet inputs into the contract (maybe NULL) + * @param h_age_commitment hash over the age commitment (maybe all zeroes, if not applicable to the denomination) + * @param h_policy hash over the policy extension + * @param h_denom_pub hash of the coin denomination's public key + * @param wallet_timestamp timestamp when the contract was finalized, must not be too far in the future + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param coin_pub coin’s public key + * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_deposit_verify ( + const struct TALER_Amount *amount, + 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, + struct GNUNET_TIME_Timestamp wallet_timestamp, + const struct TALER_MerchantPublicKeyP *merchant_pub, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign a melt request. + * + * @param amount_with_fee the amount to be melted (with fee) + * @param melt_fee the melt fee we expect to pay + * @param rc refresh session we are committed to + * @param h_denom_pub hash of the coin denomination's public key + * @param h_age_commitment hash of the age commitment (may be NULL) + * @param coin_priv coin’s private key + * @param[out] coin_sig set to the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT + */ +void +TALER_wallet_melt_sign ( + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *melt_fee, + const struct TALER_RefreshCommitmentP *rc, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify a melt request. + * + * @param amount_with_fee the amount to be melted (with fee) + * @param melt_fee the melt fee we expect to pay + * @param rc refresh session we are committed to + * @param h_denom_pub hash of the coin denomination's public key + * @param h_age_commitment hash of the age commitment (may be NULL) + * @param coin_pub coin’s public key + * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_MELT + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_melt_verify ( + const struct TALER_Amount *amount_with_fee, + const struct TALER_Amount *melt_fee, + const struct TALER_RefreshCommitmentP *rc, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign link data. + * + * @param h_denom_pub hash of the denomiantion public key of the new coin + * @param transfer_pub transfer public key + * @param bch blinded coin hash + * @param old_coin_priv private key to sign with + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_link_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_TransferPublicKeyP *transfer_pub, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_CoinSpendPrivateKeyP *old_coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify link signature. + * + * @param h_denom_pub hash of the denomiantion public key of the new coin + * @param transfer_pub transfer public key + * @param h_coin_ev hash of the coin envelope + * @param old_coin_pub old coin key that the link signature is for + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_link_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_TransferPublicKeyP *transfer_pub, + const struct TALER_BlindedCoinHashP *h_coin_ev, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Sign withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_priv private key to sign with + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_withdraw_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify withdraw request. + * + * @param h_denom_pub hash of the denomiantion public key of the coin to withdraw + * @param amount_with_fee amount to debit the reserve for + * @param bch blinded coin hash + * @param reserve_pub public key of the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_withdraw_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_Amount *amount_with_fee, + const struct TALER_BlindedCoinHashP *bch, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Sign age-withdraw request. + * + * @param h_commitment hash over all n*kappa blinded coins in the commitment for the age-withdraw + * @param amount_with_fee amount to debit the reserve for + * @param mask the mask that defines the age groups + * @param max_age maximum age from which the age group is derived, that the withdrawn coins must be restricted to. + * @param reserve_priv private key to sign with + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_age_withdraw_sign ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + +/** + * Verify an age-withdraw request. + * + * @param h_commitment hash all n*kappa blinded coins in the commitment for the age-withdraw + * @param amount_with_fee amount to debit the reserve for + * @param mask the mask that defines the age groups + * @param max_age maximum age from which the age group is derived, that the withdrawn coins must be restricted to. + * @param reserve_pub public key of the reserve + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_age_withdraw_verify ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + const struct TALER_Amount *amount_with_fee, + const struct TALER_AgeMask *mask, + uint8_t max_age, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + +/** + * Verify exchange melt confirmation. + * + * @param rc refresh session this is about + * @param noreveal_index gamma value chosen by the exchange + * @param exchange_pub public signing key used + * @param exchange_sig signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_melt_confirmation_verify ( + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +/** + * Verify recoup signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_pub coin key of the coin to be recouped + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_recoup_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create recoup signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_priv coin key of the coin to be recouped + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_recoup_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify recoup-refresh signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_pub coin key of the coin to be recouped + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_recoup_refresh_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create recoup-refresh signature. + * + * @param h_denom_pub hash of the denomiantion public key of the coin + * @param coin_bks blinding factor used when withdrawing the coin + * @param coin_priv coin key of the coin to be recouped + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_recoup_refresh_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Verify reserve history request signature. + * + * @param start_off start of the requested range + * @param reserve_pub reserve the history request was for + * @param reserve_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_reserve_history_verify ( + uint64_t start_off, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Create reserve status request signature. + * + * @param start_off start of the requested range + * @param reserve_priv private key of the reserve the history request is for + * @param[out] reserve_sig resulting signature + */ +void +TALER_wallet_reserve_history_sign ( + uint64_t start_off, + const struct TALER_ReservePrivateKeyP *reserve_priv, + struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Verify coin history request signature. + * + * @param start_off start of the requested range + * @param coin_pub coin the history request was for + * @param coin_sig resulting signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_wallet_coin_history_verify ( + uint64_t start_off, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Create coin status request signature. + * + * @param start_off start of the requested range + * @param coin_priv private key of the coin the history request is for + * @param[out] coin_sig resulting signature + */ +void +TALER_wallet_coin_history_sign ( + uint64_t start_off, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_CoinSpendSignatureP *coin_sig); + + +/* ********************* merchant signing ************************** */ + + +/** + * Create merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_priv private key to sign with + * @param[out] merchant_sig where to write the signature + */ +void +TALER_merchant_refund_sign ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Verify merchant signature approving a refund. + * + * @param coin_pub coin to be refunded + * @param h_contract_terms contract to be refunded + * @param rtransaction_id unique ID for this (partial) refund + * @param amount amount to be refunded + * @param merchant_pub public key of the merchant + * @param merchant_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_refund_verify ( + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint64_t rtransaction_id, + const struct TALER_Amount *amount, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/* ********************* exchange deposit signing ************************* */ + +/** + * Sign a deposit. + * + * @param h_contract_terms hash of contract terms + * @param h_wire hash of the merchant account details + * @param coin_pub coin to be deposited + * @param merchant_priv private key to sign with + * @param[out] merchant_sig where to write the signature + */ +void +TALER_merchant_deposit_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPrivateKeyP *merchant_priv, + struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Verify a deposit. + * + * @param merchant merchant public key + * @param coin_pub public key of the deposited coin + * @param h_contract_terms hash of contract terms + * @param h_wire hash of the merchant account details + * @param merchant_sig signature of the merchant + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_deposit_verify ( + const struct TALER_MerchantPublicKeyP *merchant, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/* ********************* exchange online signing ************************** */ + + +/** + * Signature of a function that signs the message in @a purpose with the + * exchange's signing key. + * + * The @a purpose data is the beginning of the data of which the signature is + * to be created. The `size` field in @a purpose must correctly indicate the + * number of bytes of the data structure, including its header. * + * @param purpose the message to sign + * @param[out] pub set to the current public signing key of the exchange + * @param[out] sig signature over purpose using current signing key + * @return #TALER_EC_NONE on success + */ +typedef enum TALER_ErrorCode +(*TALER_ExchangeSignCallback)( + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Signature of a function that signs the message in @a purpose with the + * exchange's signing key. + * + * The @a purpose data is the beginning of the data of which the signature is + * to be created. The `size` field in @a purpose must correctly indicate the + * number of bytes of the data structure, including its header. * + * @param cls closure + * @param purpose the message to sign + * @param[out] pub set to the current public signing key of the exchange + * @param[out] sig signature over purpose using current signing key + * @return #TALER_EC_NONE on success + */ +typedef enum TALER_ErrorCode +(*TALER_ExchangeSignCallback2)( + void *cls, + const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Create deposit confirmation signature. + * + * @param scb function to call to create the signature + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param h_wire hash of the merchant’s account details + * @param h_policy hash over the policy extension, can be NULL + * @param exchange_timestamp timestamp when the contract was finalized, must not be too far off + * @param wire_deadline date until which the exchange should wire the funds + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param total_without_fee the total amount to be deposited after fees over all coins + * @param num_coins length of @a coin_sigs array + * @param coin_sigs signatures of the deposited coins + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_deposit_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], + const struct TALER_MerchantPublicKeyP *merchant_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify deposit confirmation signature. + * + * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) + * @param h_wire hash of the merchant’s account details + * @param h_policy hash over the policy extension, can be NULL + * @param exchange_timestamp timestamp when the contract was finalized, must not be too far off + * @param wire_deadline date until which the exchange should wire the funds + * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline + * @param total_without_fee the total amount to be deposited after fees over all coins + * @param num_coins length of @a coin_sigs array + * @param coin_sigs signatures of the deposited coins + * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_deposit_confirmation_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_ExtensionPolicyHashP *h_policy, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Timestamp wire_deadline, + struct GNUNET_TIME_Timestamp refund_deadline, + const struct TALER_Amount *total_without_fee, + unsigned int num_coins, + const struct TALER_CoinSpendSignatureP *coin_sigs[static num_coins], + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create refund confirmation signature. + * + * @param scb function to call to create the signature + * @param h_contract_terms hash of contract being refunded + * @param coin_pub public key of the coin receiving the refund + * @param merchant public key of the merchant that granted the refund + * @param rtransaction_id refund transaction ID used by the merchant + * @param refund_amount amount refunded + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_refund_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + uint64_t rtransaction_id, + const struct TALER_Amount *refund_amount, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify refund confirmation signature. + * + * @param h_contract_terms hash of contract being refunded + * @param coin_pub public key of the coin receiving the refund + * @param merchant public key of the merchant that granted the refund + * @param rtransaction_id refund transaction ID used by the merchant + * @param refund_amount amount refunded + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_refund_confirmation_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + uint64_t rtransaction_id, + const struct TALER_Amount *refund_amount, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create refresh melt confirmation signature. + * + * @param scb function to call to create the signature + * @param rc refresh commitment that identifies the melt operation + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_melt_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify refresh melt confirmation signature. + * + * @param rc refresh commitment that identifies the melt operation + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_melt_confirmation_verify ( + const struct TALER_RefreshCommitmentP *rc, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create exchange purse refund confirmation signature. + * + * @param scb function to call to create the signature + * @param amount_without_fee refunded amount + * @param refund_fee refund fee charged + * @param coin_pub coin that was refunded + * @param purse_pub public key of the expired purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_refund_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *refund_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature of exchange affirming purse refund + * from purse expiration. + * + * @param amount_without_fee refunded amount + * @param refund_fee refund fee charged + * @param coin_pub coin that was refunded + * @param purse_pub public key of the expired purse + * @param pub public key to verify signature against + * @param sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_refund_verify ( + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *refund_fee, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create exchange key set signature. + * + * @param scb function to call to create the signature + * @param cls closure for @a scb + * @param timestamp time when the key set was issued + * @param hc hash over all the keys + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_key_set_sign ( + TALER_ExchangeSignCallback2 scb, + void *cls, + struct GNUNET_TIME_Timestamp timestamp, + const struct GNUNET_HashCode *hc, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify key set signature. + * + * @param timestamp time when the key set was issued + * @param hc hash over all the keys + * @param pub public key to verify signature against + * @param sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_key_set_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct GNUNET_HashCode *hc, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create account KYC setup success signature. + * + * @param scb function to call to create the signature + * @param h_payto target of the KYC account + * @param kyc JSON data describing which KYC checks + * were satisfied + * @param timestamp time when the KYC was confirmed + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_account_setup_success_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_PaytoHashP *h_payto, + const json_t *kyc, + struct GNUNET_TIME_Timestamp timestamp, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify account KYC setup success signature. + * + * @param h_payto target of the KYC account + * @param kyc JSON data describing which KYC checks + * were satisfied + * @param timestamp time when the KYC was confirmed + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_account_setup_success_verify ( + const struct TALER_PaytoHashP *h_payto, + const json_t *kyc, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Hash normalized @a j JSON object or array and + * store the result in @a hc. + * + * @param j JSON to hash + * @param[out] hc where to write the hash + */ +void +TALER_json_hash (const json_t *j, + struct GNUNET_HashCode *hc); + + +/** + * Update the @a hash_context in the computation of the + * h_details for a wire status signature. + * + * @param[in,out] hash_context context to update + * @param h_contract_terms hash of the contract + * @param execution_time when was the wire transfer initiated + * @param coin_pub deposited coin + * @param deposit_value contribution of the coin + * @param deposit_fee how high was the deposit fee + */ +void +TALER_exchange_online_wire_deposit_append ( + struct GNUNET_HashContext *hash_context, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *deposit_value, + const struct TALER_Amount *deposit_fee); + + +/** + * Create wire deposit signature. + * + * @param scb function to call to create the signature + * @param total amount the merchant was credited + * @param wire_fee fee charged by the exchange for the wire transfer + * @param merchant_pub which merchant was credited + * @param payto payto://-URI of the merchant account + * @param h_details hash over the aggregation details + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_wire_deposit_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_Amount *total, + const struct TALER_Amount *wire_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *payto, + const struct GNUNET_HashCode *h_details, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify wire deposit signature. + * + * @param total amount the merchant was credited + * @param wire_fee fee charged by the exchange for the wire transfer + * @param merchant_pub which merchant was credited + * @param h_payto hash of the payto://-URI of the merchant account + * @param h_details hash over the aggregation details + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_wire_deposit_verify ( + const struct TALER_Amount *total, + const struct TALER_Amount *wire_fee, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PaytoHashP *h_payto, + const struct GNUNET_HashCode *h_details, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create wire confirmation signature. + * + * @param scb function to call to create the signature + * @param h_wire hash of the merchant's account + * @param h_contract_terms hash of the contract + * @param wtid wire transfer this deposit was aggregated into + * @param coin_pub public key of the deposited coin + * @param execution_time when was wire transfer initiated + * @param coin_contribution what was @a coin_pub's contribution to the wire transfer + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_wire_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_Amount *coin_contribution, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm wire signature. + * + * @param h_wire hash of the merchant's account + * @param h_contract_terms hash of the contract + * @param wtid wire transfer this deposit was aggregated into + * @param coin_pub public key of the deposited coin + * @param execution_time when was wire transfer initiated + * @param coin_contribution what was @a coin_pub's contribution to the wire transfer + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_wire_verify ( + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Timestamp execution_time, + const struct TALER_Amount *coin_contribution, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create confirm recoup signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param reserve_pub reserve that was credited + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_recoup_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm recoup signature. + * + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param reserve_pub reserve that was credited + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_recoup_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create confirm recoup refresh signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param old_coin_pub old coin that was credited + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_confirm_recoup_refresh_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify confirm recoup refresh signature. + * + * @param timestamp when was the recoup done + * @param recoup_amount how much was recouped + * @param coin_pub coin that was recouped + * @param old_coin_pub old coin that was credited + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_confirm_recoup_refresh_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *recoup_amount, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create denomination unknown signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is unknown + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_denomination_unknown_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify denomination unknown signature. + * + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is unknown + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_denomination_unknown_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create denomination expired signature. + * + * @param scb function to call to create the signature + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is expired + * @param op character string describing the operation for which + * the denomination is expired + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_denomination_expired_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const char *op, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify denomination expired signature. + * + * @param timestamp when was the error created + * @param h_denom_pub hash of denomination that is expired + * @param op character string describing the operation for which + * the denomination is expired + * @param pub where to write the public key + * @param sig where to write the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_denomination_expired_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_DenominationHashP *h_denom_pub, + const char *op, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create reserve closure signature. + * + * @param scb function to call to create the signature + * @param timestamp time when the reserve was closed + * @param closing_amount amount left in the reserve + * @param closing_fee closing fee charged + * @param payto target of the wire transfer + * @param wtid wire transfer subject used + * @param reserve_pub public key of the closed reserve + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_reserve_closed_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *closing_amount, + const struct TALER_Amount *closing_fee, + const char *payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify reserve closure signature. + * + * @param timestamp time when the reserve was closed + * @param closing_amount amount left in the reserve + * @param closing_fee closing fee charged + * @param payto target of the wire transfer + * @param wtid wire transfer subject used + * @param reserve_pub public key of the closed reserve + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_reserve_closed_verify ( + struct GNUNET_TIME_Timestamp timestamp, + const struct TALER_Amount *closing_amount, + const struct TALER_Amount *closing_fee, + const char *payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Create signature by exchange affirming that a reserve + * has had certain attributes verified via KYC. + * + * @param scb function to call to create the signature + * @param attest_timestamp our time + * @param expiration_time when does the KYC data expire + * @param reserve_pub for which reserve are attributes attested + * @param attributes JSON object with attributes being attested to + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_reserve_attest_details_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature by exchange affirming that a reserve + * has had certain attributes verified via KYC. + * + * @param attest_timestamp our time + * @param expiration_time when does the KYC data expire + * @param reserve_pub for which reserve are attributes attested + * @param attributes JSON object with attributes being attested to + * @param pub exchange public key + * @param sig exchange signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_reserve_attest_details_verify ( + struct GNUNET_TIME_Timestamp attest_timestamp, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_ReservePublicKeyP *reserve_pub, + const json_t *attributes, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Create signature by exchange affirming that a purse was created. + * + * @param scb function to call to create the signature + * @param exchange_time our time + * @param purse_expiration when will the purse expire + * @param amount_without_fee total amount to be put into the purse (without deposit fees) + * @param total_deposited total currently in the purse + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract for the purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_created_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *total_deposited, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify exchange signature about a purse creation and balance. + * + * @param exchange_time our time + * @param purse_expiration when will the purse expire + * @param amount_without_fee total amount to be put into the purse (without deposit fees) + * @param total_deposited total currently in the purse + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract for the purse + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_created_verify ( + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_Amount *total_deposited, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Sign affirmation that a purse was merged. + * + * @param scb function to call to create the signature + * @param exchange_time our time + * @param purse_expiration when does the purse expire + * @param amount_without_fee total amount that should be in the purse without deposit fees + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract of the purse + * @param reserve_pub reserve the purse will be merged into + * @param exchange_url exchange at which the @a reserve_pub lives + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_merged_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *exchange_url, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify affirmation that a purse will be merged. + * + * @param exchange_time our time + * @param purse_expiration when does the purse expire + * @param amount_without_fee total amount that should be in the purse without deposit fees + * @param purse_pub public key of the purse + * @param h_contract_terms hash of the contract of the purse + * @param reserve_pub reserve the purse will be merged into + * @param exchange_url exchange at which the @a reserve_pub lives + * @param pub the public key of the exchange to check against + * @param sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_merged_verify ( + struct GNUNET_TIME_Timestamp exchange_time, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount_without_fee, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *exchange_url, + const struct TALER_ExchangePublicKeyP *pub, + const struct TALER_ExchangeSignatureP *sig); + + +/** + * Sign information about the status of a purse. + * + * @param scb function to call to create the signature + * @param merge_timestamp when was the purse merged (can be never) + * @param deposit_timestamp when was the purse fully paid up (can be never) + * @param balance current balance of the purse + * @param[out] pub where to write the public key + * @param[out] sig where to write the signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_purse_status_sign ( + TALER_ExchangeSignCallback scb, + struct GNUNET_TIME_Timestamp merge_timestamp, + struct GNUNET_TIME_Timestamp deposit_timestamp, + const struct TALER_Amount *balance, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify signature over information about the status of a purse. + * + * @param merge_timestamp when was the purse merged (can be never) + * @param deposit_timestamp when was the purse fully paid up (can be never) + * @param balance current balance of the purse + * @param exchange_pub the public key of the exchange to check against + * @param exchange_sig the signature to check + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_purse_status_verify ( + struct GNUNET_TIME_Timestamp merge_timestamp, + struct GNUNET_TIME_Timestamp deposit_timestamp, + const struct TALER_Amount *balance, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +/** + * Create age-withdraw confirmation signature. + * + * @param scb function to call to create the signature + * @param h_commitment age-withdraw commitment that identifies the n*kappa blinded coins + * @param noreveal_index gamma cut-and-choose value chosen by the exchange + * @param[out] pub where to write the exchange public key + * @param[out] sig where to write the exchange signature + * @return #TALER_EC_NONE on success + */ +enum TALER_ErrorCode +TALER_exchange_online_age_withdraw_confirmation_sign ( + TALER_ExchangeSignCallback scb, + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + uint32_t noreveal_index, + struct TALER_ExchangePublicKeyP *pub, + struct TALER_ExchangeSignatureP *sig); + + +/** + * Verify an exchange age-withdraw confirmation + * + * @param h_commitment Commitment over all n*kappa coin candidates from the original request to age-withdraw + * @param noreveal_index The index returned by the exchange + * @param exchange_pub The public key used for signing + * @param exchange_sig The signature from the exchange + */ +enum GNUNET_GenericReturnValue +TALER_exchange_online_age_withdraw_confirmation_verify ( + const struct TALER_AgeWithdrawCommitmentHashP *h_commitment, + uint32_t noreveal_index, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_ExchangeSignatureP *exchange_sig); + + +/* ********************* offline signing ************************** */ + + +/** + * Create AML officer status change signature. + * + * @param officer_pub public key of the AML officer + * @param officer_name name of the officer + * @param change_date when to affect the status change + * @param is_active true to enable the officer + * @param read_only true to only allow read-only access + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_aml_officer_status_sign ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *officer_name, + struct GNUNET_TIME_Timestamp change_date, + bool is_active, + bool read_only, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify AML officer status change signature. + * + * @param officer_pub public key of the AML officer + * @param officer_name name of the officer + * @param change_date when to affect the status change + * @param is_active true to enable the officer + * @param read_only true to only allow read-only access + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_aml_officer_status_verify ( + const struct TALER_AmlOfficerPublicKeyP *officer_pub, + const char *officer_name, + struct GNUNET_TIME_Timestamp change_date, + bool is_active, + bool read_only, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create auditor addition signature. + * + * @param auditor_pub public key of the auditor + * @param auditor_url URL of the auditor + * @param start_date when to enable the auditor (for replay detection) + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_auditor_add_sign ( + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify auditor add signature. + * + * @param auditor_pub public key of the auditor + * @param auditor_url URL of the auditor + * @param start_date when to enable the auditor (for replay detection) + * @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_auditor_add_verify ( + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + struct GNUNET_TIME_Timestamp start_date, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create auditor deletion signature. + * + * @param auditor_pub public key of the auditor + * @param end_date when to disable the auditor (for replay detection) + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_auditor_del_sign ( + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify auditor del signature. + * + * @param auditor_pub public key of the auditor + * @param end_date when to disable the auditor (for replay detection) + * @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_auditor_del_verify ( + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create denomination revocation signature. + * + * @param h_denom_pub hash of public denomination key to revoke + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_denomination_revoke_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify denomination revocation signature. + * + * @param h_denom_pub hash of public denomination key to revoke + * @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_denomination_revoke_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create signkey revocation signature. + * + * @param exchange_pub public signing key to revoke + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_signkey_revoke_sign ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify signkey revocation signature. + * + * @param exchange_pub public signkey key to revoke + * @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_signkey_revoke_verify ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create signkey validity signature. + * + * @param exchange_pub public signing key to validate + * @param start_sign starting point of validity for signing + * @param end_sign end point (exclusive) for validity for signing + * @param end_legal legal end point of signature validity + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_signkey_validity_sign ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Timestamp end_sign, + struct GNUNET_TIME_Timestamp end_legal, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify signkey validitity signature. + * + * @param exchange_pub public signkey key to validate + * @param start_sign starting point of validity for signing + * @param end_sign end point (exclusive) for validity for signing + * @param end_legal legal end point of signature validity + * @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_signkey_validity_verify ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Timestamp end_sign, + struct GNUNET_TIME_Timestamp end_legal, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create denomination key validity signature. + * + * @param h_denom_pub hash of the denomination's public key + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fees fees for this denomination + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_denom_validity_sign ( + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_DenomFeeSet *fees, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify denomination key validity signature. + * + * @param h_denom_pub hash of the denomination's public key + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fees fees for this denomination + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_denom_validity_verify ( + const struct TALER_DenominationHashP *h_denom_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_DenomFeeSet *fees, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create offline signature about an exchange's partners. + * + * @param partner_pub master public key of the partner + * @param start_date validity period start + * @param end_date validity period end + * @param wad_frequency how often will we do wad transfers to this partner + * @param wad_fee what is the wad fee to this partner + * @param partner_base_url what is the base URL of the @a partner_pub exchange + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_partner_details_sign ( + const struct TALER_MasterPublicKeyP *partner_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify signature about an exchange's partners. + * + * @param partner_pub master public key of the partner + * @param start_date validity period start + * @param end_date validity period end + * @param wad_frequency how often will we do wad transfers to this partner + * @param wad_fee what is the wad fee to this partner + * @param partner_base_url what is the base URL of the @a partner_pub exchange + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_partner_details_verify ( + const struct TALER_MasterPublicKeyP *partner_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create offline signature about wiring profits to a + * regular non-escrowed account of the exchange. + * + * @param wtid (random) wire transfer ID to be used + * @param date when was the profit drain approved (not exact time of execution) + * @param amount how much should be wired + * @param account_section configuration section of the + * exchange specifying the account to be debited + * @param payto_uri target account to be credited + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_profit_drain_sign ( + const struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp date, + const struct TALER_Amount *amount, + const char *account_section, + const char *payto_uri, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify offline signature about wiring profits to a + * regular non-escrowed account of the exchange. + * + * @param wtid (random) wire transfer ID to be used + * @param date when was the profit drain approved (not exact time of execution) + * @param amount how much should be wired + * @param account_section configuration section of the + * exchange specifying the account to be debited + * @param payto_uri target account to be credited + * @param master_pub public key to verify signature against + * @param master_sig the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_profit_drain_verify ( + const struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp date, + const struct TALER_Amount *amount, + const char *account_section, + const char *payto_uri, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create security module EdDSA signature. + * + * @param exchange_pub public signing key to validate + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_priv security module key to sign with + * @param[out] secm_sig where to write the signature + */ +void +TALER_exchange_secmod_eddsa_sign ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePrivateKeyP *secm_priv, + struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Verify security module EdDSA signature. + * + * @param exchange_pub public signing key to validate + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_pub public key to verify against + * @param secm_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_secmod_eddsa_verify ( + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePublicKeyP *secm_pub, + const struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Create security module denomination signature. + * + * @param h_rsa hash of the RSA public key to sign + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_priv security module key to sign with + * @param[out] secm_sig where to write the signature + */ +void +TALER_exchange_secmod_rsa_sign ( + const struct TALER_RsaPubHashP *h_rsa, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePrivateKeyP *secm_priv, + struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Verify security module denomination signature. + * + * @param h_rsa hash of the public key to validate + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_pub public key to verify against + * @param secm_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_secmod_rsa_verify ( + const struct TALER_RsaPubHashP *h_rsa, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePublicKeyP *secm_pub, + const struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Create security module denomination signature. + * + * @param h_cs hash of the CS public key to sign + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_priv security module key to sign with + * @param[out] secm_sig where to write the signature + */ +void +TALER_exchange_secmod_cs_sign ( + const struct TALER_CsPubHashP *h_cs, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePrivateKeyP *secm_priv, + struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Verify security module denomination signature. + * + * @param h_cs hash of the public key to validate + * @param section_name name of the section in the configuration + * @param start_sign starting point of validity for signing + * @param duration how long will the key be in use + * @param secm_pub public key to verify against + * @param secm_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_secmod_cs_verify ( + const struct TALER_CsPubHashP *h_cs, + const char *section_name, + struct GNUNET_TIME_Timestamp start_sign, + struct GNUNET_TIME_Relative duration, + const struct TALER_SecurityModulePublicKeyP *secm_pub, + const struct TALER_SecurityModuleSignatureP *secm_sig); + + +/** + * Create denomination key validity signature by the auditor. + * + * @param auditor_url BASE URL of the auditor's API + * @param h_denom_pub hash of the denomination's public key + * @param master_pub master public key of the exchange + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fees fees the exchange charges for this denomination + * @param auditor_priv private key to sign with + * @param[out] auditor_sig where to write the signature + */ +void +TALER_auditor_denom_validity_sign ( + const char *auditor_url, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_DenomFeeSet *fees, + const struct TALER_AuditorPrivateKeyP *auditor_priv, + struct TALER_AuditorSignatureP *auditor_sig); + + +/** + * Verify denomination key validity signature from auditor. + * + * @param auditor_url BASE URL of the auditor's API + * @param h_denom_pub hash of the denomination's public key + * @param master_pub master public key of the exchange + * @param stamp_start when does the exchange begin signing with this key + * @param stamp_expire_withdraw when does the exchange end signing with this key + * @param stamp_expire_deposit how long does the exchange accept the deposit of coins with this key + * @param stamp_expire_legal how long does the exchange preserve information for legal disputes with this key + * @param coin_value what is the value of coins signed with this key + * @param fees fees the exchange charges for this denomination + * @param auditor_pub public key to verify against + * @param auditor_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_auditor_denom_validity_verify ( + const char *auditor_url, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp stamp_start, + struct GNUNET_TIME_Timestamp stamp_expire_withdraw, + struct GNUNET_TIME_Timestamp stamp_expire_deposit, + struct GNUNET_TIME_Timestamp stamp_expire_legal, + const struct TALER_Amount *coin_value, + const struct TALER_DenomFeeSet *fees, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig); + + /* **************** /wire account offline signing **************** */ /** - * Compute the hash of the given wire details. The resulting - * hash is what is signed by the master key. + * Create wire fee signature. + * + * @param payment_method the payment method + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the wire fees + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_wire_fee_sign ( + const char *payment_method, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify wire fee signature. + * + * @param payment_method the payment method + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the wire fees + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_wire_fee_verify ( + const char *payment_method, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create global fees signature. + * + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the global fees + * @param purse_timeout how long do unmerged purses stay around + * @param history_expiration how long do we keep the history of an account + * @param purse_account_limit how many concurrent purses are free per account holder + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_global_fee_sign ( + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify global fees signature. + * + * @param start_time when do the fees start to apply + * @param end_time when do the fees start to apply + * @param fees the global fees + * @param purse_timeout how long do unmerged purses stay around + * @param history_expiration how long do we keep the history of an account + * @param purse_account_limit how many concurrent purses are free per account holder + * @param master_pub public key to verify against + * @param master_sig the signature the signature + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_global_fee_verify ( + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Create wire account addition signature. * * @param payto_uri bank account - * @param[out] hc set to the hash + * @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 */ void -TALER_exchange_wire_signature_hash (const char *payto_uri, - struct GNUNET_HashCode *hc); +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); + + +/** + * 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 + * @return #GNUNET_OK if the signature is valid + */ +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); + + +/** + * Create wire account removal signature. + * + * @param payto_uri bank account + * @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 + */ +void +TALER_exchange_offline_wire_del_sign ( + const char *payto_uri, + struct GNUNET_TIME_Timestamp now, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify wire account deletion signature. + * + * @param payto_uri bank account + * @param sign_time timestamp when signature was created + * @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_wire_del_verify ( + const char *payto_uri, + struct GNUNET_TIME_Timestamp sign_time, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig); /** * Check the signature in @a master_sig. * - * @param payto_uri URL that is signed + * @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 */ -int +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); @@ -759,12 +5468,18 @@ TALER_exchange_wire_signature_check ( * Create a signed wire statement for the given account. * * @param payto_uri account specification + * @param conversion_url URL of the conversion service, or NULL if none + * @param debit_restrictions JSON encoding of debit restrictions on the account; see AccountRestriction in the spec + * @param credit_restrictions JSON encoding of credit restrictions on the account; see AccountRestriction in the spec * @param master_priv private key to sign with * @param[out] master_sig where to write the signature */ void TALER_exchange_wire_signature_make ( const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, const struct TALER_MasterPrivateKeyP *master_priv, struct TALER_MasterSignatureP *master_sig); @@ -780,8 +5495,8 @@ TALER_exchange_wire_signature_make ( */ void TALER_merchant_wire_signature_hash (const char *payto_uri, - const char *salt, - struct GNUNET_HashCode *hc); + const struct TALER_WireSaltP *salt, + struct TALER_MerchantWireHashP *hc); /** @@ -793,10 +5508,10 @@ TALER_merchant_wire_signature_hash (const char *payto_uri, * @param merch_sig signature of the merchant * @return #GNUNET_OK if signature is valid */ -int +enum GNUNET_GenericReturnValue TALER_merchant_wire_signature_check ( const char *payto_uri, - const char *salt, + const struct TALER_WireSaltP *salt, const struct TALER_MerchantPublicKeyP *merch_pub, const struct TALER_MerchantSignatureP *merch_sig); @@ -812,9 +5527,444 @@ TALER_merchant_wire_signature_check ( void TALER_merchant_wire_signature_make ( const char *payto_uri, - const char *salt, + const struct TALER_WireSaltP *salt, const struct TALER_MerchantPrivateKeyP *merch_priv, struct TALER_MerchantSignatureP *merch_sig); +/** + * Sign a payment confirmation. + * + * @param h_contract_terms hash of the contact of the merchant with the customer + * @param merch_priv private key to sign with + * @param[out] merch_sig where to write the signature + */ +void +TALER_merchant_pay_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantPrivateKeyP *merch_priv, + struct TALER_MerchantSignatureP *merch_sig); + + +/** + * Verify payment confirmation signature. + * + * @param h_contract_terms hash of the contact of the merchant with the customer + * @param merchant_pub public key of the merchant + * @param merchant_sig signature to verify + * @return #GNUNET_OK if the signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_merchant_pay_verify ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_MerchantSignatureP *merchant_sig); + + +/** + * Sign contract sent by the merchant to the wallet. + * + * @param h_contract_terms hash of the contract terms + * @param merch_priv private key to sign with + * @param[out] merch_sig where to write the signature + */ +void +TALER_merchant_contract_sign ( + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantPrivateKeyP *merch_priv, + struct GNUNET_CRYPTO_EddsaSignature *merch_sig); + + +/* **************** /management/extensions offline signing **************** */ + +/** + * Create a signature for the hash of the manifests of extensions + * + * @param h_manifests hash of the JSON object representing the manifests + * @param master_priv private key to sign with + * @param[out] master_sig where to write the signature + */ +void +TALER_exchange_offline_extension_manifests_hash_sign ( + const struct TALER_ExtensionManifestsHashP *h_manifests, + const struct TALER_MasterPrivateKeyP *master_priv, + struct TALER_MasterSignatureP *master_sig); + + +/** + * Verify the signature in @a master_sig of the given hash, taken over the JSON + * blob representing the manifests of extensions + * + * @param h_manifest hash of the JSON blob of manifests of extensions + * @param master_pub master public key of the exchange + * @param master_sig signature of the exchange + * @return #GNUNET_OK if signature is valid + */ +enum GNUNET_GenericReturnValue +TALER_exchange_offline_extension_manifests_hash_verify ( + const struct TALER_ExtensionManifestsHashP *h_manifest, + const struct TALER_MasterPublicKeyP *master_pub, + const struct TALER_MasterSignatureP *master_sig + ); + + +/** + * @brief Representation of an age commitment: one public key per age group. + * + * The number of keys must be be the same as the number of bits set in the + * corresponding age mask. + */ +struct TALER_AgeCommitment +{ + + /** + * The age mask defines the age groups that were a parameter during the + * generation of this age commitment + */ + struct TALER_AgeMask mask; + + /** + * The number of public keys, which must be the same as the number of + * groups in the mask. + */ + size_t num; + + /** + * The list of @e num public keys. In must have same size as the number of + * age groups defined in the mask. + * + * A hash of this list is the hashed commitment that goes into FDC + * calculation during the withdraw and refresh operations for new coins. That + * way, the particular age commitment becomes mandatory and bound to a coin. + * + * The list has been allocated via GNUNET_malloc(). + */ + struct TALER_AgeCommitmentPublicKeyP *keys; +}; + + +/** + * @brief Proof for a particular age commitment, used in age attestation + * + * This struct is used in a call to TALER_age_commitment_attest to create an + * attestation for a minimum age (if that minimum age is less or equal to the + * committed age for this proof). It consists of a list private keys, one per + * age group, for which the committed age is either lager or within that + * particular group. + */ +struct TALER_AgeProof +{ + /** + * The number of private keys, which must be at most num_pub_keys. One minus + * this number corresponds to the largest age group that is supported with + * this age commitment. + * **Note**, that this and the next field are only relevant on the wallet + * side for attestation and derive operations. + */ + size_t num; + + /** + * List of @e num private keys. + * + * Note that the list can be _smaller_ than the corresponding list of public + * keys. In that case, the wallet can sign off only for a subset of the age + * groups. + * + * The list has been allocated via GNUNET_malloc. + */ + struct TALER_AgeCommitmentPrivateKeyP *keys; +}; + + +/** + * @brief Commitment and Proof for a maximum age + * + * Calling TALER_age_restriction_commit on an (maximum) age value returns this + * data structure. It consists of the proof, which is used to create + * attestations for compatible minimum ages, and the commitment, which is used + * to verify the attestations and derived commitments. + * + * The hash value of the commitment is bound to a particular coin with age + * restriction. + */ +struct TALER_AgeCommitmentProof +{ + /** + * The commitment is used to verify a particular attestation. Its hash value + * is bound to a particular coin with age restriction. This structure is + * sent to the merchant in order to verify a particular attestation for a + * minimum age. + * In itself, it does not convey any information about the maximum age that + * went into the call to TALER_age_restriction_commit. + */ + struct TALER_AgeCommitment commitment; + + /** + * The proof is used to create an attestation for a (compatible) minimum age. + */ + struct TALER_AgeProof proof; +}; + + +/** + * @brief Generates a hash of the public keys in the age commitment. + * + * @param commitment the age commitment - one public key per age group + * @param[out] hash resulting hash + */ +void +TALER_age_commitment_hash ( + const struct TALER_AgeCommitment *commitment, + struct TALER_AgeCommitmentHash *hash); + + +/** + * @brief Generates an age commitent for the given age. + * + * @param mask The age mask the defines the age groups + * @param age The actual age for which an age commitment is generated + * @param seed The seed that goes into the key generation. MUST be chosen uniformly random. + * @param[out] comm_proof The generated age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success + */ +void +TALER_age_restriction_commit ( + const struct TALER_AgeMask *mask, + uint8_t age, + const struct GNUNET_HashCode *seed, + struct TALER_AgeCommitmentProof *comm_proof); + + +/** + * @brief Derives another, equivalent age commitment for a given one. + * + * @param orig Original age commitment + * @param salt Salt to randomly move the points on the elliptic curve in order to generate another, equivalent commitment. + * @param[out] derived The resulting age commitment, ->priv and ->pub allocated via GNUNET_malloc() on success. + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_derive ( + const struct TALER_AgeCommitmentProof *orig, + const struct GNUNET_HashCode *salt, + struct TALER_AgeCommitmentProof *derived); + + +/** + * @brief Provide attestation for a given age, from a given age commitment, if possible. + * + * @param comm_proof The age commitment to be used for attestation. For successful attestation, it must contain the private key for the corresponding age group. + * @param age Age (not age group) for which the an attestation should be done + * @param[out] attest Signature of the age with the appropriate key from the age commitment for the corresponding age group, if applicable. + * @return #GNUNET_OK on success, #GNUNET_NO when no attestation can be made for that age with the given commitment, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_attest ( + const struct TALER_AgeCommitmentProof *comm_proof, + uint8_t age, + struct TALER_AgeAttestation *attest); + + +/** + * @brief Verify the attestation for an given age and age commitment + * + * @param commitment The age commitment that went into the attestation. Only the public keys are needed. + * @param age Age (not age group) for which the an attestation should be done + * @param attest Signature of the age with the appropriate key from the age commitment for the corresponding age group, if applicable. + * @return #GNUNET_OK when the attestation was successful, #GNUNET_NO no attestation couldn't be verified, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_age_commitment_verify ( + const struct TALER_AgeCommitment *commitment, + uint8_t age, + const struct TALER_AgeAttestation *attest); + + +/** + * @brief helper function to free memory of a struct TALER_AgeCommitment + * + * @param ac the commitment from which all memory should be freed. + */ +void +TALER_age_commitment_free ( + struct TALER_AgeCommitment *ac); + + +/** + * @brief helper function to free memory of a struct TALER_AgeProof + * + * @param ap the proof of commitment from which all memory should be freed. + */ +void +TALER_age_proof_free ( + struct TALER_AgeProof *ap); + + +/** + * @brief helper function to free memory of a struct TALER_AgeCommitmentProof + * + * @param acp the commitment and its proof from which all memory should be freed. + */ +void +TALER_age_commitment_proof_free ( + struct TALER_AgeCommitmentProof *acp); + + +/** + * @brief helper function to allocate and copy a struct TALER_AgeCommitmentProof + * + * @param[in] acp The original age commitment proof + * @return The deep copy of @e acp, allocated + */ +struct TALER_AgeCommitmentProof * +TALER_age_commitment_proof_duplicate ( + const struct TALER_AgeCommitmentProof *acp); + +/** + * @brief helper function to copy a struct TALER_AgeCommitmentProof + * + * @param[in] acp The original age commitment proof + * @param[out] nacp The struct to copy the data into, with freshly allocated and copied keys. + */ +void +TALER_age_commitment_proof_deep_copy ( + const struct TALER_AgeCommitmentProof *acp, + struct TALER_AgeCommitmentProof *nacp); + +/** + * @brief For age-withdraw, clients have to prove that the public keys for all + * age groups larger than the allowed maximum age group are derived by scalar + * multiplication from this Edx25519 public key (in Crockford Base32 encoding): + * + * DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG + * + * Its private key was chosen randomly and then deleted. + */ +extern struct +#ifndef AGE_RESTRICTION_WITH_ECDSA +GNUNET_CRYPTO_Edx25519PublicKey +#else +GNUNET_CRYPTO_EcdsaPublicKey +#endif +TALER_age_commitment_base_public_key; + +/** + * @brief Similar to TALER_age_restriction_commit, but takes the coin's + * private key as seed input and calculates the public keys in the slots larger + * than the given age as derived from TALER_age_commitment_base_public_key. + * + * See https://docs.taler.net/core/api-exchange.html#withdraw-with-age-restriction + * + * @param secret The master secret of the coin from which we derive the age restriction + * @param mask The age mask, defining the age groups + * @param max_age The maximum age for this coin. + * @param[out] comm_proof The commitment and proof for age restriction for age @a max_age + */ +void +TALER_age_restriction_from_secret ( + const struct TALER_PlanchetMasterSecretP *secret, + const struct TALER_AgeMask *mask, + const uint8_t max_age, + struct TALER_AgeCommitmentProof *comm_proof); + + +/** + * Group of Denominations. These are the common fields of an array of + * denominations. + * + * The corresponding JSON-blob will also contain an array of particular + * denominations with only the timestamps, cipher-specific public key and the + * master signature. + */ +struct TALER_DenominationGroup +{ + + /** + * Value of coins in this denomination group. + */ + struct TALER_Amount value; + + /** + * Fee structure for all coins in the group. + */ + struct TALER_DenomFeeSet fees; + + /** + * Cipher used for the denomination. + */ + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher; + + /** + * Age mask for the denomination. + */ + struct TALER_AgeMask age_mask; + +}; + + +/** + * Compute a unique key for the meta data of a denomination group. + * + * @param dg denomination group to evaluate + * @param[out] key key to set + */ +void +TALER_denomination_group_get_key ( + const struct TALER_DenominationGroup *dg, + struct GNUNET_HashCode *key); + + +/** + * Token family public key. + */ +struct TALER_TokenFamilyPublicKey +{ + /** + * Type of the signature. + */ + struct GNUNET_CRYPTO_BlindSignPublicKey public_key; +}; + +/** + * Hash of a public key of a token family. + */ +struct TALER_TokenFamilyPublicKeyHash +{ + /** + * Hash of the token public key. + */ + struct GNUNET_HashCode hash; +}; + +/** + * Token family private key. + */ +struct TALER_TokenFamilyPrivateKey +{ + struct GNUNET_CRYPTO_BlindSignPrivateKey private_key; +}; + +/** + * Token public key. + */ +struct TALER_TokenPublicKey +{ + struct GNUNET_CRYPTO_EddsaPublicKey public_key; +}; + +/** + * Signature made using a token private key. + */ +struct TALER_TokenSignature +{ + struct GNUNET_CRYPTO_EddsaSignature signature; +}; + +/** + * Blind signature for a token (signed by merchant). + */ +struct TALER_TokenBlindSignature +{ + struct GNUNET_CRYPTO_BlindedSignature signature; +}; + #endif diff --git a/src/include/taler_curl_lib.h b/src/include/taler_curl_lib.h index d7c24a13b..f108e6158 100644 --- a/src/include/taler_curl_lib.h +++ b/src/include/taler_curl_lib.h @@ -30,7 +30,7 @@ /** * Should we compress PUT/POST bodies with 'deflate' encoding? */ -#define COMPRESS_BODIES 1 +#define TALER_CURL_COMPRESS_BODIES 1 /** * State used for #TALER_curl_easy_post() and @@ -47,6 +47,11 @@ struct TALER_CURL_PostContext * Custom headers. */ struct curl_slist *headers; + + /** + * Set to true to disable compression of the body. + */ + bool disable_compression; }; @@ -59,7 +64,7 @@ struct TALER_CURL_PostContext * @param body JSON body to add to @e ctx * @return #GNUNET_OK on success #GNUNET_SYSERR on failure */ -int +enum GNUNET_GenericReturnValue TALER_curl_easy_post (struct TALER_CURL_PostContext *ctx, CURL *eh, const json_t *body); @@ -74,4 +79,17 @@ void TALER_curl_easy_post_finished (struct TALER_CURL_PostContext *ctx); +/** + * Set a secure redirection policy, allowing a limited + * number of redirects and only going from HTTP to HTTPS + * but not from HTTPS to HTTP. + * + * @param[in,out] eh easy handle to modify + * @param url URL to base the redirect policy on; + * must start with "http://" or "https://" + */ +void +TALER_curl_set_secure_redirect_policy (CURL *eh, + const char *url); + #endif diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h deleted file mode 100644 index f75464c35..000000000 --- a/src/include/taler_error_codes.h +++ /dev/null @@ -1,2550 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2016, 2017, 2019 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ - -/** - * @file taler_error_codes.h - * @brief error codes returned by GNU Taler - * - * This file defines constants for error codes returned - * in Taler APIs. We use codes above 1000 to avoid any - * confusing with HTTP status codes. All constants have the - * shared prefix "TALER_EC_" to indicate that they are error - * codes. - * - * THIS FILE IS AUTO-GENERATED, DO NOT MODIFY! - * If you want to add an error code, please add it in the - * taler-util.git repository. Instructions - * for this are in the README in taler-util.git. - */ -#ifndef TALER_ERROR_CODES_H -#define TALER_ERROR_CODES_H - -/** - * Enumeration with all possible Taler error codes. - */ -enum TALER_ErrorCode -{ - - /** - * Special code to indicate no error (or no "code" present). - */ - TALER_EC_NONE = 0, - - /** - * Special code to indicate that a non-integer error code was returned - * in the JSON response. - */ - TALER_EC_INVALID = 1, - - /** - * The response we got from the server was not even in JSON format. - */ - TALER_EC_INVALID_RESPONSE = 2, - - /** - * Generic implementation error: this function was not yet - * implemented. - */ - TALER_EC_NOT_IMPLEMENTED = 3, - - /** - * Exchange is badly configured and thus cannot operate. - */ - TALER_EC_EXCHANGE_BAD_CONFIGURATION = 4, - - /** - * Internal assertion error. - */ - TALER_EC_INTERNAL_INVARIANT_FAILURE = 5, - - /** - * Operation timed out. - */ - TALER_EC_TIMEOUT = 6, - - /** - * Exchange failed to allocate memory for building JSON reply. - */ - TALER_EC_JSON_ALLOCATION_FAILURE = 7, - - /** - * HTTP method invalid for this URL. - */ - TALER_EC_METHOD_INVALID = 8, - - /** - * Operation specified invalid for this URL (resulting in a "NOT - * FOUND" for the overall response). - */ - TALER_EC_OPERATION_INVALID = 9, - - /** - * There is no endpoint defined for the URL provided by the client - * (returned together with a #MHD_HTTP_NOT_FOUND status code). - */ - TALER_EC_ENDPOINT_UNKNOWN = 10, - - /** - * The URI is longer than the longest URI the HTTP server is willing - * to parse. Returned together with an HTTP status code of - * #MHD_HTTP_URI_TOO_LONG. - */ - TALER_EC_URI_TOO_LONG = 11, - - /** - * The number of segments included in the URI does not match the - * number of segments expected by the endpoint. (returned together - * with a #MHD_HTTP_NOT_FOUND status code). - */ - TALER_EC_WRONG_NUMBER_OF_SEGMENTS = 12, - - /** - * The start and end-times in the wire fee structure leave a hole. - * This is not allowed. Generated as an error on the client-side. - */ - TALER_EC_HOLE_IN_WIRE_FEE_STRUCTURE = 13, - - /** - * The version string given does not follow the expected - * CURRENT:REVISION:AGE Format. Generated as an error on the client - * side. - */ - TALER_EC_VERSION_MALFORMED = 14, - - /** - * The client-side experienced an internal failure. Generated as an - * error on the client side. - */ - TALER_EC_CLIENT_INTERNAL_FAILURE = 15, - - /** - * The exchange failed to even just initialize its connection to the - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DB_SETUP_FAILED = 1001, - - /** - * The exchange encountered an error event to just start the database - * transaction. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DB_START_FAILED = 1002, - - /** - * The exchange encountered an error event to commit the database - * transaction (hard, unrecoverable error). This response is provided - * with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DB_COMMIT_FAILED_HARD = 1003, - - /** - * The exchange encountered an error event to commit the database - * transaction, even after repeatedly retrying it there was always a - * conflicting transaction. (This indicates a repeated serialization - * error; should only happen if some client maliciously tries to - * create conflicting concurrent transactions.) This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DB_COMMIT_FAILED_ON_RETRY = 1004, - - /** - * The exchange had insufficient memory to parse the request. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PARSER_OUT_OF_MEMORY = 1005, - - /** - * The JSON in the client's request to the exchange was malformed. - * (Generic parse error). This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_JSON_INVALID = 1006, - - /** - * The JSON in the client's request to the exchange was malformed. - * Details about the location of the parse error are provided. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_JSON_INVALID_WITH_DETAILS = 1007, - - /** - * A required parameter in the request to the exchange was missing. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PARAMETER_MISSING = 1008, - - /** - * A parameter in the request to the exchange was malformed. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PARAMETER_MALFORMED = 1009, - - /** - * The exchange failed to obtain the transaction history of the given - * coin from the database while generating an insufficient funds - * errors. This can happen during /deposit or /recoup requests. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1010, - - /** - * Internal logic error. Some server-side function failed that really - * should not. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_INTERNAL_LOGIC_ERROR = 1011, - - /** - * The method specified in a payto:// URI is not one we expected. - */ - TALER_EC_PAYTO_WRONG_METHOD = 1012, - - /** - * The payto:// URI is malformed. - */ - TALER_EC_PAYTO_MALFORMED = 1013, - - /** - * We failed to update the database of known coins. - */ - TALER_EC_DB_COIN_HISTORY_STORE_ERROR = 1014, - - /** - * The public key of given to a /coins/ handler was malformed. - */ - TALER_EC_COINS_INVALID_COIN_PUB = 1050, - - /** - * The reserve key of given to a /reserves/ handler was malformed. - */ - TALER_EC_RESERVES_INVALID_RESERVE_PUB = 1051, - - /** - * The public key of given to a /transfers/ handler was malformed. - */ - TALER_EC_TRANSFERS_INVALID_WTID = 1052, - - /** - * The wire hash of given to a /deposits/ handler was malformed. - */ - TALER_EC_DEPOSITS_INVALID_H_WIRE = 1053, - - /** - * The merchant key of given to a /deposits/ handler was malformed. - */ - TALER_EC_DEPOSITS_INVALID_MERCHANT_PUB = 1054, - - /** - * The hash of the contract terms given to a /deposits/ handler was - * malformed. - */ - TALER_EC_DEPOSITS_INVALID_H_CONTRACT_TERMS = 1055, - - /** - * The coin public key of given to a /deposits/ handler was malformed. - */ - TALER_EC_DEPOSITS_INVALID_COIN_PUB = 1056, - - /** - * The body returned by the exchange for a /deposits/ request was - * malformed. Error created client-side. - */ - TALER_EC_DEPOSITS_INVALID_BODY_BY_EXCHANGE = 1057, - - /** - * The signature returned by the exchange in a /deposits/ request was - * malformed. Error created client-side. - */ - TALER_EC_DEPOSITS_INVALID_SIGNATURE_BY_EXCHANGE = 1058, - - /** - * The given reserve does not have sufficient funds to admit the - * requested withdraw operation at this time. The response includes - * the current "balance" of the reserve as well as the transaction - * "history" that lead to this balance. This response is provided - * with HTTP status code #MHD_HTTP_CONFLICT. - */ - TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS = 1100, - - /** - * The exchange has no information about the "reserve_pub" that was - * given. This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_WITHDRAW_RESERVE_UNKNOWN = 1101, - - /** - * The amount to withdraw together with the fee exceeds the numeric - * range for Taler amounts. This is not a client failure, as the coin - * value and fees come from the exchange's configuration. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_AMOUNT_FEE_OVERFLOW = 1102, - - /** - * All of the deposited amounts into this reserve total up to a value - * that is too big for the numeric range for Taler amounts. This is - * not a client failure, as the transaction history comes from the - * exchange's configuration. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_AMOUNT_DEPOSITS_OVERFLOW = 1103, - - /** - * For one of the historic withdrawals from this reserve, the exchange - * could not find the denomination key. This is not a client failure, - * as the transaction history comes from the exchange's configuration. - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_HISTORIC_DENOMINATION_KEY_NOT_FOUND = 1104, - - /** - * All of the withdrawals from reserve total up to a value that is too - * big for the numeric range for Taler amounts. This is not a client - * failure, as the transaction history comes from the exchange's - * configuration. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_AMOUNT_WITHDRAWALS_OVERFLOW = 1105, - - /** - * The exchange somehow knows about this reserve, but there seem to - * have been no wire transfers made. This is not a client failure, as - * this is a database consistency issue of the exchange. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_RESERVE_WITHOUT_WIRE_TRANSFER = 1106, - - /** - * The exchange failed to create the signature using the denomination - * key. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_SIGNATURE_FAILED = 1107, - - /** - * The exchange failed to store the withdraw operation in its - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_DB_STORE_ERROR = 1108, - - /** - * The exchange failed to check against historic withdraw data from - * database (as part of ensuring the idempotency of the operation). - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_DB_FETCH_ERROR = 1109, - - /** - * The exchange is not aware of the denomination key the wallet - * requested for the withdrawal. This response is provided with HTTP - * status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_WITHDRAW_DENOMINATION_KEY_NOT_FOUND = 1110, - - /** - * The signature of the reserve is not valid. This response is - * provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_WITHDRAW_RESERVE_SIGNATURE_INVALID = 1111, - - /** - * When computing the reserve history, we ended up with a negative - * overall balance, which should be impossible. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1112, - - /** - * When computing the reserve history, we ended up with a negative - * overall balance, which should be impossible. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_RESERVE_HISTORY_IMPOSSIBLE = 1113, - - /** - * Validity period of the coin to be withdrawn is in the future. - * Returned with an HTTP status of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_WITHDRAW_VALIDITY_IN_FUTURE = 1114, - - /** - * Withdraw period of the coin to be withdrawn is in the past. - * Returned with an HTTP status of #MHD_HTTP_GONE. - */ - TALER_EC_WITHDRAW_VALIDITY_IN_PAST = 1115, - - /** - * Withdraw period of the coin to be withdrawn is in the past. - * Returned with an HTTP status of #MHD_HTTP_GONE. - */ - TALER_EC_DENOMINATION_KEY_LOST = 1116, - - /** - * The exchange's database entry with the reserve balance summary is - * inconsistent with its own history of the reserve. Returned with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_WITHDRAW_RESERVE_BALANCE_CORRUPT = 1117, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_WITHDRAW_REPLY_MALFORMED = 1118, - - /** - * The client failed to unblind the blind signature. This error is not - * used in the protocol but created client-side. - */ - TALER_EC_WITHDRAW_UNBLIND_FAILURE = 1119, - - /** - * The exchange failed to obtain the transaction history of the given - * reserve from the database. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_RESERVE_STATUS_DB_ERROR = 1150, - - /** - * The reserve status was requested using a unknown key, to be - * returned with 404 Not Found. - */ - TALER_EC_RESERVE_STATUS_UNKNOWN = 1151, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_RESERVE_STATUS_REPLY_MALFORMED = 1152, - - /** - * The respective coin did not have sufficient residual value for the - * /deposit operation (i.e. due to double spending). The "history" in - * the respose provides the transaction history of the coin proving - * this fact. This response is provided with HTTP status code - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS = 1200, - - /** - * The exchange failed to obtain the transaction history of the given - * coin from the database (this does not happen merely because the - * coin is seen by the exchange for the first time). This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSIT_HISTORY_DB_ERROR = 1201, - - /** - * The exchange failed to store the /depost information in the - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSIT_STORE_DB_ERROR = 1202, - - /** - * The exchange database is unaware of the denomination key that - * signed the coin (however, the exchange process is; this is not - * supposed to happen; it can happen if someone decides to purge the - * DB behind the back of the exchange process). Hence the deposit is - * being refused. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSIT_DB_DENOMINATION_KEY_UNKNOWN = 1203, - - /** - * The exchange was trying to lookup the denomination key for the - * purpose of a DEPOSIT operation. However, the denomination key is - * unavailable for that purpose. This can be because it is entirely - * unknown to the exchange or not in the validity period for the - * deposit operation. Hence the deposit is being refused. This - * response is provided with HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_DEPOSIT_DENOMINATION_KEY_UNKNOWN = 1204, - - /** - * The signature made by the coin over the deposit permission is not - * valid. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_COIN_SIGNATURE_INVALID = 1205, - - /** - * The signature of the denomination key over the coin is not valid. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_DENOMINATION_SIGNATURE_INVALID = 1206, - - /** - * The stated value of the coin after the deposit fee is subtracted - * would be negative. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE = 1207, - - /** - * The stated refund deadline is after the wire deadline. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE = 1208, - - /** - * The exchange does not recognize the validity of or support the - * given wire format type. This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_TYPE = 1209, - - /** - * The exchange failed to canonicalize and hash the given wire format. - * For example, the merchant failed to provide the "salt" or a valid - * payto:// URI in the wire details. Note that while the exchange - * will do some basic sanity checking on the wire details, it cannot - * warrant that the banking system will ultimately be able to route to - * the specified address, even if this check passed. This response is - * provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_JSON = 1210, - - /** - * The hash of the given wire address does not match the hash - * specified in the proposal data. This response is provided with - * HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_CONTRACT_HASH_CONFLICT = 1211, - - /** - * The exchange detected that the given account number is invalid for - * the selected wire format type. This response is provided with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSIT_INVALID_WIRE_FORMAT_ACCOUNT_NUMBER = 1213, - - /** - * Timestamp included in deposit permission is intolerably far off - * with respect to the clock of the exchange. - */ - TALER_EC_DEPOSIT_INVALID_TIMESTAMP = 1218, - - /** - * Validity period of the denomination key is in the future. Returned - * with an HTTP status of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_DEPOSIT_DENOMINATION_VALIDITY_IN_FUTURE = 1219, - - /** - * Denomination key of the coin is past the deposit deadline. - * Returned with an HTTP status of #MHD_HTTP_GONE. - */ - TALER_EC_DEPOSIT_DENOMINATION_EXPIRED = 1220, - - /** - * The signature provided by the exchange is not valid. Error created - * client-side. - */ - TALER_EC_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE = 1221, - - /** - * The currency specified for the deposit is different from the - * currency of the coin. This response is provided with HTTP status - * code #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_DEPOSIT_CURRENCY_MISMATCH = 1222, - - /** - * The respective coin did not have sufficient residual value for the - * /refresh/melt operation. The "history" in this response provdes - * the "residual_value" of the coin, which may be less than its - * "original_value". This response is provided with HTTP status code - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_MELT_INSUFFICIENT_FUNDS = 1300, - - /** - * The respective coin did not have sufficient residual value for the - * /refresh/melt operation. The "history" in this response provdes - * the "residual_value" of the coin, which may be less than its - * "original_value". This response is provided with HTTP status code - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_MELT_DENOMINATION_KEY_NOT_FOUND = 1301, - - /** - * The exchange had an internal error reconstructing the transaction - * history of the coin that was being melted. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_MELT_COIN_HISTORY_COMPUTATION_FAILED = 1302, - - /** - * The exchange failed to check against historic melt data from - * database (as part of ensuring the idempotency of the operation). - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_MELT_DB_FETCH_ERROR = 1303, - - /** - * The exchange failed to store session data in the database. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_MELT_DB_STORE_SESSION_ERROR = 1304, - - /** - * The exchange encountered melt fees exceeding the melted coin's - * contribution. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_MELT_FEES_EXCEED_CONTRIBUTION = 1305, - - /** - * The denomination key signature on the melted coin is invalid. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_MELT_DENOMINATION_SIGNATURE_INVALID = 1306, - - /** - * The signature made with the coin to be melted is invalid. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_MELT_COIN_SIGNATURE_INVALID = 1307, - - /** - * The exchange failed to obtain the transaction history of the given - * coin from the database while generating an insufficient funds - * errors. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_MELT_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS = 1308, - - /** - * The denomination of the given coin has past its expiration date and - * it is also not a valid zombie (that is, was not refreshed with the - * fresh coin being subjected to recoup). - */ - TALER_EC_MELT_COIN_EXPIRED_NO_ZOMBIE = 1309, - - /** - * The signature returned by the exchange in a melt request was - * malformed. Error created client-side. - */ - TALER_EC_MELT_INVALID_SIGNATURE_BY_EXCHANGE = 1310, - - /** - * The currency specified for the melt amount is different from the - * currency of the coin. This response is provided with HTTP status - * code #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_MELT_CURRENCY_MISMATCH = 1311, - - /** - * The exchange is unaware of the denomination key that was used to - * sign the melted zombie coin. This response is provided with HTTP - * status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_REFRESH_RECOUP_DENOMINATION_KEY_NOT_FOUND = 1351, - - /** - * Validity period of the denomination key is in the future. Returned - * with an HTTP status of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_REFRESH_RECOUP_DENOMINATION_VALIDITY_IN_FUTURE = 1352, - - /** - * Denomination key of the coin is past the deposit deadline. - * Returned with an HTTP status of #MHD_HTTP_GONE. - */ - TALER_EC_REFRESH_RECOUP_DENOMINATION_EXPIRED = 1353, - - /** - * Denomination key of the coin is past the deposit deadline. - * Returned with an HTTP status of #MHD_HTTP_GONE. - */ - TALER_EC_REFRESH_ZOMBIE_DENOMINATION_EXPIRED = 1354, - - /** - * The provided transfer keys do not match up with the original - * commitment. Information about the original commitment is included - * in the response. This response is provided with HTTP status code - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_REVEAL_COMMITMENT_VIOLATION = 1370, - - /** - * Failed to produce the blinded signatures over the coins to be - * returned. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_SIGNING_ERROR = 1371, - - /** - * The exchange is unaware of the refresh session specified in the - * request. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_SESSION_UNKNOWN = 1372, - - /** - * The exchange failed to retrieve valid session data from the - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_DB_FETCH_SESSION_ERROR = 1373, - - /** - * The exchange failed to retrieve previously revealed data from the - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_DB_FETCH_REVEAL_ERROR = 1374, - - /** - * The exchange failed to retrieve commitment data from the database. - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_DB_COMMIT_ERROR = 1375, - - /** - * The size of the cut-and-choose dimension of the private transfer - * keys request does not match #TALER_CNC_KAPPA - 1. This response is - * provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID = 1376, - - /** - * The number of coins to be created in refresh exceeds the limits of - * the exchange. private transfer keys request does not match - * #TALER_CNC_KAPPA - 1. This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE = 1377, - - /** - * The number of envelopes given does not match the number of - * denomination keys given. This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISMATCH = 1378, - - /** - * The exchange encountered a numeric overflow totaling up the cost - * for the refresh operation. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_COST_CALCULATION_OVERFLOW = 1379, - - /** - * The exchange's cost calculation shows that the melt amount is below - * the costs of the transaction. This response is provided with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_AMOUNT_INSUFFICIENT = 1380, - - /** - * The exchange is unaware of the denomination key that was requested - * for one of the fresh coins. This response is provided with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_FRESH_DENOMINATION_KEY_NOT_FOUND = 1381, - - /** - * The signature made with the coin over the link data is invalid. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REVEAL_LINK_SIGNATURE_INVALID = 1382, - - /** - * The exchange failed to generate the signature as it could not find - * the signing key for the denomination. This response is provided - * with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REVEAL_KEYS_MISSING = 1383, - - /** - * The refresh session hash given to a /refreshes/ handler was - * malformed. - */ - TALER_EC_REVEAL_INVALID_RCH = 1384, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_REVEAL_REPLY_MALFORMED = 1385, - - /** - * The coin specified in the link request is unknown to the exchange. - * This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_LINK_COIN_UNKNOWN = 1400, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_LINK_REPLY_MALFORMED = 1401, - - /** - * The exchange knows literally nothing about the coin we were asked - * to refund. But without a transaction history, we cannot issue a - * refund. This is kind-of OK, the owner should just refresh it - * directly without executing the refund. This response is provided - * with HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_REFUND_COIN_NOT_FOUND = 1500, - - /** - * We could not process the refund request as the coin's transaction - * history does not permit the requested refund at this time. The - * "history" in the response proves this. This response is provided - * with HTTP status code #MHD_HTTP_CONFLICT. - */ - TALER_EC_REFUND_CONFLICT = 1501, - - /** - * The exchange knows about the coin we were asked to refund, but not - * about the specific /deposit operation. Hence, we cannot issue a - * refund (as we do not know if this merchant public key is authorized - * to do a refund). This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_REFUND_DEPOSIT_NOT_FOUND = 1503, - - /** - * The currency specified for the refund is different from the - * currency of the coin. This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REFUND_CURRENCY_MISMATCH = 1504, - - /** - * When we tried to check if we already paid out the coin, the - * exchange's database suddenly disagreed with data it previously - * provided (internal inconsistency). This response is provided with - * HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REFUND_DB_INCONSISTENT = 1505, - - /** - * The exchange can no longer refund the customer/coin as the money - * was already transferred (paid out) to the merchant. (It should be - * past the refund deadline.) This response is provided with HTTP - * status code #MHD_HTTP_GONE. - */ - TALER_EC_REFUND_MERCHANT_ALREADY_PAID = 1506, - - /** - * The amount the exchange was asked to refund exceeds (with fees) the - * total amount of the deposit (including fees). This response is - * provided with HTTP status code #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_REFUND_INSUFFICIENT_FUNDS = 1507, - - /** - * The exchange failed to recover information about the denomination - * key of the refunded coin (even though it recognizes the key). - * Hence it could not check the fee strucutre. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REFUND_DENOMINATION_KEY_NOT_FOUND = 1508, - - /** - * The refund fee specified for the request is lower than the refund - * fee charged by the exchange for the given denomination key of the - * refunded coin. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REFUND_FEE_TOO_LOW = 1509, - - /** - * The exchange failed to store the refund information to its - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REFUND_STORE_DB_ERROR = 1510, - - /** - * The refund fee is specified in a different currency than the refund - * amount. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REFUND_FEE_CURRENCY_MISMATCH = 1511, - - /** - * The refunded amount is smaller than the refund fee, which would - * result in a negative refund. This response is provided with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REFUND_FEE_ABOVE_AMOUNT = 1512, - - /** - * The signature of the merchant is invalid. This response is provided - * with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_REFUND_MERCHANT_SIGNATURE_INVALID = 1513, - - /** - * Merchant backend failed to create the refund confirmation - * signature. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_REFUND_MERCHANT_SIGNING_FAILED = 1514, - - /** - * The signature returned by the exchange in a refund request was - * malformed. Error created client-side. - */ - TALER_EC_REFUND_INVALID_SIGNATURE_BY_EXCHANGE = 1515, - - /** - * The wire format specified in the "sender_account_details" is not - * understood or not supported by this exchange. Returned with an HTTP - * status code of #MHD_HTTP_NOT_FOUND. (As we did not find an - * interpretation of the wire format.) - */ - TALER_EC_ADMIN_ADD_INCOMING_WIREFORMAT_UNSUPPORTED = 1600, - - /** - * The currency specified in the "amount" parameter is not supported - * by this exhange. Returned with an HTTP status code of - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_ADMIN_ADD_INCOMING_CURRENCY_UNSUPPORTED = 1601, - - /** - * The exchange failed to store information about the incoming - * transfer in its database. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ADMIN_ADD_INCOMING_DB_STORE = 1602, - - /** - * The exchange encountered an error (that is not about not finding - * the wire transfer) trying to lookup a wire transfer identifier in - * the database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRANSFERS_GET_DB_FETCH_FAILED = 1700, - - /** - * The exchange found internally inconsistent data when resolving a - * wire transfer identifier in the database. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRANSFERS_GET_DB_INCONSISTENT = 1701, - - /** - * The exchange did not find information about the specified wire - * transfer identifier in the database. This response is provided - * with HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_TRANSFERS_GET_WTID_NOT_FOUND = 1702, - - /** - * The exchange did not find information about the wire transfer fees - * it charged. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRANSFERS_GET_WIRE_FEE_NOT_FOUND = 1703, - - /** - * The exchange found a wire fee that was above the total transfer - * value (and thus could not have been charged). This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRANSFERS_GET_WIRE_FEE_INCONSISTENT = 1704, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_TRANSFERS_GET_REPLY_MALFORMED = 1705, - - /** - * The exchange found internally inconsistent fee data when resolving - * a transaction in the database. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSITS_GET_DB_FEE_INCONSISTENT = 1800, - - /** - * The exchange encountered an error (that is not about not finding - * the transaction) trying to lookup a transaction in the database. - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSITS_GET_DB_FETCH_FAILED = 1801, - - /** - * The exchange did not find information about the specified - * transaction in the database. This response is provided with HTTP - * status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_DEPOSITS_GET_NOT_FOUND = 1802, - - /** - * The exchange failed to identify the wire transfer of the - * transaction (or information about the plan that it was supposed to - * still happen in the future). This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSITS_GET_WTID_RESOLUTION_ERROR = 1803, - - /** - * The signature of the merchant is invalid. This response is provided - * with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID = 1804, - - /** - * The given denomination key is not in the "recoup" set of the - * exchange right now. This response is provided with an HTTP status - * code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_RECOUP_DENOMINATION_KEY_UNKNOWN = 1850, - - /** - * The given coin signature is invalid for the request. This response - * is provided with an HTTP status code of #MHD_HTTP_FORBIDDEN. - */ - TALER_EC_RECOUP_SIGNATURE_INVALID = 1851, - - /** - * The signature of the denomination key over the coin is not valid. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_RECOUP_DENOMINATION_SIGNATURE_INVALID = 1852, - - /** - * The exchange failed to access its own database about reserves. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_RECOUP_DB_FETCH_FAILED = 1853, - - /** - * The exchange could not find the corresponding withdraw operation. - * The request is denied. This response is provided with an HTTP - * status code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_RECOUP_WITHDRAW_NOT_FOUND = 1854, - - /** - * The exchange obtained an internally inconsistent transaction - * history for the given coin. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_RECOUP_HISTORY_DB_ERROR = 1855, - - /** - * The exchange failed to store information about the recoup to be - * performed in the database. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_RECOUP_DB_PUT_FAILED = 1856, - - /** - * The coin's remaining balance is zero. The request is denied. This - * response is provided with an HTTP status code of - * #MHD_HTTP_FORBIDDEN. - */ - TALER_EC_RECOUP_COIN_BALANCE_ZERO = 1857, - - /** - * The exchange failed to reproduce the coin's blinding. This response - * is provided with an HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_RECOUP_BLINDING_FAILED = 1858, - - /** - * The coin's remaining balance is zero. The request is denied. This - * response is provided with an HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR - */ - TALER_EC_RECOUP_COIN_BALANCE_NEGATIVE = 1859, - - /** - * Validity period of the denomination key is in the future. Returned - * with an HTTP status of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_RECOUP_DENOMINATION_VALIDITY_IN_FUTURE = 1860, - - /** - * The exchange responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_RECOUP_REPLY_MALFORMED = 1861, - - /** - * The "have" parameter was not a natural number. This response is - * provied with an HTTP status code of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_KEYS_HAVE_NOT_NUMERIC = 1900, - - /** - * We currently cannot find any keys. This response is provied with an - * HTTP status code of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_KEYS_MISSING = 1901, - - /** - * This exchange does not allow clients to request /keys for times - * other than the current (exchange) time. This response is provied - * with an HTTP status code of #MHD_HTTP_FORBIDDEN. - */ - TALER_EC_KEYS_TIMETRAVEL_FORBIDDEN = 1902, - - /** - * The keys response was malformed. This error is generated client- - * side. - */ - TALER_EC_KEYS_INVALID = 1903, - - /** - * The backend could not find the merchant instance specified in the - * request. This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_INSTANCE_UNKNOWN = 2000, - - /** - * The backend lacks a wire transfer method configuration option for - * the given instance. - */ - TALER_EC_PROPOSAL_INSTANCE_CONFIGURATION_LACKS_WIRE = 2002, - - /** - * The merchant failed to provide a meaningful response to a /pay - * request. This error is created client-side. - */ - TALER_EC_PAY_MERCHANT_INVALID_RESPONSE = 2100, - - /** - * The exchange failed to provide a meaningful response to a /deposit - * request. This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY, or #MHD_HTTP_CONFLICT in case the - * exchange reports #TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS (aka double - * spending). - */ - TALER_EC_PAY_EXCHANGE_FAILED = 2101, - - /** - * The merchant failed to commit the exchanges' response to a /deposit - * request to its database. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_DB_STORE_PAY_ERROR = 2102, - - /** - * The specified exchange is not supported/trusted by this merchant. - * This response is provided with HTTP status code - * #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_PAY_EXCHANGE_REJECTED = 2103, - - /** - * The denomination key used for payment is not listed among the - * denomination keys of the exchange. This response is provided with - * HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_DENOMINATION_KEY_NOT_FOUND = 2104, - - /** - * The denomination key used for payment is not audited by an auditor - * approved by the merchant. This response is provided with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_DENOMINATION_KEY_AUDITOR_FAILURE = 2105, - - /** - * There was an integer overflow totaling up the amounts or deposit - * fees in the payment. This response is provided with HTTP status - * code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_AMOUNT_OVERFLOW = 2106, - - /** - * The deposit fees exceed the total value of the payment. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_FEES_EXCEED_PAYMENT = 2107, - - /** - * After considering deposit and wire fees, the payment is - * insufficient to satisfy the required amount for the contract. The - * client should revisit the logic used to calculate fees it must - * cover. This response is provided with HTTP status code - * #MHD_HTTP_ACCEPTED. - */ - TALER_EC_PAY_PAYMENT_INSUFFICIENT_DUE_TO_FEES = 2108, - - /** - * Even if we do not consider deposit and wire fees, the payment is - * insufficient to satisfy the required amount for the contract. This - * response is provided with HTTP status code #MHD_HTTP_ACCEPTED. - */ - TALER_EC_PAY_PAYMENT_INSUFFICIENT = 2109, - - /** - * The signature over the contract of one of the coins was invalid. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_COIN_SIGNATURE_INVALID = 2110, - - /** - * We failed to contact the exchange for the /pay request. This - * response is provided with HTTP status code - * #MHD_HTTP_REQUEST_TIMEOUT. - */ - TALER_EC_PAY_EXCHANGE_TIMEOUT = 2111, - - /** - * When we tried to find information about the exchange to issue the - * deposit, we failed. This usually only happens if the merchant - * backend is somehow unable to get its own HTTP client logic to work. - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_EXCHANGE_LOOKUP_FAILED = 2112, - - /** - * The refund deadline in the contract is after the transfer deadline. - * This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR as this should have been caught - * when the offer was first setup. - */ - TALER_EC_PAY_REFUND_DEADLINE_PAST_WIRE_TRANSFER_DEADLINE = 2114, - - /** - * The request fails to provide coins for the payment. This response - * is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_COINS_ARRAY_EMPTY = 2115, - - /** - * The merchant failed to fetch the contract terms from the merchant's - * database. This response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_DB_FETCH_PAY_ERROR = 2116, - - /** - * The merchant failed to fetch the merchant's previous state with - * respect to transactions from its database. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_DB_FETCH_TRANSACTION_ERROR = 2117, - - /** - * The merchant failed to store the merchant's state with respect to - * the transaction in its database. This response is provided with - * HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_DB_STORE_TRANSACTION_ERROR = 2119, - - /** - * The exchange failed to provide a valid response to the merchant's - * /keys request. This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENDCY. - */ - TALER_EC_PAY_EXCHANGE_KEYS_FAILURE = 2120, - - /** - * The payment is too late, the offer has expired. This response is - * provided with HTTP status code #MHD_HTTP_GONE. - */ - TALER_EC_PAY_OFFER_EXPIRED = 2121, - - /** - * The "merchant" field is missing in the proposal data. This response - * is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PAY_MERCHANT_FIELD_MISSING = 2122, - - /** - * Failed computing a hash code (likely server out-of-memory). This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_FAILED_COMPUTE_PROPOSAL_HASH = 2123, - - /** - * Failed to locate merchant's account information matching the wire - * hash given in the proposal. This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_WIRE_HASH_UNKNOWN = 2124, - - /** - * We got different currencies for the wire fee and the maximum wire - * fee. This response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_WIRE_FEE_CURRENCY_MISMATCH = 2125, - - /** - * A unknown merchant public key was included in the payment. That - * happens typically when the wallet sends the payment to the wrong - * merchant instance. This response is provided with an HTTP status - * code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_PAY_WRONG_INSTANCE = 2127, - - /** - * The exchange failed to give us a response when we asked for /keys. - * This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_PAY_EXCHANGE_HAS_NO_KEYS = 2128, - - /** - * The deposit time for the denomination has expired. This response is - * provided with HTTP status code #MHD_HTTP_GONE. - */ - TALER_EC_PAY_DENOMINATION_DEPOSIT_EXPIRED = 2129, - - /** - * The proposal is not known to the backend. This response is provided - * with an HTTP status code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_PAY_PROPOSAL_NOT_FOUND = 2130, - - /** - * The exchange of the deposited coin charges a wire fee that could - * not be added to the total (total amount too high). This response - * is provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED = 2131, - - /** - * The contract was not fully paid because of refunds. Note that - * clients MAY treat this as paid if, for example, contracts must be - * executed despite of refunds. This response is provided with HTTP - * status code #MHD_HTTP_PAYMENT_REQUIRED. - */ - TALER_EC_PAY_REFUNDED = 2132, - - /** - * According to our database, we have refunded more than we were paid - * (which should not be possible). This response is provided with HTTP - * status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PAY_REFUNDS_EXCEED_PAYMENTS = 2133, - - /** - * Legacy stuff. Remove me with protocol v1. This response is provided - * with HTTP status code #MHD_HTTP_PREREQUISTE. - */ - TALER_EC_PAY_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE = 2134, - - /** - * The merchant failed to contact the exchange. This response is - * provided with HTTP status code of #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_ABORT_EXCHANGE_KEYS_FAILURE = 2150, - - /** - * The merchant failed to send the exchange the refund request. This - * response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ABORT_EXCHANGE_REFUND_FAILED = 2151, - - /** - * The merchant failed to find the exchange to process the lookup. - * This response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ABORT_EXCHANGE_LOOKUP_FAILED = 2152, - - /** - * The merchant failed to store the abort request in its database. - * This response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ABORT_DB_STORE_ABORT_ERROR = 2153, - - /** - * The merchant failed to repeatedly serialize the transaction. This - * response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ABORT_DB_STORE_TRANSACTION_ERROR = 2154, - - /** - * The merchant failed in the lookup part of the transaction. This - * response is provided with HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ABORT_DB_FETCH_TRANSACTION_ERROR = 2155, - - /** - * The merchant could not find the contract. This response is provided - * with HTTP status code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_ABORT_CONTRACT_NOT_FOUND = 2156, - - /** - * The payment was already completed and thus cannot be aborted - * anymore. This response is provided with HTTP status code of - * #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE = 2157, - - /** - * The hash provided by the wallet does not match the order. This - * response is provided with HTTP status code of #MHD_HTTP_FORBIDDEN. - */ - TALER_EC_ABORT_CONTRACT_HASH_MISSMATCH = 2158, - - /** - * The array of coins cannot be empty. This response is provided with - * HTTP status code of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_ABORT_COINS_ARRAY_EMPTY = 2159, - - /** - * The merchant experienced a timeout processing the request. This - * response is provided with HTTP status code of - * #MHD_HTTP_REQUEST_TIMEOUT. - */ - TALER_EC_ABORT_EXCHANGE_TIMEOUT = 2160, - - /** - * Integer overflow with specified timestamp argument detected. This - * response is provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_HISTORY_TIMESTAMP_OVERFLOW = 2200, - - /** - * Failed to retrieve history from merchant database. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_HISTORY_DB_FETCH_ERROR = 2201, - - /** - * The backend could not find the contract specified in the request. - * This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_POLL_PAYMENT_CONTRACT_NOT_FOUND = 2250, - - /** - * The response provided by the merchant backend was malformed. This - * error is created client-side. - */ - TALER_EC_POLL_PAYMENT_REPLY_MALFORMED = 2251, - - /** - * We failed to contact the exchange for the /track/transaction - * request. This response is provided with HTTP status code - * #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_TRACK_TRANSACTION_EXCHANGE_TIMEOUT = 2300, - - /** - * We failed to get a valid /keys response from the exchange for the - * /track/transaction request. This response is provided with HTTP - * status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSACTION_EXCHANGE_KEYS_FAILURE = 2301, - - /** - * The backend could not find the transaction specified in the - * request. This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_TRACK_TRANSACTION_TRANSACTION_UNKNOWN = 2302, - - /** - * The backend had a database access error trying to retrieve - * transaction data from its database. The response is provided with - * HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSACTION_DB_FETCH_TRANSACTION_ERROR = 2303, - - /** - * The backend had a database access error trying to retrieve payment - * data from its database. The response is provided with HTTP status - * code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSACTION_DB_FETCH_PAYMENT_ERROR = 2304, - - /** - * The backend found no applicable deposits in the database. This is - * odd, as we know about the transaction, but not about deposits we - * made for the transaction. The response is provided with HTTP - * status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_TRACK_TRANSACTION_DB_NO_DEPOSITS_ERROR = 2305, - - /** - * We failed to obtain a wire transfer identifier for one of the coins - * in the transaction. The response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY if the exchange had a hard error, or - * #MHD_HTTP_ACCEPTED if the exchange signaled that the transfer was - * in progress. - */ - TALER_EC_TRACK_TRANSACTION_COIN_TRACE_ERROR = 2306, - - /** - * We failed to obtain the full wire transfer identifier for the - * transfer one of the coins was aggregated into. The response is - * provided with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSACTION_WIRE_TRANSFER_TRACE_ERROR = 2307, - - /** - * We got conflicting reports from the exhange with respect to which - * transfers are included in which aggregate. The response is provided - * with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSACTION_CONFLICTING_REPORTS = 2308, - - /** - * We failed to contact the exchange for the /track/transfer request. - * This response is provided with HTTP status code - * #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_TRACK_TRANSFER_EXCHANGE_TIMEOUT = 2400, - - /** - * We failed to obtain an acceptable /keys response from the exchange - * for the /track/transfer request. This response is provided with - * HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSFER_EXCHANGE_KEYS_FAILURE = 2401, - - /** - * We failed to persist coin wire transfer information in our merchant - * database. The response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSFER_DB_STORE_COIN_ERROR = 2402, - - /** - * We internally failed to execute the /track/transfer request. The - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSFER_REQUEST_ERROR = 2403, - - /** - * We failed to persist wire transfer information in our merchant - * database. The response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR = 2404, - - /** - * The exchange returned an error from /track/transfer. The response - * is provided with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSFER_EXCHANGE_ERROR = 2405, - - /** - * We failed to fetch deposit information from our merchant database. - * The response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR = 2406, - - /** - * We encountered an internal logic error. The response is provided - * with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TRACK_TRANSFER_DB_INTERNAL_LOGIC_ERROR = 2407, - - /** - * The exchange gave conflicting information about a coin which has - * been wire transferred. The response is provided with HTTP status - * code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSFER_CONFLICTING_REPORTS = 2408, - - /** - * The merchant backend had problems in creating the JSON response. - */ - TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR = 2409, - - /** - * The exchange charged a different wire fee than what it originally - * advertised, and it is higher. The response is provied with an HTTP - * status of #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TRACK_TRANSFER_JSON_BAD_WIRE_FEE = 2410, - - /** - * The merchant backend cannot create an instance under the given - * identifier as one already exists. Use PATCH to modify the existing - * entry. The response is provied with an HTTP status of - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_POST_INSTANCES_ALREADY_EXISTS = 2450, - - /** - * The merchant backend cannot create an instance because the - * specified bank accounts are somehow invalid. The response is - * provied with an HTTP status of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_POST_INSTANCES_BAD_PAYTO_URIS = 2451, - - /** - * The merchant backend cannot create an instance because it failed to - * start the database transaction. The response is provied with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_POST_INSTANCES_DB_START_ERROR = 2452, - - /** - * The merchant backend cannot create an instance because it failed to - * commit the database transaction. The response is provied with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_POST_INSTANCES_DB_COMMIT_ERROR = 2453, - - /** - * The merchant backend cannot delete an instance because it failed to - * commit the database transaction. The response is provied with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DELETE_INSTANCES_ID_DB_HARD_FAILURE = 2454, - - /** - * The merchant backend cannot delete the data because it already does - * not exist. The response is provied with an HTTP status of - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_DELETE_INSTANCES_ID_NO_SUCH_INSTANCE = 2455, - - /** - * The merchant backend cannot update an instance because the - * specified bank accounts are somehow invalid. The response is - * provied with an HTTP status of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PATCH_INSTANCES_BAD_PAYTO_URIS = 2456, - - /** - * The merchant backend cannot patch an instance because it failed to - * start the database transaction. The response is provied with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PATCH_INSTANCES_DB_START_ERROR = 2457, - - /** - * The merchant backend cannot patch an instance because it failed to - * commit the database transaction. The response is provied with an - * HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PATCH_INSTANCES_DB_COMMIT_ERROR = 2458, - - /** - * The hash provided in the request of /map/in does not match the - * contract sent alongside in the same request. - */ - TALER_EC_MAP_IN_UNMATCHED_HASH = 2500, - - /** - * The backend encountered an error while trying to store the - * h_contract_terms into the database. The response is provided with - * HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_STORE_DB_ERROR = 2501, - - /** - * The backend encountered an error while trying to retrieve the - * proposal data from database. Likely to be an internal error. The - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_LOOKUP_DB_ERROR = 2502, - - /** - * The proposal being looked up is not found on this merchant. - * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND - */ - TALER_EC_PROPOSAL_LOOKUP_NOT_FOUND = 2503, - - /** - * The proposal had no timestamp and the backend failed to obtain the - * local time. Likely to be an internal error. The response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_NO_LOCALTIME = 2504, - - /** - * The order provided to the backend could not be parsed, some - * required fields were missing or ill-formed. Returned with an HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PROPOSAL_ORDER_PARSE_ERROR = 2505, - - /** - * The backend encountered an error while trying to find the existing - * proposal in the database. The response is provided with HTTP status - * code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_STORE_DB_ERROR_HARD = 2506, - - /** - * The backend encountered an error while trying to find the existing - * proposal in the database. The response is provided with HTTP status - * code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_STORE_DB_ERROR_SOFT = 2507, - - /** - * The backend encountered an error: the proposal already exists. The - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PROPOSAL_STORE_DB_ERROR_ALREADY_EXISTS = 2508, - - /** - * The order provided to the backend uses an amount in a currency that - * does not match the backend's configuration. Returned with HTTP - * status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_PROPOSAL_ORDER_BAD_CURRENCY = 2509, - - /** - * The response provided by the merchant backend was malformed. This - * error is created client-side. - */ - TALER_EC_PROPOSAL_REPLY_MALFORMED = 2510, - - /** - * The order provided to the backend could not be deleted, it is not - * known. Returned with an HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_ORDERS_DELETE_NO_SUCH_ORDER = 2511, - - /** - * The order provided to the backend could not be deleted, our offer - * is still valid and awaiting payment. Returned with an HTTP status - * code #MHD_HTTP_CONFLICT. - */ - TALER_EC_ORDERS_DELETE_AWAITING_PAYMENT = 2512, - - /** - * The order provided to the backend could not be deleted, due to a - * database error. Returned with an HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_DELETE_DB_HARD_FAILURE = 2513, - - /** - * The order provided to the backend could not be completed, due to a - * database error trying to fetch product inventory data. Returned - * with an HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_LOOKUP_PRODUCT_DB_HARD_FAILURE = 2514, - - /** - * The order provided to the backend could not be completed, due to a - * database serialization error (which should be impossible) trying to - * fetch product inventory data. Returned with an HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_LOOKUP_PRODUCT_DB_SOFT_FAILURE = 2515, - - /** - * The order provided to the backend could not be completed, because a - * product to be completed via inventory data is not actually in our - * inventory. Returned with an HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_ORDERS_LOOKUP_PRODUCT_NOT_FOUND = 2516, - - /** - * We could not obtain a list of all orders because of a database - * failure. Returned with an HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_GET_DB_LOOKUP_ERROR = 2517, - - /** - * We could not claim the order because of a database failure. - * Returned with an HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_CLAIM_HARD_DB_ERROR = 2518, - - /** - * We could not claim the order because of a database serialization - * failure. Returned with an HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_ORDERS_CLAIM_SOFT_DB_ERROR = 2519, - - /** - * We could not claim the order because the backend is unaware of it. - * Returned with an HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_ORDERS_CLAIM_NOT_FOUND = 2520, - - /** - * We could not claim the order because someone else claimed it first. - * Returned with an HTTP status code #MHD_HTTP_CONFLICT. - */ - TALER_EC_ORDERS_ALREADY_CLAIMED = 2521, - - /** - * The merchant backend failed to lookup the products. The response is - * provied with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_GET_PRODUCTS_DB_LOOKUP_ERROR = 2550, - - /** - * The merchant backend failed to start the transaction. The response - * is provied with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PRODUCTS_POST_DB_START_ERROR = 2551, - - /** - * The product ID exists. The response is provied with an HTTP status - * of #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_POST_CONFLICT_PRODUCT_EXISTS = 2552, - - /** - * The merchant backend failed to serialize the transaction. The - * response is provied with an HTTP status of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PRODUCTS_POST_DB_COMMIT_SOFT_ERROR = 2553, - - /** - * The merchant backend failed to commit the transaction. The response - * is provied with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PRODUCTS_POST_DB_COMMIT_HARD_ERROR = 2554, - - /** - * The merchant backend failed to commit the transaction. The response - * is provied with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PRODUCTS_PATCH_DB_COMMIT_HARD_ERROR = 2555, - - /** - * The merchant backend did not find the product to be updated. The - * response is provied with an HTTP status of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_PRODUCTS_PATCH_UNKNOWN_PRODUCT = 2556, - - /** - * The update would have reduced the total amount of product lost, - * which is not allowed. The response is provied with an HTTP status - * of #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_PATCH_TOTAL_LOST_REDUCED = 2557, - - /** - * The update would have mean that more stocks were lost than what - * remains from total inventory after sales, which is not allowed. The - * response is provied with an HTTP status of #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_PATCH_TOTAL_LOST_EXCEEDS_STOCKS = 2558, - - /** - * The update would have reduced the total amount of product in stock, - * which is not allowed. The response is provied with an HTTP status - * of #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_PATCH_TOTAL_STOCKED_REDUCED = 2559, - - /** - * The lock request is for more products than we have left (unlocked) - * in stock. The response is provied with an HTTP status of - * #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_LOCK_INSUFFICIENT_STOCKS = 2560, - - /** - * The lock request is for an unknown product. The response is provied - * with an HTTP status of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_PRODUCTS_LOCK_UNKNOWN_PRODUCT = 2561, - - /** - * The deletion request resulted in a hard database error. The - * response is provied with an HTTP status of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_PRODUCTS_DELETE_DB_HARD_FAILURE = 2562, - - /** - * The deletion request was for a product unknown to the backend. The - * response is provied with an HTTP status of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_PRODUCTS_DELETE_NO_SUCH_PRODUCT = 2563, - - /** - * The deletion request is for a product that is locked. The response - * is provied with an HTTP status of #MHD_HTTP_CONFLICT. - */ - TALER_EC_PRODUCTS_DELETE_CONFLICTING_LOCK = 2564, - - /** - * The merchant returned a malformed response. Error created client- - * side. - */ - TALER_EC_REFUND_LOOKUP_INVALID_RESPONSE = 2600, - - /** - * The frontend gave an unknown order id to issue the refund to. - */ - TALER_EC_REFUND_ORDER_ID_UNKNOWN = 2601, - - /** - * The amount to be refunded is inconsistent: either is lower than the - * previous amount being awarded, or it is too big to be paid back. In - * this second case, the fault stays on the business dept. side. - * Returned with an HTTP status of #MHD_HTTP_CONFLICT. - */ - TALER_EC_REFUND_INCONSISTENT_AMOUNT = 2602, - - /** - * The backend encountered an error while trying to retrieve the - * payment data from database. Likely to be an internal error. - */ - TALER_EC_REFUND_LOOKUP_DB_ERROR = 2603, - - /** - * The backend encountered an error while trying to retrieve the - * payment data from database. Likely to be an internal error. - */ - TALER_EC_REFUND_MERCHANT_DB_COMMIT_ERROR = 2604, - - /** - * Payments are stored in a single db transaction; this error - * indicates that one db operation within that transaction failed. - * This might involve storing of coins or other related db operations, - * like starting/committing the db transaction or marking a contract - * as paid. - */ - TALER_EC_PAY_DB_STORE_PAYMENTS_ERROR = 2605, - - /** - * The backend failed to sign the refund request. - */ - TALER_EC_PAY_REFUND_SIGNATURE_FAILED = 2606, - - /** - * The merchant backend is not available of any applicable refund(s) - * for this order. Returned with an HTTP status of - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_REFUND_LOOKUP_NO_REFUND = 2607, - - /** - * The backend knows the instance that was supposed to support the - * tip, but it was not configured for tipping (i.e. has no exchange - * associated with it). Likely to be a configuration error. Returned - * with an HTTP status code of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_TIP_AUTHORIZE_INSTANCE_DOES_NOT_TIP = 2701, - - /** - * The reserve that was used to fund the tips has expired. Returned - * with an HTTP status code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_TIP_AUTHORIZE_RESERVE_EXPIRED = 2702, - - /** - * The reserve that was used to fund the tips was not found in the DB. - * Returned with an HTTP status code of #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_TIP_AUTHORIZE_RESERVE_UNKNOWN = 2703, - - /** - * The backend knows the instance that was supposed to support the - * tip, and it was configured for tipping. However, the funds - * remaining are insufficient to cover the tip, and the merchant - * should top up the reserve. Returned with an HTTP status code of - * #MHD_HTTP_PRECONDITION FAILED. - */ - TALER_EC_TIP_AUTHORIZE_INSUFFICIENT_FUNDS = 2704, - - /** - * The backend had trouble accessing the database to persist - * information about the tip authorization. Returned with an HTTP - * status code of internal error. - */ - TALER_EC_TIP_AUTHORIZE_DB_HARD_ERROR = 2705, - - /** - * The backend had trouble accessing the database to persist - * information about the tip authorization. The problem might be - * fixable by repeating the transaction. - */ - TALER_EC_TIP_AUTHORIZE_DB_SOFT_ERROR = 2706, - - /** - * The backend failed to obtain a reserve status from the exchange. - * This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_STATUS_FAILED_EXCHANGE_DOWN = 2707, - - /** - * The backend got an empty (!) reserve history from the exchange. - * This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_FAILED_EMPTY = 2708, - - /** - * The backend got an invalid reserve history (fails to start with a - * deposit) from the exchange. This response is provided with HTTP - * status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_INVALID_NO_DEPOSIT = 2709, - - /** - * The backend got an 404 response from the exchange when it inquired - * about the reserve history. The response is provided with HTTP - * status code #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_TIP_QUERY_RESERVE_UNKNOWN_TO_EXCHANGE = 2710, - - /** - * The backend got a reserve with a currency that does not match the - * backend's currency. The response is provided with HTTP status code - * #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_TIP_QUERY_RESERVE_CURRENCY_MISMATCH = 2711, - - /** - * The backend got a reserve history with amounts it cannot process - * (addition failure in deposits). The response is provided with HTTP - * status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_DEPOSIT = 2712, - - /** - * The backend got a reserve history with amounts it cannot process - * (addition failure in withdraw amounts). The response is provided - * with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_WITHDRAW = 2713, - - /** - * The backend got a reserve history with amounts it cannot process - * (addition failure in closing amounts). The response is provided - * with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_CLOSED = 2714, - - /** - * The backend got a reserve history with inconsistent amounts. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_INCONSISTENT = 2715, - - /** - * The backend encountered a database error querying tipping reserves. - */ - TALER_EC_TIP_QUERY_DB_ERROR = 2716, - - /** - * The backend got an unexpected resever history reply from the - * exchange. This response is provided with HTTP status code - * #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_FAILED = 2717, - - /** - * The backend got a reserve history with amounts it cannot process - * (addition failure in withdraw amounts). The response is provided - * with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_QUERY_RESERVE_HISTORY_ARITHMETIC_ISSUE_RECOUP = 2718, - - /** - * The backend knows the instance that was supposed to support the - * tip, but it was not configured for tipping (i.e. has no exchange - * associated with it). Likely to be a configuration error. Returned - * with an HTTP status code of #MHD_HTTP_PRECONDITION_FAILED. - */ - TALER_EC_TIP_QUERY_INSTANCE_DOES_NOT_TIP = 2719, - - /** - * The tip id is unknown. This could happen if the tip id is wrong or - * the tip authorization expired. - */ - TALER_EC_TIP_QUERY_TIP_ID_UNKNOWN = 2720, - - /** - * The backend had trouble accessing the database to persist - * information about enabling tips. Returned with an HTTP status code - * of internal error. - */ - TALER_EC_TIP_ENABLE_DB_TRANSACTION_ERROR = 2750, - - /** - * The tip ID is unknown. This could happen if the tip has expired. - * Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_TIP_PICKUP_TIP_ID_UNKNOWN = 2800, - - /** - * The amount requested exceeds the remaining tipping balance for this - * tip ID. Returned with an HTTP status code of "Conflict" (as it - * conflicts with a previous pickup operation). - */ - TALER_EC_TIP_PICKUP_NO_FUNDS = 2801, - - /** - * We encountered a DB error, repeating the request may work. - */ - TALER_EC_TIP_PICKUP_DB_ERROR_SOFT = 2802, - - /** - * We encountered a DB error, repeating the request will not help. - * This is an internal server error. - */ - TALER_EC_TIP_PICKUP_DB_ERROR_HARD = 2803, - - /** - * The same pickup ID was already used for picking up a different - * amount. This points to a very strange internal error as the pickup - * ID is derived from the denomination key which is tied to a - * particular amount. Hence this should also be an internal server - * error. - */ - TALER_EC_TIP_PICKUP_AMOUNT_CHANGED = 2804, - - /** - * We failed to contact the exchange to obtain the denomination keys. - * Returned with a response code #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_PICKUP_EXCHANGE_DOWN = 2805, - - /** - * We contacted the exchange to obtain any denomination keys, but got - * no valid keys. Returned with a response code - * #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_PICKUP_EXCHANGE_LACKED_KEYS = 2806, - - /** - * We contacted the exchange to obtain at least one of the - * denomination keys specified in the request. Returned with a - * response code "not found" (404). - */ - TALER_EC_TIP_PICKUP_EXCHANGE_LACKED_KEY = 2807, - - /** - * We encountered an arithmetic issue totaling up the amount to - * withdraw. Returned with a response code of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_TIP_PICKUP_EXCHANGE_AMOUNT_OVERFLOW = 2808, - - /** - * The number of planchets specified exceeded the limit. Returned with - * a response code of #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_TIP_PICKUP_EXCHANGE_TOO_MANY_PLANCHETS = 2809, - - /** - * The merchant failed to initialize the withdraw operaiton. Returned - * with a response code of #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TIP_PICKUP_WITHDRAW_FAILED = 2810, - - /** - * The merchant failed to initialize the withdraw operaiton. Returned - * with a response code of #MHD_HTTP_FAILED_DEPENDENCY. - */ - TALER_EC_TIP_PICKUP_WITHDRAW_FAILED_AT_EXCHANGE = 2811, - - /** - * The client failed to unblind the signature returned by the - * merchant. Generated client-side. - */ - TALER_EC_TIP_PICKUP_UNBLIND_FAILURE = 2812, - - /** - * We failed to contract terms from our merchant database. The - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_CHECK_PAYMENT_DB_FETCH_CONTRACT_TERMS_ERROR = 2911, - - /** - * We failed to contract terms from our merchant database. The - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_CHECK_PAYMENT_DB_FETCH_ORDER_ERROR = 2912, - - /** - * The order id we're checking is unknown, likely the frontend did not - * create the order first. - */ - TALER_EC_CHECK_PAYMENT_ORDER_ID_UNKNOWN = 2913, - - /** - * Failed computing a hash code (likely server out-of-memory). This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_CHECK_PAYMENT_FAILED_COMPUTE_PROPOSAL_HASH = 2914, - - /** - * Signature "session_sig" failed to verify. This response is provided - * with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_CHECK_PAYMENT_SESSION_SIGNATURE_INVALID = 2915, - - /** - * The response we received from the merchant is malformed. This error - * is generated client-side. - */ - TALER_EC_CHECK_PAYMENT_RESPONSE_MALFORMED = 2916, - - /** - * The signature from the exchange on the deposit confirmation is - * invalid. Returned with a "400 Bad Request" status code. - */ - TALER_EC_DEPOSIT_CONFIRMATION_SIGNATURE_INVALID = 3000, - - /** - * The auditor had trouble storing the deposit confirmation in its - * database. Returned with an HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_DEPOSIT_CONFIRMATION_STORE_DB_ERROR = 3001, - - /** - * The auditor had trouble retrieving the exchange list from its - * database. Returned with an HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_LIST_EXCHANGES_DB_ERROR = 3002, - - /** - * The auditor had trouble storing an exchange in its database. - * Returned with an HTTP status code of - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_AUDITOR_EXCHANGE_STORE_DB_ERROR = 3003, - - /** - * The auditor (!) responded with a reply that did not satsify the - * protocol. This error is not used in the protocol but created - * client-side. - */ - TALER_EC_AUDITOR_EXCHANGES_REPLY_MALFORMED = 3004, - - /** - * The exchange failed to compute ECDH. This response is provided - * with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TEST_ECDH_ERROR = 4000, - - /** - * The EdDSA test signature is invalid. This response is provided - * with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_TEST_EDDSA_INVALID = 4001, - - /** - * The exchange failed to compute the EdDSA test signature. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TEST_EDDSA_ERROR = 4002, - - /** - * The exchange failed to generate an RSA key. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TEST_RSA_GEN_ERROR = 4003, - - /** - * The exchange failed to compute the public RSA key. This response - * is provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TEST_RSA_PUB_ERROR = 4004, - - /** - * The exchange failed to compute the RSA signature. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_TEST_RSA_SIGN_ERROR = 4005, - - /** - * The JSON in the server's response was malformed. This response is - * provided with HTTP status code of 0. - */ - TALER_EC_SERVER_JSON_INVALID = 5000, - - /** - * A signature in the server's response was malformed. This response - * is provided with HTTP status code of 0. - */ - TALER_EC_SERVER_SIGNATURE_INVALID = 5001, - - /** - * Wire transfer attempted with credit and debit party being the same - * bank account. - */ - TALER_EC_BANK_SAME_ACCOUNT = 5102, - - /** - * Wire transfer impossible, due to financial limitation of the party - * that attempted the payment. - */ - TALER_EC_BANK_UNALLOWED_DEBIT = 5103, - - /** - * Arithmetic operation between two amounts of different currency was - * attempted. - */ - TALER_EC_BANK_CURRENCY_MISMATCH = 5104, - - /** - * At least one GET parameter was either missing or invalid for the - * requested operation. - */ - TALER_EC_BANK_PARAMETER_MISSING_OR_INVALID = 5105, - - /** - * JSON body sent was invalid for the requested operation. - */ - TALER_EC_BANK_JSON_INVALID = 5106, - - /** - * Negative number was used (as value and/or fraction) to initiate a - * Amount object. - */ - TALER_EC_BANK_NEGATIVE_NUMBER_AMOUNT = 5107, - - /** - * A number too big was used (as value and/or fraction) to initiate a - * amount object. - */ - TALER_EC_BANK_NUMBER_TOO_BIG = 5108, - - /** - * Could not login for the requested operation. - */ - TALER_EC_BANK_LOGIN_FAILED = 5109, - - /** - * The bank account referenced in the requested operation was not - * found. Returned along "400 Not found". - */ - TALER_EC_BANK_UNKNOWN_ACCOUNT = 5110, - - /** - * The transaction referenced in the requested operation (typically a - * reject operation), was not found. - */ - TALER_EC_BANK_TRANSACTION_NOT_FOUND = 5111, - - /** - * Bank received a malformed amount string. - */ - TALER_EC_BANK_BAD_FORMAT_AMOUNT = 5112, - - /** - * The client does not own the account credited by the transaction - * which is to be rejected, so it has no rights do reject it. To be - * returned along HTTP 403 Forbidden. - */ - TALER_EC_BANK_REJECT_NO_RIGHTS = 5200, - - /** - * This error code is returned when no known exception types captured - * the exception, and comes along with a 500 Internal Server Error. - */ - TALER_EC_BANK_UNMANAGED_EXCEPTION = 5300, - - /** - * This error code is used for all those exceptions that do not really - * need a specific error code to return to the client, but need to - * signal the middleware that the bank is not responding with 500 - * Internal Server Error. Used for example when a client is trying to - * register with a unavailable username. - */ - TALER_EC_BANK_SOFT_EXCEPTION = 5400, - - /** - * The request UID for a request to transfer funds has already been - * used, but with different details for the transfer. - */ - TALER_EC_BANK_TRANSFER_REQUEST_UID_REUSED = 5500, - - /** - * The sync service failed to access its database. This response is - * provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_DB_FETCH_ERROR = 6000, - - /** - * The sync service failed find the record in its database. This - * response is provided with HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_SYNC_BACKUP_UNKNOWN = 6001, - - /** - * The sync service failed find the account in its database. This - * response is provided with HTTP status code #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_SYNC_ACCOUNT_UNKNOWN = 6002, - - /** - * The SHA-512 hash provided in the If-None-Match header is malformed. - * This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_SYNC_BAD_IF_NONE_MATCH = 6003, - - /** - * The SHA-512 hash provided in the If-Match header is malformed or - * missing. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_SYNC_BAD_IF_MATCH = 6004, - - /** - * The signature provided in the "Sync-Signature" header is malformed - * or missing. This response is provided with HTTP status code - * #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_SYNC_BAD_SYNC_SIGNATURE = 6005, - - /** - * The signature provided in the "Sync-Signature" header does not - * match the account, old or new Etags. This response is provided with - * HTTP status code #MHD_HTTP_FORBIDDEN. - */ - TALER_EC_SYNC_INVALID_SIGNATURE = 6007, - - /** - * The "Content-length" field for the upload is either not a number, - * or too big, or missing. This response is provided with HTTP status - * code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_SYNC_BAD_CONTENT_LENGTH = 6008, - - /** - * The "Content-length" field for the upload is too big based on the - * server's terms of service. This response is provided with HTTP - * status code #MHD_HTTP_PAYLOAD_TOO_LARGE. - */ - TALER_EC_SYNC_EXCESSIVE_CONTENT_LENGTH = 6009, - - /** - * The server is out of memory to handle the upload. Trying again - * later may succeed. This response is provided with HTTP status code - * #MHD_HTTP_PAYLOAD_TOO_LARGE. - */ - TALER_EC_SYNC_OUT_OF_MEMORY_ON_CONTENT_LENGTH = 6010, - - /** - * The uploaded data does not match the Etag. This response is - * provided with HTTP status code #MHD_HTTP_BAD_REQUEST. - */ - TALER_EC_SYNC_INVALID_UPLOAD = 6011, - - /** - * We failed to check for existing upload data in the database. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_DATABASE_FETCH_ERROR = 6012, - - /** - * HTTP server was being shutdown while this operation was pending. - * This response is provided with HTTP status code - * #MHD_HTTP_SERVICE_UNAVAILABLE. - */ - TALER_EC_SYNC_SHUTDOWN = 6013, - - /** - * HTTP server experienced a timeout while awaiting promised payment. - * This response is provided with HTTP status code - * #MHD_HTTP_REQUEST_TIMEOUT. - */ - TALER_EC_SYNC_PAYMENT_TIMEOUT = 6014, - - /** - * Sync could not store order data in its own database. This response - * is provided with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_PAYMENT_CREATE_DB_ERROR = 6015, - - /** - * Sync could not store payment confirmation in its own database. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_PAYMENT_CONFIRM_DB_ERROR = 6016, - - /** - * Sync could not fetch information about possible existing orders - * from its own database. This response is provided with HTTP status - * code #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_PAYMENT_CHECK_ORDER_DB_ERROR = 6017, - - /** - * Sync could not setup the payment request with its own backend. This - * response is provided with HTTP status code - * #MHD_HTTP_INTERNAL_SERVER_ERROR. - */ - TALER_EC_SYNC_PAYMENT_CREATE_BACKEND_ERROR = 6018, - - /** - * The sync service failed find the backup to be updated in its - * database. This response is provided with HTTP status code - * #MHD_HTTP_NOT_FOUND. - */ - TALER_EC_SYNC_PREVIOUS_BACKUP_UNKNOWN = 6019, - - /** - * End of error code range. - */ - TALER_EC_END = 9999, - -}; - - -#endif diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h index f7fa71443..0597799b5 100644 --- a/src/include/taler_exchange_service.h +++ b/src/include/taler_exchange_service.h @@ -1,23 +1,26 @@ /* - This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + This file is part of TALER + Copyright (C) 2014-2024 Taler Systems SA - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU Affero General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. - You should have received a copy of the GNU Affero General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ /** * @file include/taler_exchange_service.h * @brief C interface of libtalerexchange, a C library to use exchange's HTTP API + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Sree Harsha Totakura <sreeharsha@totakura.in> * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef _TALER_EXCHANGE_SERVICE_H #define _TALER_EXCHANGE_SERVICE_H @@ -25,31 +28,17 @@ #include <jansson.h> #include "taler_util.h" #include "taler_error_codes.h" +#include "taler_kyclogic_lib.h" #include <gnunet/gnunet_curl_lib.h> -/* ********************* /keys *********************** */ - /** - * List of possible options to be passed to - * #TALER_EXCHANGE_connect(). + * Version of the Taler Exchange API, in hex. + * Thus 0.8.4-1 = 0x00080401. */ -enum TALER_EXCHANGE_Option -{ - /** - * Terminator (end of option list). - */ - TALER_EXCHANGE_OPTION_END = 0, - - /** - * 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 *********************** */ /** @@ -70,17 +59,17 @@ struct TALER_EXCHANGE_SigningPublicKey /** * Validity start time */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Validity expiration time (how long the exchange may use it). */ - struct GNUNET_TIME_Absolute valid_until; + struct GNUNET_TIME_Timestamp valid_until; /** * Validity expiration time for legal disputes. */ - struct GNUNET_TIME_Absolute valid_legal; + struct GNUNET_TIME_Timestamp valid_legal; }; @@ -97,7 +86,7 @@ struct TALER_EXCHANGE_DenomPublicKey /** * The hash of the public key. */ - struct GNUNET_HashCode h_key; + struct TALER_DenominationHashP h_key; /** * Exchange's master signature over this denomination record. @@ -107,18 +96,18 @@ struct TALER_EXCHANGE_DenomPublicKey /** * Timestamp indicating when the denomination key becomes valid */ - struct GNUNET_TIME_Absolute valid_from; + struct GNUNET_TIME_Timestamp valid_from; /** * Timestamp indicating when the denomination key can’t be used anymore to * withdraw new coins. */ - struct GNUNET_TIME_Absolute withdraw_valid_until; + struct GNUNET_TIME_Timestamp withdraw_valid_until; /** * Timestamp indicating when coins of this denomination become invalid. */ - struct GNUNET_TIME_Absolute expire_deposit; + struct GNUNET_TIME_Timestamp expire_deposit; /** * When do signatures with this denomination key become invalid? @@ -127,7 +116,7 @@ struct TALER_EXCHANGE_DenomPublicKey * of the evidence. @e expire_legal is expected to be significantly * larger than @e expire_deposit (by a year or more). */ - struct GNUNET_TIME_Absolute expire_legal; + struct GNUNET_TIME_Timestamp expire_legal; /** * The value of this denomination @@ -135,30 +124,23 @@ struct TALER_EXCHANGE_DenomPublicKey struct TALER_Amount value; /** - * The applicable fee for withdrawing a coin of this denomination - */ - struct TALER_Amount fee_withdraw; - - /** - * The applicable fee to spend a coin of this denomination - */ - struct TALER_Amount fee_deposit; - - /** - * The applicable fee to melt/refresh a coin of this denomination + * The applicable fees for this denomination */ - struct TALER_Amount fee_refresh; + struct TALER_DenomFeeSet fees; /** - * The applicable fee to refund a coin of this denomination + * Set to true if the private denomination key has been + * lost by the exchange and thus the key cannot be + * used for withdrawing at this time. */ - struct TALER_Amount fee_refund; + bool lost; /** - * Set to #GNUNET_YES if this denomination key has been + * Set to true if this denomination key has been * revoked by the exchange. */ - int revoked; + bool revoked; + }; @@ -219,6 +201,227 @@ struct TALER_EXCHANGE_AuditorInformation /** + * Global fees and options of an exchange for a given time period. + */ +struct TALER_EXCHANGE_GlobalFee +{ + + /** + * Signature affirming all of the data. + */ + struct TALER_MasterSignatureP master_sig; + + /** + * Starting time of the validity period (inclusive). + */ + struct GNUNET_TIME_Timestamp start_date; + + /** + * End time of the validity period (exclusive). + */ + struct GNUNET_TIME_Timestamp end_date; + + /** + * Unmerged purses will be timed out after at most this time. + */ + struct GNUNET_TIME_Relative purse_timeout; + + /** + * Account history is limited to this timeframe. + */ + struct GNUNET_TIME_Relative history_expiration; + + /** + * Fees that apply globally, independent of denomination + * and wire method. + */ + struct TALER_GlobalFeeSet fees; + + /** + * Number of free purses per account. + */ + uint32_t purse_account_limit; +}; + + +/** + * List sorted by @a start_date with fees to be paid for aggregate wire transfers. + */ +struct TALER_EXCHANGE_WireAggregateFees +{ + /** + * This is a linked list. + */ + struct TALER_EXCHANGE_WireAggregateFees *next; + + /** + * Fee to be paid whenever the exchange wires funds to the merchant. + */ + struct TALER_WireFeeSet fees; + + /** + * Time when this fee goes into effect (inclusive) + */ + struct GNUNET_TIME_Timestamp start_date; + + /** + * Time when this fee stops being in effect (exclusive). + */ + struct GNUNET_TIME_Timestamp end_date; + + /** + * Signature affirming the above fee structure. + */ + struct TALER_MasterSignatureP master_sig; +}; + + +/** + * Information about wire fees by wire method. + */ +struct TALER_EXCHANGE_WireFeesByMethod +{ + /** + * Wire method with the given @e fees. + */ + char *method; + + /** + * Linked list of wire fees the exchange charges for + * accounts of the wire @e method. + */ + struct TALER_EXCHANGE_WireAggregateFees *fees_head; + +}; + + +/** + * Type of an account restriction. + */ +enum TALER_EXCHANGE_AccountRestrictionType +{ + /** + * Invalid restriction. + */ + TALER_EXCHANGE_AR_INVALID = 0, + + /** + * Account must not be used for this operation. + */ + TALER_EXCHANGE_AR_DENY = 1, + + /** + * Other account must match given regular expression. + */ + TALER_EXCHANGE_AR_REGEX = 2 +}; + +/** + * Restrictions that apply to using a given exchange bank account. + */ +struct TALER_EXCHANGE_AccountRestriction +{ + + /** + * Type of the account restriction. + */ + enum TALER_EXCHANGE_AccountRestrictionType type; + + /** + * Restriction details depending on @e type. + */ + union + { + /** + * Details if type is #TALER_EXCHANGE_AR_REGEX. + */ + struct + { + /** + * Regular expression that the payto://-URI of the partner account must + * follow. The regular expression should follow posix-egrep, but + * without support for character classes, GNU extensions, + * back-references or intervals. See + * https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html + * for a description of the posix-egrep syntax. Applications may support + * regexes with additional features, but exchanges must not use such + * regexes. + */ + char *posix_egrep; + + /** + * Hint for a human to understand the restriction. + */ + char *human_hint; + + /** + * Internationalizations for the @e human_hint. Map from IETF BCP 47 + * language tax to localized human hints. + */ + json_t *human_hint_i18n; + } regex; + } details; + +}; + + +/** + * Information about a wire account of the exchange. + */ +struct TALER_EXCHANGE_WireAccount +{ + /** + * payto://-URI of the exchange. + */ + char *payto_uri; + + /** + * URL of a conversion service in case using this account is subject to + * currency conversion. NULL for no conversion needed. + */ + char *conversion_url; + + /** + * Array of restrictions that apply when crediting + * this account. + */ + struct TALER_EXCHANGE_AccountRestriction *credit_restrictions; + + /** + * Array of restrictions that apply when debiting + * this account. + */ + struct TALER_EXCHANGE_AccountRestriction *debit_restrictions; + + /** + * Length of the @e credit_restrictions array. + */ + unsigned int credit_restrictions_length; + + /** + * Length of the @e debit_restrictions array. + */ + unsigned int debit_restrictions_length; + + /** + * Signature of the exchange over the account (was checked by the API). + */ + struct TALER_MasterSignatureP master_sig; + + /** + * Display label for the account, can be NULL. + */ + char *bank_label; + + /** + * Priority for ordering the account in the display. + */ + int64_t priority; + +}; + + +/** * @brief Information about keys from the exchange. */ struct TALER_EXCHANGE_Keys @@ -230,6 +433,11 @@ struct TALER_EXCHANGE_Keys struct TALER_MasterPublicKeyP master_pub; /** + * Signature over extension configuration data, if any. + */ + struct TALER_MasterSignatureP extensions_sig; + + /** * Array of the exchange's online signing keys. */ struct TALER_EXCHANGE_SigningPublicKey *sign_keys; @@ -245,6 +453,16 @@ struct TALER_EXCHANGE_Keys struct TALER_EXCHANGE_AuditorInformation *auditors; /** + * Array with the global fees of the exchange. + */ + struct TALER_EXCHANGE_GlobalFee *global_fees; + + /** + * Configuration data for extensions. + */ + json_t *extensions; + + /** * Supported Taler protocol version by the exchange. * String in the format current:revision:age using the * semantics of GNU libtool. See @@ -253,6 +471,46 @@ struct TALER_EXCHANGE_Keys char *version; /** + * Supported currency of the exchange. + */ + char *currency; + + /** + * What is the base URL of the exchange that returned + * these keys? + */ + char *exchange_url; + + /** + * Asset type used by the exchange. Typical values + * are "fiat" or "crypto" or "regional" or "stock". + * Wallets should adjust their UI/UX based on this + * value. + */ + char *asset_type; + + /** + * Array of amounts a wallet is allowed to hold from + * this exchange before it must undergo further KYC checks. + */ + struct TALER_Amount *wallet_balance_limit_without_kyc; + + /** + * Array of accounts of the exchange. + */ + struct TALER_EXCHANGE_WireAccount *accounts; + + /** + * Array of wire fees by wire method. + */ + struct TALER_EXCHANGE_WireFeesByMethod *fees; + + /** + * Currency rendering specification for this exchange. + */ + struct TALER_CurrencySpecification cspec; + + /** * How long after a reserve went idle will the exchange close it? * This is an approximate number, not cryptographically signed by * the exchange (advisory-only, may change anytime). @@ -262,14 +520,60 @@ struct TALER_EXCHANGE_Keys /** * Timestamp indicating the /keys generation. */ - struct GNUNET_TIME_Absolute list_issue_date; + 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. */ - struct GNUNET_TIME_Absolute last_denom_issue_date; + struct GNUNET_TIME_Timestamp last_denom_issue_date; + + /** + * If age restriction is enabled on the exchange, we get an non-zero age_mask + */ + struct TALER_AgeMask age_mask; + + /** + * Absolute STEFAN parameter. + */ + struct TALER_Amount stefan_abs; + + /** + * Logarithmic STEFAN parameter. + */ + struct TALER_Amount stefan_log; + + /** + * Linear STEFAN parameter. + */ + double stefan_lin; + + /** + * Length of @e accounts array. + */ + unsigned int accounts_len; + + /** + * Length of @e fees array. + */ + unsigned int fees_len; + + /** + * Length of the @e wallet_balance_limit_without_kyc + * array. + */ + unsigned int wblwk_length; + + /** + * Length of the @e global_fees array. + */ + unsigned int num_global_fees; /** * Length of the @e sign_keys array (number of valid entries). @@ -296,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; }; @@ -392,141 +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 key the exchange is using. + * 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); /** - * Set the fake now to be used when requesting "/keys". + * Increment reference counter for @a keys * - * @param exchange exchange handle. - * @param now fake now to use. Note: this value will be - * used _until_ its use will be unset via @a TALER_EXCHANGE_unset_now() + * @param[in,out] keys object to increment reference counter for + * @return keys, with incremented reference counter */ -void -TALER_EXCHANGE_set_now (struct TALER_EXCHANGE_Handle *exchange, - struct GNUNET_TIME_Absolute now); +struct TALER_EXCHANGE_Keys * +TALER_EXCHANGE_keys_incref (struct TALER_EXCHANGE_Keys *keys); + /** - * Unset the fake now to be used when requesting "/keys". + * Decrement reference counter for @a keys. + * Frees @a keys if reference counter becomes zero. * - * @param exchange exchange handle. + * @param[in,out] keys object to decrement reference counter for */ void -TALER_EXCHANGE_unset_now (struct TALER_EXCHANGE_Handle *exchange); +TALER_EXCHANGE_keys_decref (struct TALER_EXCHANGE_Keys *keys); /** - * Let the user set the last valid denomination time manually. + * 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 exchange the exchange handle. - * @param last_denom_new new last denomination time. + * @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) */ -void -TALER_EXCHANGE_set_last_denom (struct TALER_EXCHANGE_Handle *exchange, - struct GNUNET_TIME_Absolute last_denom_new); +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 force_download #GNUNET_YES to force download even if /keys is still valid - * @param pull_all_keys if #GNUNET_YES, then the exchange state is reset to #MHS_INIT, - * and all denoms will be redownloaded. - * @return until when the response is current, 0 if we are re-downloading + * @param keys exchange key data + * @param net net amount (effective amount) + * @param[out] brut gross amount (actual cost including fees) + * @return #GNUNET_OK on success, #GNUNET_NO if the + * resulting @a brut is zero (only if @a net was zero) */ -struct GNUNET_TIME_Absolute -TALER_EXCHANGE_check_keys_current (struct TALER_EXCHANGE_Handle *exchange, - int force_download, - int pull_all_keys); +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); /** @@ -537,19 +905,10 @@ TALER_EXCHANGE_get_keys_raw (struct TALER_EXCHANGE_Handle *exchange); * @param pub claimed current online signing key for the exchange * @return #GNUNET_OK if @a pub is (according to /keys) a current signing key */ -int -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); +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_test_signing_key ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ExchangePublicKeyP *pub); /** @@ -567,10 +926,24 @@ TALER_EXCHANGE_get_denomination_key ( /** + * Obtain the global fee details from the exchange. + * + * @param keys the exchange's key set + * @param ts time for when to fetch the fees + * @return details about the fees, NULL if no fees are known at @a ts + */ +const struct TALER_EXCHANGE_GlobalFee * +TALER_EXCHANGE_get_global_fee ( + const struct TALER_EXCHANGE_Keys *keys, + struct GNUNET_TIME_Timestamp ts); + + +/** * Create a copy of a denomination public key. * * @param key key to copy - * @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key + * @returns a copy, must be freed with #TALER_EXCHANGE_destroy_denomination_key() + * @deprecated */ struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_copy_denomination_key ( @@ -579,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 ( @@ -598,7 +972,7 @@ TALER_EXCHANGE_destroy_denomination_key ( const struct TALER_EXCHANGE_DenomPublicKey * TALER_EXCHANGE_get_denomination_key_by_hash ( const struct TALER_EXCHANGE_Keys *keys, - const struct GNUNET_HashCode *hc); + const struct TALER_DenominationHashP *hc); /** @@ -615,139 +989,209 @@ TALER_EXCHANGE_get_signing_key_info ( const struct TALER_ExchangePublicKeyP *exchange_pub); -/* ********************* /wire *********************** */ +/* ********************* wire helpers *********************** */ /** - * Sorted list of fees to be paid for aggregate wire transfers. + * Parse array of @a accounts of the exchange into @a was. + * + * @param master_pub master public key of the exchange, NULL to not verify signatures + * @param accounts array of accounts to parse + * @param[out] was where to write the result (already allocated) + * @param was_length length of the @a was array, must match the length of @a accounts + * @return #GNUNET_OK if parsing @a accounts succeeded */ -struct TALER_EXCHANGE_WireAggregateFees +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_accounts ( + const struct TALER_MasterPublicKeyP *master_pub, + const json_t *accounts, + unsigned int was_length, + struct TALER_EXCHANGE_WireAccount was[static was_length]); + + +/** + * Free data within @a was, but not @a was itself. + * + * @param was array of wire account data + * @param was_len length of the @a was array + */ +void +TALER_EXCHANGE_free_accounts ( + unsigned int was_len, + struct TALER_EXCHANGE_WireAccount was[static was_len]); + + +/* ********************* /coins/$COIN_PUB/deposit *********************** */ + + +/** + * Information needed for a coin to be deposited. + */ +struct TALER_EXCHANGE_CoinDepositDetail { + /** - * This is a linked list. + * The amount to be deposited. */ - struct TALER_EXCHANGE_WireAggregateFees *next; + struct TALER_Amount amount; /** - * Fee to be paid whenever the exchange wires funds to the merchant. + * Hash over the age commitment of the coin. */ - struct TALER_Amount wire_fee; + struct TALER_AgeCommitmentHash h_age_commitment; /** - * Fee to be paid when the exchange closes a reserve and wires funds - * back to a customer. + * The coin’s public key. */ - struct TALER_Amount closing_fee; + struct TALER_CoinSpendPublicKeyP coin_pub; /** - * Time when this fee goes into effect (inclusive) + * The signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made + * by the customer with the coin’s private key. */ - struct GNUNET_TIME_Absolute start_date; + struct TALER_CoinSpendSignatureP coin_sig; /** - * Time when this fee stops being in effect (exclusive). + * Exchange’s unblinded signature of the coin. */ - struct GNUNET_TIME_Absolute end_date; + struct TALER_DenominationSignature denom_sig; /** - * Signature affirming the above fee structure. + * Hash of the public key of the coin. */ - struct TALER_MasterSignatureP master_sig; + struct TALER_DenominationHashP h_denom_pub; }; /** - * Information about a wire account of the exchange. + * Meta information about the contract relevant for a coin's deposit + * operation. */ -struct TALER_EXCHANGE_WireAccount +struct TALER_EXCHANGE_DepositContractDetail { + /** - * payto://-URI of the exchange. + * Hash of the contact of the merchant with the customer (further details + * are never disclosed to the exchange) */ - const char *payto_uri; + struct TALER_PrivateContractHashP h_contract_terms; /** - * Signature of the exchange over the account (was checked by the API). + * The public key of the merchant (used to identify the merchant for refund + * requests). */ - struct TALER_MasterSignatureP master_sig; + struct TALER_MerchantPublicKeyP merchant_pub; /** - * Linked list of wire fees the exchange charges for - * accounts of the wire method matching @e payto_uri. + * Salt used to hash the @e merchant_payto_uri. + */ + struct TALER_WireSaltP wire_salt; + + /** + * Hash over data provided by the wallet to customize the contract. + * All zero if not used. + */ + struct GNUNET_HashCode wallet_data_hash; + + /** + * Date until which the merchant can issue a refund to the customer via the + * exchange (can be zero if refunds are not allowed); must not be after the + * @e wire_deadline. + */ + struct GNUNET_TIME_Timestamp refund_deadline; + + /** + * Execution date, until which the merchant would like the exchange to + * settle the balance (advisory, the exchange cannot be forced to settle in + * the past or upon very short notice, but of course a well-behaved exchange + * will limit aggregation based on the advice received). + */ + struct GNUNET_TIME_Timestamp wire_deadline; + + /** + * Timestamp when the contract was finalized, must match approximately the + * current time of the exchange. + */ + struct GNUNET_TIME_Timestamp wallet_timestamp; + + /** + * The merchant’s account details, in the payto://-format supported by the + * exchange. */ - const struct TALER_EXCHANGE_WireAggregateFees *fees; + const char *merchant_payto_uri; + + /** + * Policy extension specific details about the deposit relevant to the exchange. + */ + const json_t *policy_details; }; /** - * Callbacks of this type are used to serve the result of submitting a - * wire format inquiry request to a exchange. - * - * If the request fails to generate a valid response from the - * exchange, @a http_status will also be zero. - * - * @param cls closure - * @param hr HTTP response data - * @param accounts_len length of the @a accounts array - * @param accounts list of wire accounts of the exchange, NULL on error + * @brief A Batch Deposit Handle */ -typedef void -(*TALER_EXCHANGE_WireCallback) ( - void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int accounts_len, - const struct TALER_EXCHANGE_WireAccount *accounts); +struct TALER_EXCHANGE_BatchDepositHandle; /** - * @brief A Wire format inquiry handle + * Structure with information about a batch deposit + * operation's result. */ -struct TALER_EXCHANGE_WireHandle; +struct TALER_EXCHANGE_BatchDepositResult +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + union + { -/** - * 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); + /** + * Information returned if the HTTP status is + * #MHD_HTTP_OK. + */ + struct + { + /** + * Time when the exchange generated the batch deposit confirmation + */ + struct GNUNET_TIME_Timestamp deposit_timestamp; + /** + * Deposit confirmation signature provided by the exchange + */ + const struct TALER_ExchangeSignatureP *exchange_sig; -/** - * Cancel a wire information request. This function cannot be used - * on a request handle if a response is already served for it. - * - * @param wh the wire information request handle - */ -void -TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh); + /** + * 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; -/* ********************* /coins/$COIN_PUB/deposit *********************** */ + } ok; + /** + * Information returned if the HTTP status is + * #MHD_HTTP_CONFLICT. + */ + struct + { + /** + * The coin that had a conflict. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; -/** - * @brief A Deposit Handle - */ -struct TALER_EXCHANGE_DepositHandle; + } conflict; + + } details; +}; /** @@ -755,86 +1199,73 @@ struct TALER_EXCHANGE_DepositHandle; * deposit permission request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param exchange_sig signature provided by the exchange - * @param exchange_pub exchange key used to sign @a obj, or NULL + * @param dr deposit response details */ typedef void -(*TALER_EXCHANGE_DepositResultCallback) ( +(*TALER_EXCHANGE_BatchDepositResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangeSignatureP *exchange_sig, - const struct TALER_ExchangePublicKeyP *exchange_pub); + const struct TALER_EXCHANGE_BatchDepositResult *dr); /** - * Submit a deposit permission to the exchange and get the exchange's - * response. This API is typically used by a merchant. Note that - * while we return the response verbatim to the caller for further - * processing, we do already verify that the response is well-formed - * (i.e. that signatures included in the response are all valid). If - * the exchange's reply is not well-formed, we return an HTTP status code - * of zero to @a cb. + * Submit a batch of deposit permissions to the exchange and get the + * exchange's response. This API is typically used by a merchant. Note that + * while we return the response verbatim to the caller for further processing, + * we do already verify that the response is well-formed (i.e. that signatures + * included in the response are all valid). If the exchange's reply is not + * well-formed, we return an HTTP status code of zero to @a cb. * - * We also verify that the @a coin_sig is valid for this deposit - * request, and that the @a ub_sig is a valid signature for @a + * We also verify that the @a cdds.coin_sig are valid for this deposit + * request, and that the @a cdds.ub_sig are a valid signatures for @a * coin_pub. Also, the @a exchange must be ready to operate (i.e. have * finished processing the /keys reply). If either check fails, we do * NOT initiate the transaction with the exchange and instead return NULL. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param amount the amount to be deposited - * @param wire_deadline execution date, until which the merchant would like the exchange to settle the balance (advisory, the exchange cannot be - * forced to settle in the past or upon very short notice, but of course a well-behaved exchange will limit aggregation based on the advice received) - * @param wire_details the merchant’s account details, in a format supported by the exchange - * @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the exchange) - * @param coin_pub coin’s public key - * @param denom_pub denomination key with which the coin is signed - * @param denom_sig exchange’s unblinded signature of the coin - * @param timestamp timestamp when the contract was finalized, must match approximately the current time of the exchange - * @param merchant_pub the public key of the merchant (used to identify the merchant for refund requests) - * @param refund_deadline date until which the merchant can issue a refund to the customer via the exchange (can be zero if refunds are not allowed); must not be after the @a wire_deadline - * @param coin_sig the signature made with purpose #TALER_SIGNATURE_WALLET_COIN_DEPOSIT made by the customer with the coin’s private key. + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param dcd details about the contract the deposit is for + * @param num_cdds length of the @a cdds array + * @param cdds array with details about the coins to be deposited * @param cb the callback to call when a reply for this request is available * @param cb_cls closure for the above callback + * @param[out] ec if NULL is returned, set to the error code explaining why the operation failed * @return a handle for this request; NULL if the inputs are invalid (i.e. * signatures fail to verify). In this case, the callback is not called. */ -struct TALER_EXCHANGE_DepositHandle * -TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - struct GNUNET_TIME_Absolute wire_deadline, - json_t *wire_details, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_DenominationPublicKey *denom_pub, - struct GNUNET_TIME_Absolute timestamp, - const struct TALER_MerchantPublicKeyP *merchant_pub, - struct GNUNET_TIME_Absolute refund_deadline, - const struct TALER_CoinSpendSignatureP *coin_sig, - TALER_EXCHANGE_DepositResultCallback cb, - void *cb_cls); +struct TALER_EXCHANGE_BatchDepositHandle * +TALER_EXCHANGE_batch_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DepositContractDetail *dcd, + unsigned int num_cdds, + const struct TALER_EXCHANGE_CoinDepositDetail cdds[static num_cdds], + TALER_EXCHANGE_BatchDepositResultCallback cb, + void *cb_cls, + enum TALER_ErrorCode *ec); /** * Change the chance that our deposit confirmation will be given to the * auditor to 100%. * - * @param deposit the deposit permission request handle + * @param[in,out] deposit the batch deposit permission request handle */ void -TALER_EXCHANGE_deposit_force_dc (struct TALER_EXCHANGE_DepositHandle *deposit); +TALER_EXCHANGE_batch_deposit_force_dc ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /** - * Cancel a deposit permission request. This function cannot be used + * Cancel a batch deposit permission request. This function cannot be used * on a request handle if a response is already served for it. * - * @param deposit the deposit permission request handle + * @param[in] deposit the deposit permission request handle */ void -TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit); +TALER_EXCHANGE_batch_deposit_cancel ( + struct TALER_EXCHANGE_BatchDepositHandle *deposit); /* ********************* /coins/$COIN_PUB/refund *********************** */ @@ -844,23 +1275,51 @@ TALER_EXCHANGE_deposit_cancel (struct TALER_EXCHANGE_DepositHandle *deposit); */ struct TALER_EXCHANGE_RefundHandle; +/** + * Response from the /refund API. + */ +struct TALER_EXCHANGE_RefundResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status code. + */ + union + { + /** + * Details on #MHD_HTTP_OK. + */ + struct + { + /** + * Exchange key used to sign. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * The actual signature + */ + struct TALER_ExchangeSignatureP exchange_sig; + } ok; + } details; +}; + /** * Callbacks of this type are used to serve the result of submitting a * refund request to an exchange. * * @param cls closure - * @param hr HTTP response data - * @param sign_key exchange key used to sign @a obj, or NULL - * @param signature the actual signature, or NULL on error + * @param rr refund response */ typedef void (*TALER_EXCHANGE_RefundCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, - const struct TALER_ExchangeSignatureP *signature); - + const struct TALER_EXCHANGE_RefundResponse *rr); /** * Submit a refund request to the exchange and get the exchange's response. @@ -874,11 +1333,12 @@ 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 - * @param refund_fee fee applicable to this coin for the refund * @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded * @param coin_pub coin’s public key of the coin from the original deposit operation * @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation); @@ -892,61 +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_Amount *refund_fee, - const struct GNUNET_HashCode *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); - - -/** - * Submit a refund request to the exchange and get the exchange's - * response. This API is 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. - * - * The @a exchange must be ready to operate (i.e. have - * finished processing the /keys reply). If this check fails, we do - * NOT initiate the transaction with the exchange and instead return NULL. - * - * FIXME: We can probably DEPRECATE this API and only use #TALER_EXCHANGE_refund()! - * - * @param exchange the exchange handle; the exchange must be ready to operate - * @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 - * @param refund_fee fee applicable to this coin for the refund - * @param h_contract_terms hash of the contact of the merchant with the customer that is being refunded - * @param coin_pub coin’s public key of the coin from the original deposit operation - * @param rtransaction_id transaction id for the transaction between merchant and customer (of refunding operation); - * this is needed as we may first do a partial refund and later a full refund. If both - * refunds are also over the same amount, we need the @a rtransaction_id to make the disjoint - * refund requests different (as requests are idempotent and otherwise the 2nd refund might not work). - * @param merchant_pub public key of the merchant - * @param merchant_sig signature affirming the refund from the merchant - * @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_RefundHandle * -TALER_EXCHANGE_refund2 (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_Amount *amount, - const struct TALER_Amount *refund_fee, - const struct GNUNET_HashCode *h_contract_terms, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - uint64_t rtransaction_id, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_MerchantSignatureP *merchant_sig, - 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); /** @@ -961,16 +1377,549 @@ void TALER_EXCHANGE_refund_cancel (struct TALER_EXCHANGE_RefundHandle *refund); -/* ********************* GET /reserves/$RESERVE_PUB *********************** */ +/* ********************* POST /csr-melt *********************** */ /** - * @brief A /reserves/ GET Handle + * @brief A /csr-melt Handle */ -struct TALER_EXCHANGE_ReservesGetHandle; +struct TALER_EXCHANGE_CsRMeltHandle; + + +/** + * Details about a response for a CS R request. + */ +struct TALER_EXCHANGE_CsRMeltResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Length of the @e alg_values array. + */ + unsigned int alg_values_len; + + /** + * Values contributed by the exchange for the + * respective coin's withdraw operation. + */ + const struct TALER_ExchangeWithdrawValues *alg_values; + } ok; + + /** + * Details if the status is #MHD_HTTP_GONE. + */ + struct + { + /* FIXME: returning full details is not implemented */ + } gone; + + } details; +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * CS R request to a exchange. + * + * @param cls closure + * @param csrr response details + */ +typedef void +(*TALER_EXCHANGE_CsRMeltCallback) ( + void *cls, + const struct TALER_EXCHANGE_CsRMeltResponse *csrr); + + +/** + * Information we pass per coin to a /csr-melt request. + */ +struct TALER_EXCHANGE_NonceKey +{ + /** + * Which denomination key is the /csr-melt request for? + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + + /** + * What is number to derive the client nonce for the + * fresh coin? + */ + uint32_t cnc_num; +}; + + +/** + * Get a set of CS R values using a /csr-melt request. + * + * @param ctx curl context + * @param url exchange base URL + * @param rms master key used for the derivation of the CS values + * @param nks_len length of the @a nks array + * @param nks array of denominations and nonces + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return handle for the operation on success, NULL on error, i.e. + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_CsRMeltHandle * +TALER_EXCHANGE_csr_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_RefreshMasterSecretP *rms, + unsigned int nks_len, + struct TALER_EXCHANGE_NonceKey nks[static nks_len], + TALER_EXCHANGE_CsRMeltCallback res_cb, + void *res_cb_cls); + + +/** + * + * Cancel a CS R melt request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param csrh the withdraw handle + */ +void +TALER_EXCHANGE_csr_melt_cancel (struct TALER_EXCHANGE_CsRMeltHandle *csrh); + + +/* ********************* POST /csr-withdraw *********************** */ + + +/** + * @brief A /csr-withdraw Handle + */ +struct TALER_EXCHANGE_CsRWithdrawHandle; + + +/** + * Details about a response for a CS R request. + */ +struct TALER_EXCHANGE_CsRWithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Values contributed by the exchange for the + * respective coin's withdraw operation. + */ + struct TALER_ExchangeWithdrawValues alg_values; + + } ok; + + /** + * Details if the status is #MHD_HTTP_GONE. + */ + struct + { + /* TODO: returning full details is not implemented */ + } gone; + + } details; +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * CS R withdraw request to a exchange. + * + * @param cls closure + * @param csrr response details + */ +typedef void +(*TALER_EXCHANGE_CsRWithdrawCallback) ( + void *cls, + const struct TALER_EXCHANGE_CsRWithdrawResponse *csrr); + + +/** + * Get a CS R using a /csr-withdraw request. + * + * @param curl_ctx The curl context to use for the requests + * @param exchange_url Base-URL to the excnange + * @param pk Which denomination key is the /csr request for + * @param nonce client nonce for the request + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for the above callback + * @return handle for the operation on success, NULL on error, i.e. + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_CsRWithdrawHandle * +TALER_EXCHANGE_csr_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + TALER_EXCHANGE_CsRWithdrawCallback res_cb, + void *res_cb_cls); + + +/** + * + * Cancel a CS R withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param csrh the withdraw handle + */ +void +TALER_EXCHANGE_csr_withdraw_cancel ( + struct TALER_EXCHANGE_CsRWithdrawHandle *csrh); + + +/* ********************* GET /coins/$COIN_PUB *********************** */ + +/** + * Ways how a coin's balance may change. + */ +enum TALER_EXCHANGE_CoinTransactionType +{ + + /** + * Reserved for uninitialized / none. + */ + TALER_EXCHANGE_CTT_NONE, + + /** + * Deposit into a contract. + */ + TALER_EXCHANGE_CTT_DEPOSIT, + + /** + * Spent on melt. + */ + TALER_EXCHANGE_CTT_MELT, + + /** + * Refunded by merchant. + */ + TALER_EXCHANGE_CTT_REFUND, + + /** + * Debited in recoup (to reserve) operation. + */ + TALER_EXCHANGE_CTT_RECOUP, + + /** + * Debited in recoup-and-refresh operation. + */ + TALER_EXCHANGE_CTT_RECOUP_REFRESH, + + /** + * Credited in recoup-refresh. + */ + TALER_EXCHANGE_CTT_OLD_COIN_RECOUP, + + /** + * Deposited into purse. + */ + TALER_EXCHANGE_CTT_PURSE_DEPOSIT, + + /** + * Refund from purse. + */ + TALER_EXCHANGE_CTT_PURSE_REFUND, + + /** + * Reserve open payment operation. + */ + TALER_EXCHANGE_CTT_RESERVE_OPEN_DEPOSIT + +}; + + +/** + * @brief Entry in the coin's transaction history. + */ +struct TALER_EXCHANGE_CoinHistoryEntry +{ + + /** + * Type of the transaction. + */ + enum TALER_EXCHANGE_CoinTransactionType type; + + /** + * Amount transferred (in or out). + */ + struct TALER_Amount amount; + + /** + * Details depending on @e type. + */ + union + { + + struct + { + struct TALER_MerchantWireHashP h_wire; + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_ExtensionPolicyHashP h_policy; + bool no_h_policy; + struct GNUNET_HashCode wallet_data_hash; + bool no_wallet_data_hash; + struct GNUNET_TIME_Timestamp wallet_timestamp; + struct TALER_MerchantPublicKeyP merchant_pub; + struct GNUNET_TIME_Timestamp refund_deadline; + struct TALER_CoinSpendSignatureP sig; + struct TALER_AgeCommitmentHash hac; + bool no_hac; + struct TALER_Amount deposit_fee; + } deposit; + + struct + { + struct TALER_CoinSpendSignatureP sig; + struct TALER_RefreshCommitmentP rc; + struct TALER_AgeCommitmentHash h_age_commitment; + bool no_hac; + struct TALER_Amount melt_fee; + } melt; + + struct + { + struct TALER_PrivateContractHashP h_contract_terms; + struct TALER_MerchantPublicKeyP merchant_pub; + struct TALER_MerchantSignatureP sig; + struct TALER_Amount refund_fee; + struct TALER_Amount sig_amount; + uint64_t rtransaction_id; + } refund; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp timestamp; + union GNUNET_CRYPTO_BlindingSecretP coin_bks; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } recoup; + + struct + { + struct TALER_CoinSpendPublicKeyP old_coin_pub; + union GNUNET_CRYPTO_BlindingSecretP coin_bks; + struct GNUNET_TIME_Timestamp timestamp; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } recoup_refresh; + + struct + { + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + struct TALER_CoinSpendPublicKeyP new_coin_pub; + struct GNUNET_TIME_Timestamp timestamp; + } old_coin_recoup; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_CoinSpendSignatureP coin_sig; + const char *exchange_base_url; + bool refunded; + struct TALER_AgeCommitmentHash phac; + } purse_deposit; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_Amount refund_fee; + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_ExchangeSignatureP exchange_sig; + } purse_refund; + + struct + { + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_CoinSpendSignatureP coin_sig; + } reserve_open_deposit; + + } details; + +}; /** + * @brief A /coins/$RID/history Handle + */ +struct TALER_EXCHANGE_CoinsHistoryHandle; + + +/** + * Parses and verifies a coin's transaction history as + * returned by the exchange. Note that in case of + * incremental histories, the client must first combine + * the incremental histories into one complete history. + * + * @param keys /keys data of the exchange + * @param dk denomination key of the coin + * @param history JSON array with the coin's history + * @param coin_pub public key of the coin + * @param[out] total_in set to total amount credited to the coin in @a history + * @param[out] total_out set to total amount debited to the coin in @a history + * @param rlen length of the @a rhistory array + * @param[out] rhistory array where to write the parsed @a history + * @return #GNUNET_OK if @a history is valid, + * #GNUNET_SYSERR if not + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_parse_coin_history ( + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *dk, + const json_t *history, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *total_in, + struct TALER_Amount *total_out, + unsigned int rlen, + struct TALER_EXCHANGE_CoinHistoryEntry rhistory[static rlen]); + + +/** + * Verify that @a coin_sig does NOT appear in the @a history of a coin's + * transactions and thus whatever transaction is authorized by @a coin_sig is + * a conflict with @a proof. + * + * @param history coin history to check + * @param coin_sig signature that must not be in @a history + * @return #GNUNET_OK if @a coin_sig is not in @a history + */ +enum GNUNET_GenericReturnValue +TALER_EXCHANGE_check_coin_signature_conflict ( + const json_t *history, + const struct TALER_CoinSpendSignatureP *coin_sig); + + +/** + * Response to a GET /coins/$COIN_PUB/history request. + */ +struct TALER_EXCHANGE_CoinHistory +{ + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Coin transaction history (possibly partial). + * Not yet validated, combine with other already + * known history data for this coin and then use + * #TALER_EXCHANGE_parse_coin_history() to validate + * the complete history and obtain it in binary + * format. + */ + const json_t *history; + + /** + * The hash of the coin denomination's public key + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Coin balance. + */ + struct TALER_Amount balance; + + } ok; + + } details; + +}; + + +/** + * Signature of functions called with the result of + * a coin transaction history request. + * + * @param cls closure + * @param ch transaction history for the coin + */ +typedef void +(*TALER_EXCHANGE_CoinsHistoryCallback)( + void *cls, + const struct TALER_EXCHANGE_CoinHistory *ch); + + +/** + * Parses and verifies a coin's transaction history as + * returned by the exchange. Note that a client may + * have to combine multiple partial coin histories + * into one coherent history before calling this function. + * + * @param ctx context for managing request + * @param url base URL of the exchange + * @param coin_priv private key of the coin + * @param start_off offset from which on to request history + * @param cb function to call with results + * @param cb_cls closure for @a cb + * @return #GNUNET_OK if @a history is valid, + * #GNUNET_SYSERR if not + */ +struct TALER_EXCHANGE_CoinsHistoryHandle * +TALER_EXCHANGE_coins_history ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + uint64_t start_off, + TALER_EXCHANGE_CoinsHistoryCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_coins_history() operation. + * + * @param[in] rsh operation to cancel + */ +void +TALER_EXCHANGE_coins_history_cancel ( + struct TALER_EXCHANGE_CoinsHistoryHandle *rsh); + + +/* ********************* GET /reserves/$RESERVE_PUB *********************** */ + +/** * Ways how a reserve's balance may change. */ enum TALER_EXCHANGE_ReserveTransactionType @@ -987,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, @@ -994,6 +1948,21 @@ enum TALER_EXCHANGE_ReserveTransactionType /** * Reserve closed operation. */ + TALER_EXCHANGE_RTT_CLOSING, + + /** + * Reserve purse merge operation. + */ + TALER_EXCHANGE_RTT_MERGE, + + /** + * Reserve open request operation. + */ + TALER_EXCHANGE_RTT_OPEN, + + /** + * Reserve close request operation. + */ TALER_EXCHANGE_RTT_CLOSE }; @@ -1002,7 +1971,7 @@ enum TALER_EXCHANGE_ReserveTransactionType /** * @brief Entry in the reserve's transaction history. */ -struct TALER_EXCHANGE_ReserveHistory +struct TALER_EXCHANGE_ReserveHistoryEntry { /** @@ -1035,17 +2004,12 @@ struct TALER_EXCHANGE_ReserveHistory /** * Information that uniquely identifies the wire transfer. */ - void *wire_reference; + uint64_t wire_reference; /** * When did the wire transfer happen? */ - struct GNUNET_TIME_Absolute timestamp; - - /** - * Number of bytes stored in @e wire_reference. - */ - size_t wire_reference_size; + struct GNUNET_TIME_Timestamp timestamp; } in_details; @@ -1067,6 +2031,28 @@ struct TALER_EXCHANGE_ReserveHistory } withdraw; /** + * Information about withdraw operation. + * @e type is #TALER_EXCHANGE_RTT_AGEWITHDRAWAL. + */ + struct + { + /** + * Signature authorizing the withdrawal for outgoing transaction. + */ + json_t *out_authorization_sig; + + /** + * Maximum age committed + */ + uint8_t max_age; + + /** + * Fee that was charged for the withdrawal. + */ + struct TALER_Amount fee; + } age_withdraw; + + /** * Information provided if the reserve was filled via /recoup. * @e type is #TALER_EXCHANGE_RTT_RECOUP. */ @@ -1092,7 +2078,7 @@ struct TALER_EXCHANGE_ReserveHistory /** * When did the /recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; } recoup_details; @@ -1103,7 +2089,7 @@ struct TALER_EXCHANGE_ReserveHistory struct { /** - * Receiver account information for the outgoing wire transfer. + * Receiver account information for the outgoing wire transfer as a payto://-URI. */ const char *receiver_account_details; @@ -1126,7 +2112,7 @@ struct TALER_EXCHANGE_ReserveHistory /** * When did the wire transfer happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * Fee that was charged for the closing. @@ -1135,6 +2121,173 @@ struct TALER_EXCHANGE_ReserveHistory } close_details; + /** + * Information about a merge operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_MERGE. + */ + struct + { + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * When was the purse set to expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * Minimum age required for depositing into the purse. + */ + uint32_t min_age; + + /** + * Flags of the purse. + */ + enum TALER_WalletAccountMergeFlags flags; + + /** + * True if the purse was actually merged, false + * if only the @e purse_fee was charged. + */ + bool merged; + + } merge_details; + + /** + * Information about an open request operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_OPEN. + */ + struct + { + + /** + * Signature by the reserve approving the open. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Amount to be paid from the reserve balance to open + * the reserve. + */ + struct TALER_Amount reserve_payment; + + /** + * When was the request created. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * For how long should the reserve be kept open. + * (Determines amount to be paid.) + */ + struct GNUNET_TIME_Timestamp reserve_expiration; + + /** + * How many open purses should be included with the + * open reserve? + * (Determines amount to be paid.) + */ + uint32_t purse_limit; + + } open_request; + + /** + * Information about an close request operation on the reserve. + * @e type is #TALER_EXCHANGE_RTT_CLOSE. + */ + struct + { + + /** + * Signature by the reserve approving the close. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the request created. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + + } close_request; + + + } details; + +}; + + +/** + * @brief A /reserves/ GET Handle + */ +struct TALER_EXCHANGE_ReservesGetHandle; + + +/** + * @brief Reserve summary. + */ +struct TALER_EXCHANGE_ReserveSummary +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Reserve balance. + */ + struct TALER_Amount balance; + + } ok; + } details; }; @@ -1145,18 +2298,12 @@ struct TALER_EXCHANGE_ReserveHistory * reserve status request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param balance current balance in the reserve, NULL on error - * @param history_length number of entries in the transaction history, 0 on error - * @param history detailed transaction history, NULL on error + * @param rs HTTP response data */ typedef void (*TALER_EXCHANGE_ReservesGetCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_Amount *balance, - unsigned int history_length, - const struct TALER_EXCHANGE_ReserveHistory *history); + const struct TALER_EXCHANGE_ReserveSummary *rs); /** @@ -1168,8 +2315,11 @@ 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) * @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. @@ -1177,8 +2327,10 @@ 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, void *cb_cls); @@ -1194,84 +2346,352 @@ TALER_EXCHANGE_reserves_get_cancel ( struct TALER_EXCHANGE_ReservesGetHandle *rgh); -/* ********************* POST /reserves/$RESERVE_PUB/withdraw *********************** */ +/** + * @brief A /reserves/$RID/history Handle + */ +struct TALER_EXCHANGE_ReservesHistoryHandle; + + +/** + * @brief Reserve history details. + */ +struct TALER_EXCHANGE_ReserveHistory +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_history. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_history is #MHD_HTTP_OK + */ + struct + { + + /** + * Current reserve balance. May not be the difference between + * @e total_in and @e total_out because the @e may be truncated. + */ + struct TALER_Amount balance; + + /** + * Total of all inbound transactions in @e history. + */ + struct TALER_Amount total_in; + + /** + * Total of all outbound transactions in @e history. + */ + struct TALER_Amount total_out; + + /** + * Current etag / last entry in the history. + * Useful to filter requests by starting offset. + * Offsets are not necessarily contiguous. + */ + uint64_t etag; + + /** + * Reserve history. + */ + const struct TALER_EXCHANGE_ReserveHistoryEntry *history; + + /** + * Length of the @e history array. + */ + unsigned int history_len; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve history request to a exchange. + * + * @param cls closure + * @param rs HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesHistoryCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveHistory *rs); /** - * @brief A /reserves/$RESERVE_PUB/withdraw Handle + * Submit a request to obtain the reserve history. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve to inspect + * @param start_off offset of the oldest history entry to exclude from the response + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. */ -struct TALER_EXCHANGE_WithdrawHandle; +struct TALER_EXCHANGE_ReservesHistoryHandle * +TALER_EXCHANGE_reserves_history ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + uint64_t start_off, + TALER_EXCHANGE_ReservesHistoryCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve history request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rsh the reserve request handle + */ +void +TALER_EXCHANGE_reserves_history_cancel ( + struct TALER_EXCHANGE_ReservesHistoryHandle *rsh); + + +/** + * Information input into the withdraw process per coin. + */ +struct TALER_EXCHANGE_WithdrawCoinInput +{ + /** + * Denomination of the coin. + */ + const struct TALER_EXCHANGE_DenomPublicKey *pk; + + /** + * Master key material for the coin. + */ + const struct TALER_PlanchetMasterSecretP *ps; + + /** + * Age commitment for the coin. + */ + const struct TALER_AgeCommitmentHash *ach; + +}; + + +/** + * All the details about a coin that are generated during withdrawal and that + * may be needed for future operations on the coin. + */ +struct TALER_EXCHANGE_PrivateCoinDetails +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Value used to blind the key for the signature. + * Needed for recoup operations. + */ + union GNUNET_CRYPTO_BlindingSecretP bks; + + /** + * Signature over the coin. + */ + struct TALER_DenominationSignature sig; + + /** + * Values contributed from the exchange during the + * withdraw protocol. + */ + struct TALER_ExchangeWithdrawValues exchange_vals; +}; + + +/** + * @brief A /reserves/$RESERVE_PUB/batch-withdraw Handle + */ +struct TALER_EXCHANGE_BatchWithdrawHandle; + + +/** + * Details about a response for a batch withdraw request. + */ +struct TALER_EXCHANGE_BatchWithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + + /** + * Array of coins returned by the batch withdraw operation. + */ + struct TALER_EXCHANGE_PrivateCoinDetails *coins; + + /** + * Length of the @e coins array. + */ + unsigned int num_coins; + } ok; + + /** + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + /** + * Legitimization requirement that the merchant should use + * to check for its KYC status, 0 if not known. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; + + /** + * Details if the status is #MHD_HTTP_CONFLICT. + */ + 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. + * batch withdraw request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param sig signature over the coin, NULL on error + * @param wr response details */ typedef void -(*TALER_EXCHANGE_WithdrawCallback) ( +(*TALER_EXCHANGE_BatchWithdrawCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_DenominationSignature *sig); + const struct TALER_EXCHANGE_BatchWithdrawResponse *wr); /** - * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/withdraw - * request. This API is typically used by a wallet to withdraw from a - * reserve. + * Withdraw multiple coins from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a wallet to withdraw many coins from a + * reserve. The blind signatures are unblinded and verified before being returned + * to the caller at @a res_cb. * * Note that to ensure that no money is lost in case of hardware * failures, the caller must have committed (most of) the arguments to * disk before calling, and be ready to repeat the request with the * same arguments in case of failures. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param pk kind of coin to create + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange * @param reserve_priv private key of the reserve to withdraw from - * @param ps secrets of the planchet - * caller must have committed this value to disk before the call (with @a pk) + * @param wci_length number of entries in @a wcis + * @param wcis inputs that determine the planchets * @param res_cb the callback to call when the final result for this request is available * @param res_cb_cls closure for @a res_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). * In this case, the callback is not called. */ -struct TALER_EXCHANGE_WithdrawHandle * -TALER_EXCHANGE_withdraw ( - struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, +struct TALER_EXCHANGE_BatchWithdrawHandle * +TALER_EXCHANGE_batch_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, const struct TALER_ReservePrivateKeyP *reserve_priv, - const struct TALER_PlanchetSecretsP *ps, - TALER_EXCHANGE_WithdrawCallback res_cb, + unsigned int wci_length, + const struct TALER_EXCHANGE_WithdrawCoinInput wcis[static wci_length], + TALER_EXCHANGE_BatchWithdrawCallback res_cb, void *res_cb_cls); /** - * Cancel a withdraw status request. This function cannot be used - * on a request handle if a response is already served for it. + * Cancel a batch withdraw status request. This function cannot be used on a + * request handle if a response is already served for it. * - * @param wh the withdraw handle + * @param wh the batch withdraw handle */ void -TALER_EXCHANGE_withdraw_cancel (struct TALER_EXCHANGE_WithdrawHandle *wh); +TALER_EXCHANGE_batch_withdraw_cancel ( + struct TALER_EXCHANGE_BatchWithdrawHandle *wh); /** + * Response from a withdraw2 request. + */ +struct TALER_EXCHANGE_Withdraw2Response +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * blind signature over the coin + */ + struct TALER_BlindedDenominationSignature blind_sig; + } ok; + } details; + +}; + +/** * Callbacks of this type are used to serve the result of submitting a * withdraw request to a exchange without the (un)blinding factor. * * @param cls closure - * @param hr HTTP response data - * @param blind_sig blind signature over the coin, NULL on error + * @param w2r response data */ typedef void (*TALER_EXCHANGE_Withdraw2Callback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct GNUNET_CRYPTO_RsaSignature *blind_sig); + const struct TALER_EXCHANGE_Withdraw2Response *w2r); /** @@ -1287,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 @@ -1304,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); /** @@ -1321,56 +2750,592 @@ void TALER_EXCHANGE_withdraw2_cancel (struct TALER_EXCHANGE_Withdraw2Handle *wh); -/* ********************* /refresh/melt+reveal ***************************** */ +/** + * Response from a batch-withdraw request (2nd variant). + */ +struct TALER_EXCHANGE_BatchWithdraw2Response +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * array of blind signatures over the coins. + */ + const struct TALER_BlindedDenominationSignature *blind_sigs; + + /** + * length of @e blind_sigs + */ + unsigned int blind_sigs_length; + + } ok; + + struct + { + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + /** + * ID identifying the KYC requirement to withdraw. + */ + uint64_t kyc_requirement_id; + + } unavailable_for_legal_reasons; + + } details; + +}; /** - * Melt (partially spent) coins to obtain fresh coins that are - * unlinkable to the original coin(s). Note that melting more - * than one coin in a single request will make those coins linkable, - * so the safest operation only melts one coin at a time. + * Callbacks of this type are used to serve the result of submitting a batch + * withdraw request to a exchange without the (un)blinding factor. + * + * @param cls closure + * @param bw2r response data + */ +typedef void +(*TALER_EXCHANGE_BatchWithdraw2Callback) ( + void *cls, + const struct TALER_EXCHANGE_BatchWithdraw2Response *bw2r); + + +/** + * @brief A /reserves/$RESERVE_PUB/batch-withdraw Handle, 2nd variant. + * This variant does not do the blinding/unblinding and only + * fetches the blind signatures on the already blinded planchets. + * Used internally by the `struct TALER_EXCHANGE_BatchWithdrawHandle` + * implementation as well as for the tipping logic of merchants. + */ +struct TALER_EXCHANGE_BatchWithdraw2Handle; + + +/** + * Withdraw a coin from the exchange using a /reserves/$RESERVE_PUB/batch-withdraw + * request. This API is typically used by a merchant to withdraw a tip + * where the blinding factor is unknown to the merchant. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param pds array of planchet details of the planchet to withdraw + * @param pds_length number of entries in the @a pds array + * @param reserve_priv private key of the reserve to withdraw from + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_BatchWithdraw2Handle * +TALER_EXCHANGE_batch_withdraw2 ( + struct GNUNET_CURL_Context *curl_ctx, + const char *exchange_url, + const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int pds_length, + const struct TALER_PlanchetDetail pds[static pds_length], + TALER_EXCHANGE_BatchWithdraw2Callback res_cb, + void *res_cb_cls); + + +/** + * Cancel a batch withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param wh the withdraw handle + */ +void +TALER_EXCHANGE_batch_withdraw2_cancel ( + struct TALER_EXCHANGE_BatchWithdraw2Handle *wh); + + +/* ********************* /reserve/$RESERVE_PUB/age-withdraw *************** */ + +/** + * @brief Information needed to withdraw (and reveal) age restricted coins. + */ +struct TALER_EXCHANGE_AgeWithdrawCoinInput +{ + /** + * The master secret from which we derive all other relevant values for + * the coin: private key, nonces (if applicable) and age restriction + */ + struct TALER_PlanchetMasterSecretP secrets[TALER_CNC_KAPPA]; + + /** + * The denomination of the coin. Must support age restriction, i.e + * its .keys.age_mask MUST not be 0 + */ + struct TALER_EXCHANGE_DenomPublicKey *denom_pub; +}; + + +/** + * All the details about a coin that are generated during age-withdrawal and + * that may be needed for future operations on the coin. + */ +struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Hash of the public key of the coin. + */ + struct TALER_CoinPubHashP h_coin_pub; + + /** + * Value used to blind the key for the signature. + * Needed for recoup operations. + */ + union GNUNET_CRYPTO_BlindingSecretP blinding_key; + + /** + * The age commitment, proof for the coin, derived from the + * Master secret and maximum age in the originating request + */ + struct TALER_AgeCommitmentProof age_commitment_proof; + + /** + * The hash of the age commitment + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Values contributed from the exchange during the + * withdraw protocol. + */ + struct TALER_ExchangeWithdrawValues alg_values; + + /** + * The planchet constructed + */ + struct TALER_PlanchetDetail planchet; +}; + +/** + * @brief A handle to a /reserves/$RESERVE_PUB/age-withdraw request + */ +struct TALER_EXCHANGE_AgeWithdrawHandle; + +/** + * @brief Details about the response for a age withdraw request. + */ +struct TALER_EXCHANGE_AgeWithdrawResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response + */ + union + { + /** + * Details if the status is #MHD_HTTP_OK. + */ + struct + { + /** + * Index that should not be revealed during the age-withdraw reveal + * phase. + */ + uint8_t noreveal_index; + + /** + * The commitment of the age-withdraw request, needed for the + * subsequent call to /age-withdraw/$ACH/reveal + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * The number of elements in @e coins, each referring to + * TALER_CNC_KAPPA elements + */ + size_t num_coins; + + /** + * The computed details of the non-revealed @e num_coins coins to keep. + */ + const struct TALER_EXCHANGE_AgeWithdrawCoinPrivateDetails *coin_details; + + /** + * The array of blinded hashes of the non-revealed + * @e num_coins coins, needed for the reveal step; + */ + const struct TALER_BlindedCoinHashP *blinded_coin_hs; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + } ok; + } details; +}; + + +typedef void +(*TALER_EXCHANGE_AgeWithdrawCallback)( + void *cls, + const struct TALER_EXCHANGE_AgeWithdrawResponse *awr); + +/** + * Submit an age-withdraw request to the exchange and get the exchange's + * response. * * This API is typically used by a wallet. Note that to ensure that - * no money is lost in case of hardware failures, is operation does - * not actually initiate the request. Instead, it generates a buffer - * which the caller must store before proceeding with the actual call - * to #TALER_EXCHANGE_melt() that will generate the request. - * - * This function does verify that the given request data is internally - * consistent. However, the @a melts_sigs are NOT verified. - * - * Aside from some non-trivial cryptographic operations that might - * take a bit of CPU time to complete, this function returns - * its result immediately and does not start any asynchronous - * processing. This function is also thread-safe. - * - * @param melt_priv private keys of the coin to melt - * @param melt_amount amount specifying how much - * the coin will contribute to the melt (including fee) - * @param melt_sig signatures affirming the - * validity of the public keys corresponding to the - * @a melt_priv private key - * @param melt_pk denomination key information - * record corresponding to the @a melt_sig - * validity of the keys - * @param fresh_pks_len length of the @a pks array - * @param fresh_pks array of @a pks_len denominations of fresh coins to create - * @param[out] res_size set to the size of the return value, or 0 on error + * no money is lost in case of hardware failures, the provided + * argument @a rd should be committed to persistent storage + * prior to calling this function. + * + * @param curl_ctx The curl context + * @param exchange_url The base url of the exchange + * @param keys The denomination keys from the exchange + * @param reserve_priv The private key to the reserve + * @param num_coins The number of elements in @e coin_inputs + * @param coin_inputs The input for the coins to withdraw + * @param max_age The maximum age we commit to. + * @param res_cb A callback for the result, maybe NULL + * @param res_cb_cls A closure for @e res_cb, maybe NULL + * @return a handle for this request; NULL if the argument was invalid. + * In this case, the callback will not be called. + */ +struct TALER_EXCHANGE_AgeWithdrawHandle * +TALER_EXCHANGE_age_withdraw ( + struct GNUNET_CURL_Context *curl_ctx, + struct TALER_EXCHANGE_Keys *keys, + const char *exchange_url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + size_t num_coins, + const struct TALER_EXCHANGE_AgeWithdrawCoinInput coin_inputs[static + num_coins], + uint8_t max_age, + TALER_EXCHANGE_AgeWithdrawCallback res_cb, + void *res_cb_cls); + +/** + * Cancel a age-withdraw request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param awh the age-withdraw handle + */ +void +TALER_EXCHANGE_age_withdraw_cancel ( + struct TALER_EXCHANGE_AgeWithdrawHandle *awh); + + +/**++++++ age-withdraw with pre-blinded planchets ***************************/ + +/** + * @brief Information needed to withdraw (and reveal) age restricted coins. + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedInput +{ + /** + * The denomination of the coin. Must support age restriction, i.e + * its .keys.age_mask MUST not be 0 + */ + const struct TALER_EXCHANGE_DenomPublicKey *denom_pub; + + /** + * Blinded Planchets + */ + struct TALER_PlanchetDetail planchet_details[TALER_CNC_KAPPA]; +}; + +/** + * Response from an age-withdraw request with pre-blinded planchets + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * Index that should not be revealed during the age-withdraw reveal phase. + * The struct TALER_PlanchetMasterSecretP * from the request + * with this index are the ones to keep. + */ + uint8_t noreveal_index; + + /** + * The commitment of the call to age-withdraw, needed for the subsequent + * call to /age-withdraw/$ACH/reveal. + */ + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + } ok; + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting an + * age-withdraw request to a exchange with pre-blinded planchets + * without the (un)blinding factor. + * + * @param cls closure + * @param awbr response data + */ +typedef void +(*TALER_EXCHANGE_AgeWithdrawBlindedCallback) ( + void *cls, + const struct TALER_EXCHANGE_AgeWithdrawBlindedResponse *awbr); + + +/** + * @brief A /reserves/$RESERVE_PUB/age-withdraw Handle, 2nd variant with + * pre-blinded planchets. + * + * This variant does not do the blinding/unblinding and only + * fetches the blind signatures on the already blinded planchets. + * Used internally by the `struct TALER_EXCHANGE_BatchWithdrawHandle` + * implementation as well as for the reward logic of merchants. + */ +struct TALER_EXCHANGE_AgeWithdrawBlindedHandle; + +/** + * Withdraw age-restricted coins from the exchange using a + * /reserves/$RESERVE_PUB/age-withdraw request. This API is typically used + * by a merchant to withdraw a reward where the planchets are pre-blinded and + * the blinding factor is unknown to the merchant. + * + * Note that to ensure that no money is lost in case of hardware + * failures, the caller must have committed (most of) the arguments to + * disk before calling, and be ready to repeat the request with the + * same arguments in case of failures. + * + * @param curl_ctx The curl context to use + * @param exchange_url The base-URL of the exchange + * @param keys The /keys material from the exchange + * @param max_age The maximum age that the coins are committed to. + * @param num_input number of entries in the @a blinded_input array + * @param blinded_input array of planchet details of the planchet to withdraw + * @param reserve_priv private key of the reserve to withdraw from + * @param res_cb the callback to call when the final result for this request is available + * @param res_cb_cls closure for @a res_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). - * Otherwise, pointer to a buffer of @a res_size to store persistently - * before proceeding to #TALER_EXCHANGE_melt(). - * Non-null results should be freed using GNUNET_free(). + * In this case, the callback is not called. + */ +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. */ -char * -TALER_EXCHANGE_refresh_prepare ( - const struct TALER_CoinSpendPrivateKeyP *melt_priv, - const struct TALER_Amount *melt_amount, - const struct TALER_DenominationSignature *melt_sig, - const struct TALER_EXCHANGE_DenomPublicKey *melt_pk, - unsigned int fresh_pks_len, - const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks, - size_t *res_size); +struct TALER_EXCHANGE_RefreshData +{ + /** + * private key of the coin to melt + */ + struct TALER_CoinSpendPrivateKeyP melt_priv; + + /** + * age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentProof *melt_age_commitment_proof; + + /** + * Hash of age commitment and proof that went into the original coin, + * might be NULL. + */ + const struct TALER_AgeCommitmentHash *melt_h_age_commitment; + + /** + * amount specifying how much the coin will contribute to the melt + * (including fee) + */ + struct TALER_Amount melt_amount; + + /** + * signatures affirming the validity of the public keys corresponding to the + * @e melt_priv private key + */ + struct TALER_DenominationSignature melt_sig; + + /** + * denomination key information record corresponding to the @e melt_sig + * validity of the keys + */ + struct TALER_EXCHANGE_DenomPublicKey melt_pk; + + /** + * array of @e pks_len denominations of fresh coins to create + */ + const struct TALER_EXCHANGE_DenomPublicKey *fresh_pks; + + /** + * length of the @e pks array + */ + unsigned int fresh_pks_len; +}; /* ********************* /coins/$COIN_PUB/melt ***************************** */ @@ -1382,23 +3347,79 @@ struct TALER_EXCHANGE_MeltHandle; /** + * Information we obtain per coin during melting. + */ +struct TALER_EXCHANGE_MeltBlindingDetail +{ + /** + * Exchange values contributed to the refresh operation + */ + struct TALER_ExchangeWithdrawValues alg_value; + +}; + + +/** + * Response returned to a /melt request. + */ +struct TALER_EXCHANGE_MeltResponse +{ + /** + * Full HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + + /** + * Information returned per coin. + */ + const struct TALER_EXCHANGE_MeltBlindingDetail *mbds; + + /** + * Key used by the exchange to sign the response. + */ + struct TALER_ExchangePublicKeyP sign_key; + + /** + * Length of the @a mbds array with the exchange values + * and blinding keys we are using. + */ + unsigned int num_mbds; + + /** + * Gamma value chosen by the exchange. + */ + uint32_t noreveal_index; + } ok; + + } details; +}; + + +/** * Callbacks of this type are used to notify the application about the result * of the /coins/$COIN_PUB/melt stage. If successful, the @a noreveal_index * should be committed to disk prior to proceeding * #TALER_EXCHANGE_refreshes_reveal(). * * @param cls closure - * @param hr HTTP response data - * @param noreveal_index choice by the exchange in the cut-and-choose protocol, - * UINT32_MAX on error - * @param sign_key exchange key used to sign @a full_response, or NULL + * @param mr response details */ typedef void (*TALER_EXCHANGE_MeltCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - uint32_t noreveal_index, - const struct TALER_ExchangePublicKeyP *sign_key); + const struct TALER_EXCHANGE_MeltResponse *mr); /** @@ -1407,26 +3428,28 @@ typedef void * * This API is typically used by a wallet. Note that to ensure that * no money is lost in case of hardware failures, the provided - * argument should have been constructed using - * #TALER_EXCHANGE_refresh_prepare and committed to persistent storage + * argument @a rd should be committed to persistent storage * prior to calling this function. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param refresh_data_length size of the @a refresh_data (returned - * in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare()) - * @param refresh_data the refresh data as returned from - #TALER_EXCHANGE_refresh_prepare()) + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param rms the fresh secret that defines the refresh operation + * @param rd the refresh data specifying the characteristics of the operation * @param melt_cb the callback to call with the result * @param melt_cb_cls closure for @a melt_cb * @return a handle for this request; NULL if the argument was invalid. * In this case, neither callback will be called. */ struct TALER_EXCHANGE_MeltHandle * -TALER_EXCHANGE_melt (struct TALER_EXCHANGE_Handle *exchange, - size_t refresh_data_length, - const char *refresh_data, - TALER_EXCHANGE_MeltCallback melt_cb, - void *melt_cb_cls); +TALER_EXCHANGE_melt ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_EXCHANGE_RefreshData *rd, + TALER_EXCHANGE_MeltCallback melt_cb, + void *melt_cb_cls); /** @@ -1443,26 +3466,92 @@ TALER_EXCHANGE_melt_cancel (struct TALER_EXCHANGE_MeltHandle *mh); /** + * Information about a coin obtained via /refreshes/$RCH/reveal. + */ +struct TALER_EXCHANGE_RevealedCoinInfo +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Master secret of this coin. + */ + struct TALER_PlanchetMasterSecretP ps; + + /** + * Age commitment and its hash of the coin, might be NULL. + */ + struct TALER_AgeCommitmentProof *age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Blinding keys used to blind the fresh coin. + */ + union GNUNET_CRYPTO_BlindingSecretP bks; + + /** + * Signature affirming the validity of the coin. + */ + struct TALER_DenominationSignature sig; + +}; + + +/** + * Result of a /refreshes/$RCH/reveal request. + */ +struct TALER_EXCHANGE_RevealResult +{ + /** + * HTTP status. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + /** + * Array of @e num_coins values about the coins obtained via the refresh + * operation. The array give the coins in the same order (and should + * have the same length) in which the original melt request specified the + * respective denomination keys. + */ + const struct TALER_EXCHANGE_RevealedCoinInfo *coins; + + /** + * Number of coins returned. + */ + unsigned int num_coins; + } ok; + + } details; + +}; + + +/** * Callbacks of this type are used to return the final result of * submitting a refresh request to a exchange. If the operation was * successful, this function returns the signatures over the coins - * that were remelted. The @a coin_privs and @a sigs arrays give the - * coins in the same order (and should have the same length) in which - * the original request specified the respective denomination keys. + * that were remelted. * * @param cls closure - * @param hr HTTP response data - * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed - * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error - * @param sigs array of signature over @a num_coins coins, NULL on error + * @param rr result of the reveal operation */ typedef void (*TALER_EXCHANGE_RefreshesRevealCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_PlanchetSecretsP *coin_privs, - const struct TALER_DenominationSignature *sigs); + const struct TALER_EXCHANGE_RevealResult *rr); /** @@ -1480,11 +3569,12 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; * arguments should have been committed to persistent storage * prior to calling this function. * - * @param exchange the exchange handle; the exchange must be ready to operate - * @param refresh_data_length size of the @a refresh_data (returned - * in the `res_size` argument from #TALER_EXCHANGE_refresh_prepare()) - * @param refresh_data the refresh data as returned from - #TALER_EXCHANGE_refresh_prepare()) + * @param ctx curl context + * @param url exchange base URL + * @param rms the fresh secret that defines the refresh operation + * @param rd the refresh data that characterizes the refresh operation + * @param num_coins number of fresh coins to be created, length of the @a exchange_vals array, must match value in @a rd + * @param alg_values array @a num_coins of exchange values contributed to the refresh operation * @param noreveal_index response from the exchange to the * #TALER_EXCHANGE_melt() invocation * @param reveal_cb the callback to call with the final result of the @@ -1495,9 +3585,12 @@ struct TALER_EXCHANGE_RefreshesRevealHandle; */ struct TALER_EXCHANGE_RefreshesRevealHandle * TALER_EXCHANGE_refreshes_reveal ( - struct TALER_EXCHANGE_Handle *exchange, - size_t refresh_data_length, - const char *refresh_data, + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_EXCHANGE_RefreshData *rd, + unsigned int num_coins, + const struct TALER_ExchangeWithdrawValues alg_values[static num_coins], uint32_t noreveal_index, TALER_EXCHANGE_RefreshesRevealCallback reveal_cb, void *reveal_cb_cls); @@ -1524,26 +3617,90 @@ struct TALER_EXCHANGE_LinkHandle; /** + * Information about a coin obtained via /link. + */ +struct TALER_EXCHANGE_LinkedCoinInfo +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Age commitment and its hash, if applicable. + */ + bool has_age_commitment; + struct TALER_AgeCommitmentProof age_commitment_proof; + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Master secret of this coin. + */ + struct TALER_PlanchetMasterSecretP ps; + + /** + * Signature affirming the validity of the coin. + */ + struct TALER_DenominationSignature sig; + + /** + * Denomination public key of the coin. + */ + struct TALER_DenominationPublicKey pub; +}; + + +/** + * Result of a /link request. + */ +struct TALER_EXCHANGE_LinkResult +{ + /** + * HTTP status. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Parsed response details, variant depending on the + * @e hr.http_status. + */ + union + { + /** + * Results for status #MHD_HTTP_OK. + */ + struct + { + /** + * Array of @e num_coins values about the + * coins obtained via linkage. + */ + const struct TALER_EXCHANGE_LinkedCoinInfo *coins; + + /** + * Number of coins returned. + */ + unsigned int num_coins; + } ok; + + } details; + +}; + + +/** * Callbacks of this type are used to return the final result of submitting a * /coins/$COIN_PUB/link request to a exchange. If the operation was * successful, this function returns the signatures over the coins that were * created when the original coin was melted. * * @param cls closure - * @param hr HTTP response data - * @param num_coins number of fresh coins created, length of the @a sigs and @a coin_privs arrays, 0 if the operation failed - * @param coin_privs array of @a num_coins private keys for the coins that were created, NULL on error - * @param sigs array of signature over @a num_coins coins, NULL on error - * @param pubs array of public keys for the @a sigs, NULL on error + * @param lr result of the /link operation */ typedef void (*TALER_EXCHANGE_LinkCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - unsigned int num_coins, - const struct TALER_CoinSpendPrivateKeyP *coin_privs, - const struct TALER_DenominationSignature *sigs, - const struct TALER_DenominationPublicKey *pubs); + const struct TALER_EXCHANGE_LinkResult *lr); /** @@ -1552,18 +3709,23 @@ typedef void * This API is typically not used by anyone, it is more a threat against those * trying to receive a funds transfer by abusing the refresh protocol. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx CURL context + * @param url exchange base URL * @param coin_priv private key to request link data for + * @param age_commitment_proof age commitment to the corresponding coin, might be NULL * @param link_cb the callback to call with the useful result of the * refresh operation the @a coin_priv was involved in (if any) * @param link_cb_cls closure for @a link_cb * @return a handle for this request */ struct TALER_EXCHANGE_LinkHandle * -TALER_EXCHANGE_link (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - TALER_EXCHANGE_LinkCallback link_cb, - void *link_cb_cls); +TALER_EXCHANGE_link ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_AgeCommitmentProof *age_commitment_proof, + TALER_EXCHANGE_LinkCallback link_cb, + void *link_cb_cls); /** @@ -1585,38 +3747,101 @@ struct TALER_EXCHANGE_TransfersGetHandle; /** + * Information the exchange returns per wire transfer. + */ +struct TALER_EXCHANGE_TransferData +{ + + /** + * exchange key used to sign + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * exchange signature over the transfer data + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * hash of the payto:// URI the transfer went to + */ + struct TALER_PaytoHashP h_payto; + + /** + * time when the exchange claims to have performed the wire transfer + */ + struct GNUNET_TIME_Timestamp execution_time; + + /** + * Actual amount of the wire transfer, excluding the wire fee. + */ + struct TALER_Amount total_amount; + + /** + * wire fee that was charged by the exchange + */ + struct TALER_Amount wire_fee; + + /** + * length of the @e details array + */ + unsigned int details_length; + + /** + * array with details about the combined transactions + */ + const struct TALER_TrackTransferDetails *details; + +}; + + +/** + * 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 sign_key exchange key used to sign @a json, or NULL - * @param h_wire hash of the wire transfer address the transfer went to, or NULL on error - * @param execution_time time when the exchange claims to have performed the wire transfer - * @param total_amount total amount of the wire transfer, or NULL if the exchange could - * not provide any @a wtid (set only if @a http_status is #MHD_HTTP_OK) - * @param wire_fee wire fee that was charged by the exchange - * @param details_length length of the @a details array - * @param details array with details about the combined transactions + * @param tgr response data */ typedef void (*TALER_EXCHANGE_TransfersGetCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, - const struct GNUNET_HashCode *h_wire, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *total_amount, - const struct TALER_Amount *wire_fee, - unsigned int details_length, - const struct TALER_TrackTransferDetails *details); + 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 @@ -1624,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); @@ -1651,24 +3878,102 @@ struct TALER_EXCHANGE_DepositGetHandle; /** + * Data returned for a successful GET /deposits/ request. + */ +struct TALER_EXCHANGE_GetDepositResponse +{ + + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details about the response. + */ + union + { + + /** + * Response if the status was #MHD_HTTP_OK + */ + struct TALER_EXCHANGE_DepositData + { + /** + * exchange key used to sign, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * signature from the exchange over the deposit data, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * wire transfer identifier used by the exchange, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_WireTransferIdentifierRawP wtid; + + /** + * actual execution time for the wire transfer + */ + struct GNUNET_TIME_Timestamp execution_time; + + /** + * contribution to the total amount by this coin, all zeros if exchange did not + * yet execute the transaction + */ + struct TALER_Amount coin_contribution; + + } ok; + + /** + * Response if the status was #MHD_HTTP_ACCEPTED + */ + struct + { + + /** + * planned execution time for the wire transfer + */ + struct GNUNET_TIME_Timestamp execution_time; + + /** + * KYC legitimization requirement that the merchant should use to check + * for its KYC status. + */ + uint64_t requirement_row; + + /** + * Current AML state for the account. May explain why transfers are + * not happening. + */ + 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. + */ + bool kyc_ok; + } accepted; + + } details; +}; + + +/** * Function called with detailed wire transfer data. * * @param cls closure - * @param hr HTTP response data - * @param sign_key exchange key used to sign @a json, or NULL - * @param wtid wire transfer identifier used by the exchange, NULL if exchange did not - * yet execute the transaction - * @param execution_time actual or planned execution time for the wire transfer - * @param coin_contribution contribution to the total amount by this coin (can be NULL) + * @param dr details about the deposit response */ typedef void (*TALER_EXCHANGE_DepositGetCallback)( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ExchangePublicKeyP *sign_key, - const struct TALER_WireTransferIdentifierRawP *wtid, - struct GNUNET_TIME_Absolute execution_time, - const struct TALER_Amount *coin_contribution); + const struct TALER_EXCHANGE_GetDepositResponse *dr); /** @@ -1676,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 GNUNET_HashCode *h_wire, - const struct GNUNET_HashCode *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct GNUNET_TIME_Relative timeout, TALER_EXCHANGE_DepositGetCallback cb, void *cb_cls); @@ -1707,132 +4018,3310 @@ TALER_EXCHANGE_deposits_get_cancel ( struct TALER_EXCHANGE_DepositGetHandle *dwh); +/* ********************* /recoup *********************** */ + + +/** + * @brief A /recoup Handle + */ +struct TALER_EXCHANGE_RecoupHandle; + + /** - * Convenience function. Verifies a coin's transaction history as - * returned by the exchange. + * Response from a recoup request. + */ +struct TALER_EXCHANGE_RecoupResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * public key of the reserve receiving the recoup + */ + struct TALER_ReservePublicKeyP reserve_pub; + + } ok; + } details; + +}; + + +/** + * Callbacks of this type are used to return the final result of + * submitting a recoup request to a exchange. If the operation was + * successful, this function returns the @a reserve_pub of the + * reserve that was credited. * - * @param dk fee structure for the coin, NULL to skip verifying fees - * @param currency expected currency for the coin - * @param coin_pub public key of the coin - * @param history history of the coin in json encoding - * @param[out] total how much of the coin has been spent according to @a history - * @return #GNUNET_OK if @a history is valid, #GNUNET_SYSERR if not + * @param cls closure + * @param rr response data */ -int -TALER_EXCHANGE_verify_coin_history ( - const struct TALER_EXCHANGE_DenomPublicKey *dk, - const char *currency, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - json_t *history, - struct TALER_Amount *total); +typedef void +(*TALER_EXCHANGE_RecoupResultCallback) ( + void *cls, + const struct TALER_EXCHANGE_RecoupResponse *rr); /** - * Parse history given in JSON format and return it in binary - * format. + * Ask the exchange to pay back a coin due to the exchange triggering + * the emergency recoup protocol for a given denomination. The value + * of the coin will be refunded to the original customer (without fees). * - * @param exchange connection to the exchange we can use - * @param history JSON array with the history - * @param reserve_pub public key of the reserve to inspect - * @param currency currency we expect the balance to be in - * @param[out] balance final balance - * @param history_length number of entries in @a history - * @param[out] rhistory array of length @a history_length, set to the - * parsed history entries - * @return #GNUNET_OK if history was valid and @a rhistory and @a balance - * were set, - * #GNUNET_SYSERR if there was a protocol violation in @a history - */ -int -TALER_EXCHANGE_parse_reserve_history ( - struct TALER_EXCHANGE_Handle *exchange, - const json_t *history, - const struct TALER_ReservePublicKeyP *reserve_pub, - const char *currency, - struct TALER_Amount *balance, - unsigned int history_length, - struct TALER_EXCHANGE_ReserveHistory *rhistory); + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param pk kind of coin to pay back + * @param denom_sig signature over the coin by the exchange using @a pk + * @param exchange_vals contribution from the exchange on the withdraw + * @param ps secret internals of the original planchet + * @param recoup_cb the callback to call when the final result for this request is available + * @param recoup_cb_cls closure for @a recoup_cb + * @return NULL + * if the inputs are invalid (i.e. denomination key not with this exchange). + * In this case, the callback is not called. + */ +struct TALER_EXCHANGE_RecoupHandle * +TALER_EXCHANGE_recoup ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_PlanchetMasterSecretP *ps, + TALER_EXCHANGE_RecoupResultCallback recoup_cb, + void *recoup_cb_cls); /** - * Free memory (potentially) allocated by #TALER_EXCHANGE_parse_reserve_history(). + * Cancel a recoup request. This function cannot be used on a + * request handle if the callback was already invoked. * - * @param rhistory result to free - * @param len number of entries in @a rhistory + * @param ph the recoup handle */ void -TALER_EXCHANGE_free_reserve_history ( - struct TALER_EXCHANGE_ReserveHistory *rhistory, - unsigned int len); +TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph); -/* ********************* /recoup *********************** */ +/* ********************* /recoup-refresh *********************** */ /** - * @brief A /recoup Handle + * @brief A /recoup-refresh Handle */ -struct TALER_EXCHANGE_RecoupHandle; +struct TALER_EXCHANGE_RecoupRefreshHandle; + + +/** + * Response from a /recoup-refresh request. + */ +struct TALER_EXCHANGE_RecoupRefreshResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Response details depending on the HTTP status. + */ + union + { + /** + * Details if HTTP status is #MHD_HTTP_OK. + */ + struct + { + /** + * public key of the dirty coin that was credited + */ + struct TALER_CoinSpendPublicKeyP old_coin_pub; + + } ok; + } details; + +}; /** * Callbacks of this type are used to return the final result of - * submitting a refresh request to a exchange. If the operation was - * successful, this function returns the signatures over the coins - * that were remelted. The @a coin_privs and @a sigs arrays give the - * coins in the same order (and should have the same length) in which - * the original request specified the respective denomination keys. + * submitting a recoup-refresh request to a exchange. * * @param cls closure - * @param hr HTTP response data - * @param amount amount the exchange will wire back for this coin, - * on error the total balance remaining, or NULL - * @param timestamp what time did the exchange receive the /recoup request - * @param reserve_pub public key of the reserve receiving the recoup, NULL if refreshed or on error - * @param old_coin_pub public key of the dirty coin, NULL if not refreshed or on error + * @param rrr response data */ typedef void -(*TALER_EXCHANGE_RecoupResultCallback) ( +(*TALER_EXCHANGE_RecoupRefreshResultCallback) ( void *cls, - const struct TALER_EXCHANGE_HttpResponse *hr, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinSpendPublicKeyP *old_coin_pub); + const struct TALER_EXCHANGE_RecoupRefreshResponse *rrr); /** * Ask the exchange to pay back a coin due to the exchange triggering * the emergency recoup protocol for a given denomination. The value - * of the coin will be refunded to the original customer (without fees). + * of the coin will be refunded to the original coin that the + * revoked coin was refreshed from. The original coin is then + * considered a zombie. * - * @param exchange the exchange handle; the exchange must be ready to operate + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys * @param pk kind of coin to pay back * @param denom_sig signature over the coin by the exchange using @a pk - * @param ps secret internals of the original planchet - * @param was_refreshed #GNUNET_YES if the coin in @a ps was refreshed + * @param exchange_vals contribution from the exchange on the withdraw + * @param rms melt secret of the refreshing operation + * @param ps coin-specific secrets derived for this coin during the refreshing operation + * @param idx index of the fresh coin in the refresh operation that is now being recouped * @param recoup_cb the callback to call when the final result for this request is available * @param recoup_cb_cls closure for @a recoup_cb * @return NULL * if the inputs are invalid (i.e. denomination key not with this exchange). * In this case, the callback is not called. */ -struct TALER_EXCHANGE_RecoupHandle * -TALER_EXCHANGE_recoup (struct TALER_EXCHANGE_Handle *exchange, - const struct TALER_EXCHANGE_DenomPublicKey *pk, - const struct TALER_DenominationSignature *denom_sig, - const struct TALER_PlanchetSecretsP *ps, - int was_refreshed, - TALER_EXCHANGE_RecoupResultCallback recoup_cb, - void *recoup_cb_cls); +struct TALER_EXCHANGE_RecoupRefreshHandle * +TALER_EXCHANGE_recoup_refresh ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_EXCHANGE_DenomPublicKey *pk, + const struct TALER_DenominationSignature *denom_sig, + const struct TALER_ExchangeWithdrawValues *exchange_vals, + const struct TALER_RefreshMasterSecretP *rms, + const struct TALER_PlanchetMasterSecretP *ps, + unsigned int idx, + TALER_EXCHANGE_RecoupRefreshResultCallback recoup_cb, + void *recoup_cb_cls); /** - * Cancel a recoup request. This function cannot be used on a - * request handle if the callback was already invoked. + * Cancel a recoup-refresh request. This function cannot be used on a request + * handle if the callback was already invoked. * * @param ph the recoup handle */ void -TALER_EXCHANGE_recoup_cancel (struct TALER_EXCHANGE_RecoupHandle *ph); +TALER_EXCHANGE_recoup_refresh_cancel ( + struct TALER_EXCHANGE_RecoupRefreshHandle *ph); + + +/* ********************* /kyc* *********************** */ + +/** + * Handle for a ``/kyc-check`` operation. + */ +struct TALER_EXCHANGE_KycCheckHandle; + + +/** + * KYC status response details. + */ +struct TALER_EXCHANGE_KycStatus +{ + /** + * HTTP status code returned by the exchange. + */ + unsigned int http_status; + + /** + * Taler error code, if any. + */ + enum TALER_ErrorCode ec; + + union + { + + /** + * KYC is OK, affirmation returned by the exchange. + */ + struct + { + + /** + * Details about which KYC check(s) were passed. + */ + const json_t *kyc_details; + + /** + * Time of the affirmation. + */ + struct GNUNET_TIME_Timestamp timestamp; + + /** + * The signing public key used for @e exchange_sig. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature of purpose + * #TALER_SIGNATURE_EXCHANGE_ACCOUNT_SETUP_SUCCESS affirming + * the successful KYC process. + */ + struct TALER_ExchangeSignatureP exchange_sig; + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } ok; + + /** + * KYC is required. + */ + struct + { + + /** + * URL the user should open in a browser if + * the KYC process is to be run. Returned if + * @e http_status is #MHD_HTTP_ACCEPTED. + */ + const char *kyc_url; + + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } accepted; + + /** + * KYC is OK, but account needs positive AML decision. + */ + struct + { + + /** + * AML status for the account. + */ + enum TALER_AmlDecisionState aml_status; + + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with the result of a KYC check. + * + * @param cls closure + * @param ks the account's KYC status details + */ +typedef void +(*TALER_EXCHANGE_KycStatusCallback)( + void *cls, + const struct TALER_EXCHANGE_KycStatus *ks); + + +/** + * Run interaction with exchange to check KYC status + * of a merchant. + * + * @param ctx CURL context + * @param url exchange base URL + * @param keys keys of the exchange + * @param requirement_row number identifying the KYC requirement + * @param h_payto hash of the payto:// URI at @a payment_target + * @param ut type of the entity performing the KYC check + * @param timeout how long to wait for a positive KYC status + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return NULL on error + */ +struct TALER_EXCHANGE_KycCheckHandle * +TALER_EXCHANGE_kyc_check ( + struct 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); + + +/** + * Cancel KYC check operation. + * + * @param kyc handle for operation to cancel + */ +void +TALER_EXCHANGE_kyc_check_cancel (struct TALER_EXCHANGE_KycCheckHandle *kyc); + + +/** + * KYC proof response details. + */ +struct TALER_EXCHANGE_KycProofResponse +{ + /** + * HTTP status code returned by the exchange. + */ + unsigned int http_status; + + union + { + + /** + * KYC is OK, affirmation returned by the exchange. + */ + struct + { + + /** + * Where to redirect the client next. + */ + const char *redirect_url; + + } found; + + } details; + +}; + +/** + * Function called with the result of a KYC check. + * + * @param cls closure + * @param kpr the account's KYC status details + */ +typedef void +(*TALER_EXCHANGE_KycProofCallback)( + void *cls, + const struct TALER_EXCHANGE_KycProofResponse *kpr); + + +/** + * Handle for a /kyc-proof operation. + */ +struct TALER_EXCHANGE_KycProofHandle; + + +/** + * Run interaction with exchange to provide proof of KYC status. + * + * @param ctx CURL context + * @param url exchange base URL + * @param h_payto hash of payto URI identifying the target account + * @param logic name of the KYC logic to run + * @param args additional args to pass, can be NULL + * or a string to append to the URL. Must then begin with '&'. + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return NULL on error + */ +struct TALER_EXCHANGE_KycProofHandle * +TALER_EXCHANGE_kyc_proof ( + struct 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); + + +/** + * Cancel KYC proof operation. + * + * @param kph handle for operation to cancel + */ +void +TALER_EXCHANGE_kyc_proof_cancel (struct TALER_EXCHANGE_KycProofHandle *kph); + + +/** + * Handle for a ``/kyc-wallet`` operation. + */ +struct TALER_EXCHANGE_KycWalletHandle; + + +/** + * KYC status response details. + */ +struct TALER_EXCHANGE_WalletKycResponse +{ + + /** + * HTTP status code returned by the exchange. + */ + unsigned int http_status; + + /** + * Taler error code, if any. + */ + enum TALER_ErrorCode ec; + + /** + * Variants depending on @e http_status. + */ + union + { + + /** + * In case @e http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Wallet's KYC requirement row. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI identifying the wallet to KYC. + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with the result for a wallet looking + * up its KYC payment target. + * + * @param cls closure + * @param ks the wallets KYC payment target details + */ +typedef void +(*TALER_EXCHANGE_KycWalletCallback)( + void *cls, + const struct TALER_EXCHANGE_WalletKycResponse *ks); + + +/** + * Run interaction with exchange to find out the wallet's KYC + * identifier. + * + * @param ctx CURL context + * @param url exchange base URL + * @param reserve_priv wallet private key to check + * @param balance balance (or balance threshold) crossed by the wallet + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return NULL on error + */ +struct TALER_EXCHANGE_KycWalletHandle * +TALER_EXCHANGE_kyc_wallet ( + struct 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); + + +/** + * Cancel KYC wallet operation + * + * @param kwh handle for operation to cancel + */ +void +TALER_EXCHANGE_kyc_wallet_cancel (struct TALER_EXCHANGE_KycWalletHandle *kwh); + + +/* ********************* /management *********************** */ + + +/** + * @brief Future Exchange's signature key + */ +struct TALER_EXCHANGE_FutureSigningPublicKey +{ + /** + * The signing public key + */ + struct TALER_ExchangePublicKeyP key; + + /** + * Signature by the security module affirming it owns this key. + */ + struct TALER_SecurityModuleSignatureP signkey_secmod_sig; + + /** + * Validity start time + */ + struct GNUNET_TIME_Timestamp valid_from; + + /** + * Validity expiration time (how long the exchange may use it). + */ + struct GNUNET_TIME_Timestamp valid_until; + + /** + * Validity expiration time for legal disputes. + */ + struct GNUNET_TIME_Timestamp valid_legal; +}; + + +/** + * @brief Public information about a future exchange's denomination key + */ +struct TALER_EXCHANGE_FutureDenomPublicKey +{ + /** + * The public key + */ + struct TALER_DenominationPublicKey key; + + /** + * Signature by the security module affirming it owns this key. + */ + struct TALER_SecurityModuleSignatureP denom_secmod_sig; + + /** + * Timestamp indicating when the denomination key becomes valid + */ + struct GNUNET_TIME_Timestamp valid_from; + + /** + * Timestamp indicating when the denomination key can’t be used anymore to + * withdraw new coins. + */ + struct GNUNET_TIME_Timestamp withdraw_valid_until; + + /** + * Timestamp indicating when coins of this denomination become invalid. + */ + struct GNUNET_TIME_Timestamp expire_deposit; + + /** + * When do signatures with this denomination key become invalid? + * After this point, these signatures cannot be used in (legal) + * disputes anymore, as the Exchange is then allowed to destroy its side + * of the evidence. @e expire_legal is expected to be significantly + * larger than @e expire_deposit (by a year or more). + */ + struct GNUNET_TIME_Timestamp expire_legal; + + /** + * The value of this denomination + */ + struct TALER_Amount value; + + /** + * The applicable fee for withdrawing a coin of this denomination + */ + struct TALER_Amount fee_withdraw; + + /** + * The applicable fee to spend a coin of this denomination + */ + struct TALER_Amount fee_deposit; + + /** + * The applicable fee to melt/refresh a coin of this denomination + */ + struct TALER_Amount fee_refresh; + + /** + * The applicable fee to refund a coin of this denomination + */ + struct TALER_Amount fee_refund; + +}; + + +/** + * @brief Information about future keys from the exchange. + */ +struct TALER_EXCHANGE_FutureKeys +{ + + /** + * Array of the exchange's online signing keys. + */ + struct TALER_EXCHANGE_FutureSigningPublicKey *sign_keys; + + /** + * Array of the exchange's denomination keys. + */ + struct TALER_EXCHANGE_FutureDenomPublicKey *denom_keys; + + /** + * Public key of the signkey security module. + */ + struct TALER_SecurityModulePublicKeyP signkey_secmod_public_key; + + /** + * Public key of the RSA denomination security module. + */ + struct TALER_SecurityModulePublicKeyP denom_secmod_public_key; + + /** + * Public key of the CS denomination security module. + */ + struct TALER_SecurityModulePublicKeyP denom_secmod_cs_public_key; + + /** + * Offline master public key used by this exchange. + */ + struct TALER_MasterPublicKeyP master_pub; + + /** + * Length of the @e sign_keys array (number of valid entries). + */ + unsigned int num_sign_keys; + + /** + * Length of the @e denom_keys array. + */ + unsigned int num_denom_keys; + +}; + + +/** + * 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 mgr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementGetKeysCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementGetKeysResponse *mgr); + + +/** + * @brief Handle for a GET /management/keys request. + */ +struct TALER_EXCHANGE_ManagementGetKeysHandle; + + +/** + * Request future keys from the exchange. The obtained information will be + * passed to the @a cb. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param cb function to call with the exchange's future keys result + * @param cb_cls closure for @a cb + * @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); + + +/** + * Cancel #TALER_EXCHANGE_get_management_keys() operation. + * + * @param gh handle of the operation to cancel + */ +void +TALER_EXCHANGE_get_management_keys_cancel ( + struct TALER_EXCHANGE_ManagementGetKeysHandle *gh); + + +/** + * @brief Public information about a signature on an exchange's online signing key + */ +struct TALER_EXCHANGE_SigningKeySignature +{ + /** + * The signing public key + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature over this signing key by the exchange's master signature. + * Of purpose #TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY + */ + struct TALER_MasterSignatureP master_sig; + +}; + + +/** + * @brief Public information about a signature on an exchange's denomination key + */ +struct TALER_EXCHANGE_DenominationKeySignature +{ + /** + * The hash of the denomination's public key + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Signature over this denomination key by the exchange's master signature. + * Of purpose #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY. + */ + struct TALER_MasterSignatureP master_sig; + +}; + + +/** + * Information needed for a POST /management/keys operation. + */ +struct TALER_EXCHANGE_ManagementPostKeysData +{ + + /** + * Array of the master signatures for the exchange's online signing keys. + */ + struct TALER_EXCHANGE_SigningKeySignature *sign_sigs; + + /** + * Array of the master signatures for the exchange's denomination keys. + */ + struct TALER_EXCHANGE_DenominationKeySignature *denom_sigs; + + /** + * Length of the @e sign_keys array (number of valid entries). + */ + unsigned int num_sign_sigs; + + /** + * Length of the @e denom_keys array. + */ + unsigned int num_denom_sigs; +}; + + +/** + * 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 mr response data + */ +typedef void +(*TALER_EXCHANGE_ManagementPostKeysCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementPostKeysResponse *mr); + + +/** + * @brief Handle for a POST /management/keys request. + */ +struct TALER_EXCHANGE_ManagementPostKeysHandle; + + +/** + * Provide master-key signatures to the exchange. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param pkd signature data to POST + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementPostKeysHandle * +TALER_EXCHANGE_post_management_keys ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_EXCHANGE_ManagementPostKeysData *pkd, + TALER_EXCHANGE_ManagementPostKeysCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_post_management_keys() operation. + * + * @param ph handle of the operation to cancel + */ +void +TALER_EXCHANGE_post_management_keys_cancel ( + struct TALER_EXCHANGE_ManagementPostKeysHandle *ph); + + +/** + * Information needed for a POST /management/extensions operation. + * + * It represents the interface ExchangeKeysResponse as defined in + * https://docs.taler.net/design-documents/006-extensions.html#exchange + */ +struct TALER_EXCHANGE_ManagementPostExtensionsData +{ + const json_t *extensions; + struct TALER_MasterSignatureP extensions_sig; +}; + + +/** + * Response from a POST /management/extensions request. + */ +struct TALER_EXCHANGE_ManagementPostExtensionsResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** + * Function called with information about the post extensions operation result. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementPostExtensionsCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementPostExtensionsResponse *hr); + +/** + * @brief Handle for a POST /management/extensions request. + */ +struct TALER_EXCHANGE_ManagementPostExtensionsHandle; + + +/** + * Uploads the configurations of enabled extensions to the exchange, signed + * with the master key. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param ped signature data to POST + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementPostExtensionsHandle * +TALER_EXCHANGE_management_post_extensions ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_EXCHANGE_ManagementPostExtensionsData *ped, + TALER_EXCHANGE_ManagementPostExtensionsCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_post_extensions() operation. + * + * @param ph handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_post_extensions_cancel ( + struct TALER_EXCHANGE_ManagementPostExtensionsHandle *ph); + + +/** + * Response from a POST /management/drain request. + */ +struct TALER_EXCHANGE_ManagementDrainResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** + * Function called with information about the drain profits result. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementDrainProfitsCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementDrainResponse *hr); + + +/** + * @brief Handle for a POST /management/drain request. + */ +struct TALER_EXCHANGE_ManagementDrainProfitsHandle; + + +/** + * Uploads the drain profits request. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param wtid wire transfer identifier to use + * @param amount total to transfer + * @param date when was the request created + * @param account_section configuration section identifying account to debit + * @param payto_uri RFC 8905 URI of the account to credit + * @param master_sig signature affirming the operation + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementDrainProfitsHandle * +TALER_EXCHANGE_management_drain_profits ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Timestamp date, + const char *account_section, + const char *payto_uri, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementDrainProfitsCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_drain_profits() operation. + * + * @param dp handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_drain_profits_cancel ( + struct TALER_EXCHANGE_ManagementDrainProfitsHandle *dp); + + +/** + * Response from a POST /management/denominations/$DENOM/revoke request. + */ +struct TALER_EXCHANGE_ManagementRevokeDenominationResponse +{ + /** + * HTTP response data + */ + struct TALER_EXCHANGE_HttpResponse hr; + +}; + + +/** + * Function called with information about the post revocation operation result. + * + * @param cls closure + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementRevokeDenominationResponse *hr); + + +/** + * @brief Handle for a POST /management/denominations/$H_DENOM_PUB/revoke request. + */ +struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle; + + +/** + * Inform the exchange that a denomination key was revoked. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param h_denom_pub hash of the denomination public key that was revoked + * @param master_sig signature affirming the revocation + * @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_ManagementRevokeDenominationKeyHandle * +TALER_EXCHANGE_management_revoke_denomination_key ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementRevokeDenominationKeyCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_revoke_denomination_key() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_revoke_denomination_key_cancel ( + struct TALER_EXCHANGE_ManagementRevokeDenominationKeyHandle *rh); + + +/** + * 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 + * @param hr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementRevokeSigningKeyCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementRevokeSigningKeyResponse *hr); + + +/** + * @brief Handle for a POST /management/signkeys/$H_DENOM_PUB/revoke request. + */ +struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle; + + +/** + * Inform the exchange that a signing key was revoked. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param exchange_pub the public signing key that was revoked + * @param master_sig signature affirming the revocation + * @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_ManagementRevokeSigningKeyHandle * +TALER_EXCHANGE_management_revoke_signing_key ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementRevokeSigningKeyCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_revoke_signing_key() operation. + * + * @param rh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_revoke_signing_key_cancel ( + struct TALER_EXCHANGE_ManagementRevokeSigningKeyHandle *rh); + + +/** + * 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_ManagementAuditorEnableResponse *aer); + + +/** + * @brief Handle for a POST /management/auditors request. + */ +struct TALER_EXCHANGE_ManagementAuditorEnableHandle; + + +/** + * Inform the exchange that an auditor should be enable or enabled. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param auditor_pub the public signing key of the auditor + * @param auditor_url base URL of the auditor + * @param auditor_name human readable name for the auditor + * @param validity_start when was this decided? + * @param master_sig signature affirming the auditor addition + * @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_ManagementAuditorEnableHandle * +TALER_EXCHANGE_management_enable_auditor ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name, + struct GNUNET_TIME_Timestamp validity_start, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementAuditorEnableCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_enable_auditor() operation. + * + * @param ah handle of the operation to cancel + */ +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 adr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementAuditorDisableCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementAuditorDisableResponse *adr); + + +/** + * @brief Handle for a POST /management/auditors/$AUDITOR_PUB/disable request. + */ +struct TALER_EXCHANGE_ManagementAuditorDisableHandle; + + +/** + * Inform the exchange that an auditor should be disabled. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param auditor_pub the public signing key of the auditor + * @param validity_end when was this decided? + * @param master_sig signature affirming the auditor addition + * @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_ManagementAuditorDisableHandle * +TALER_EXCHANGE_management_disable_auditor ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementAuditorDisableCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_disable_auditor() operation. + * + * @param ah handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_disable_auditor_cancel ( + struct TALER_EXCHANGE_ManagementAuditorDisableHandle *ah); + + +/** + * 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 wer HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementWireEnableCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementWireEnableResponse *wer); + + +/** + * @brief Handle for a POST /management/wire request. + */ +struct TALER_EXCHANGE_ManagementWireEnableHandle; + + +/** + * Inform the exchange that a wire account should be enabled. + * + * @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 + */ +struct TALER_EXCHANGE_ManagementWireEnableHandle * +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); + + +/** + * Cancel #TALER_EXCHANGE_management_enable_wire() operation. + * + * @param wh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_enable_wire_cancel ( + struct TALER_EXCHANGE_ManagementWireEnableHandle *wh); + + +/** + * 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 wdr response data + */ +typedef void +(*TALER_EXCHANGE_ManagementWireDisableCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementWireDisableResponse *wdr); + + +/** + * @brief Handle for a POST /management/wire/disable request. + */ +struct TALER_EXCHANGE_ManagementWireDisableHandle; + + +/** + * Inform the exchange that a wire account should be disabled. + * + * @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 validity_end when was this decided? + * @param master_sig signature affirming the wire addition + * of purpose #TALER_SIGNATURE_MASTER_DEL_WIRE + * @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_ManagementWireDisableHandle * +TALER_EXCHANGE_management_disable_wire ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const char *payto_uri, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementWireDisableCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_disable_wire() operation. + * + * @param wh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_disable_wire_cancel ( + struct TALER_EXCHANGE_ManagementWireDisableHandle *wh); + + +/** + * 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 wfr response data + */ +typedef void +(*TALER_EXCHANGE_ManagementSetWireFeeCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementSetWireFeeResponse *wfr); + + +/** + * @brief Handle for a POST /management/wire-fees request. + */ +struct TALER_EXCHANGE_ManagementSetWireFeeHandle; + + +/** + * Inform the exchange about future wire fees. + * + * @param ctx the context + * @param exchange_base_url HTTP base URL for the exchange + * @param wire_method for which wire method are fees provided + * @param validity_start start date for the provided wire fees + * @param validity_end end date for the provided wire fees + * @param fees the wire fees for this time period + * @param master_sig signature affirming the wire fees; + * of purpose #TALER_SIGNATURE_MASTER_WIRE_FEES + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementSetWireFeeHandle * +TALER_EXCHANGE_management_set_wire_fees ( + struct GNUNET_CURL_Context *ctx, + const char *exchange_base_url, + const char *wire_method, + struct GNUNET_TIME_Timestamp validity_start, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementSetWireFeeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_enable_wire() operation. + * + * @param swfh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_set_wire_fees_cancel ( + struct TALER_EXCHANGE_ManagementSetWireFeeHandle *swfh); + + +/** + * Response when setting global fees. + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about the global fee setting operation result. + * + * @param cls closure + * @param gfr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ManagementSetGlobalFeeCallback) ( + void *cls, + const struct TALER_EXCHANGE_ManagementSetGlobalFeeResponse *gfr); + + +/** + * @brief Handle for a POST /management/global-fees request. + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle; + + +/** + * Inform the exchange about global fees. + * + * @param ctx the context + * @param exchange_base_url HTTP base URL for the exchange + * @param validity_start start date for the provided wire fees + * @param validity_end end date for the provided wire fees + * @param fees the wire fees for this time period + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account + * @param master_sig signature affirming the wire fees; + * of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle * +TALER_EXCHANGE_management_set_global_fees ( + struct GNUNET_CURL_Context *ctx, + const char *exchange_base_url, + struct GNUNET_TIME_Timestamp validity_start, + struct GNUNET_TIME_Timestamp validity_end, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + const struct TALER_MasterSignatureP *master_sig, + TALER_EXCHANGE_ManagementSetGlobalFeeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_management_enable_wire() operation. + * + * @param sgfh handle of the operation to cancel + */ +void +TALER_EXCHANGE_management_set_global_fees_cancel ( + struct TALER_EXCHANGE_ManagementSetGlobalFeeHandle *sgfh); + + +/** + * Response when adding denomination signature by auditor. + */ +struct TALER_EXCHANGE_AuditorAddDenominationResponse +{ + /** + * HTTP response data. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about the POST + * /auditor/$AUDITOR_PUB/$H_DENOM_PUB operation result. + * + * @param cls closure + * @param adr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_AuditorAddDenominationCallback) ( + void *cls, + const struct TALER_EXCHANGE_AuditorAddDenominationResponse *adr); + + +/** + * @brief Handle for a POST /auditor/$AUDITOR_PUB/$H_DENOM_PUB request. + */ +struct TALER_EXCHANGE_AuditorAddDenominationHandle; + + +/** + * Provide auditor signatures for a denomination to the exchange. + * + * @param ctx the context + * @param url HTTP base URL for the exchange + * @param h_denom_pub hash of the public key of the denomination + * @param auditor_pub public key of the auditor + * @param auditor_sig signature of the auditor, of + * purpose #TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS + * @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_AuditorAddDenominationHandle * +TALER_EXCHANGE_add_auditor_denomination ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig, + TALER_EXCHANGE_AuditorAddDenominationCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_add_auditor_denomination() operation. + * + * @param ah handle of the operation to cancel + */ +void +TALER_EXCHANGE_add_auditor_denomination_cancel ( + struct TALER_EXCHANGE_AuditorAddDenominationHandle *ah); + + +/* ********************* W2W API ****************** */ + + +/** + * Response generated for a contract get request. + */ +struct TALER_EXCHANGE_ContractGetResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status code. + */ + union + { + /** + * Information returned on #MHD_HTTP_OK. + */ + struct + { + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Encrypted contract. + */ + const void *econtract; + + /** + * Number of bytes in @e econtract. + */ + size_t econtract_size; + + } ok; + + } details; + +}; + +/** + * Function called with information about the a purse. + * + * @param cls closure + * @param cgr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ContractGetCallback) ( + void *cls, + const struct TALER_EXCHANGE_ContractGetResponse *cgr); + + +/** + * @brief Handle for a GET /contracts/$CPUB request. + */ +struct TALER_EXCHANGE_ContractsGetHandle; + + +/** + * Request information about a contract from the exchange. + * + * @param ctx CURL context + * @param url exchange base URL + * @param contract_priv private key of the contract + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_ContractsGetHandle * +TALER_EXCHANGE_contract_get ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ContractDiffiePrivateP *contract_priv, + TALER_EXCHANGE_ContractGetCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_contract_get() operation. + * + * @param cgh handle of the operation to cancel + */ +void +TALER_EXCHANGE_contract_get_cancel ( + struct TALER_EXCHANGE_ContractsGetHandle *cgh); + + +/** + * Response generated for a purse get request. + */ +struct TALER_EXCHANGE_PurseGetResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Response on #MHD_HTTP_OK. + */ + struct + { + + /** + * Time when the purse was merged (or zero if it + * was not merged). + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * Time when the full amount was deposited into + * the purse (or zero if a sufficient amount + * was not yet deposited). + */ + struct GNUNET_TIME_Timestamp deposit_timestamp; + + /** + * Reserve balance (how much was deposited in + * total into the reserve, minus deposit fees). + */ + struct TALER_Amount balance; + + /** + * Time when the purse will expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + } ok; + + } details; + +}; + + +/** + * Function called with information about the a purse. + * + * @param cls closure + * @param pgr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseGetCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseGetResponse *pgr); + + +/** + * @brief Handle for a GET /purses/$PPUB request. + */ +struct TALER_EXCHANGE_PurseGetHandle; + + +/** + * Request information about a purse from the exchange. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_pub public key of the purse + * @param timeout how long to wait for a change to happen + * @param wait_for_merge true to wait for a merge event, otherwise wait for a deposit event + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseGetHandle * +TALER_EXCHANGE_purse_get ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Relative timeout, + bool wait_for_merge, + TALER_EXCHANGE_PurseGetCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_get() operation. + * + * @param pgh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_get_cancel ( + struct TALER_EXCHANGE_PurseGetHandle *pgh); + + +/** + * Response generated for a purse creation request. + */ +struct TALER_EXCHANGE_PurseCreateDepositResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + /** + * Signing key used by the exchange to sign the + * purse create with deposit confirmation. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Signature from the exchange on the + * purse create with deposit confirmation. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + + } ok; + + } details; + +}; + +/** + * Function called with information about the creation + * of a new purse. + * + * @param cls closure + * @param pcr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseCreateDepositCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseCreateDepositResponse *pcr); + + +/** + * @brief Handle for a POST /purses/$PID/create request. + */ +struct TALER_EXCHANGE_PurseCreateDepositHandle; + + +/** + * Information about a coin to be deposited into a purse or reserve. + */ +struct TALER_EXCHANGE_PurseDeposit +{ + /** + * Age commitment data, might be NULL. + */ + const struct TALER_AgeCommitmentProof *age_commitment_proof; + + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; + + /** + * Signature proving the validity of the coin. + */ + struct TALER_DenominationSignature denom_sig; + + /** + * Hash of the denomination's public key. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Amount of the coin to transfer into the purse. + */ + struct TALER_Amount amount; + +}; + + +/** + * Inform the exchange that a purse should be created + * and coins deposited into it. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_priv private key of the purse + * @param merge_priv the merge credential + * @param contract_priv key needed to obtain and decrypt the contract + * @param contract_terms contract the purse is about + * @param num_deposits length of the @a deposits array + * @param deposits array of deposits to make into the purse + * @param upload_contract true to upload the contract; must + * be FALSE for repeated calls to this API for the + * same purse (i.e. when adding more deposits). + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseCreateDepositHandle * +TALER_EXCHANGE_purse_create_with_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + unsigned int num_deposits, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], + bool upload_contract, + TALER_EXCHANGE_PurseCreateDepositCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_create_with_deposit() operation. + * + * @param pch handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_create_with_deposit_cancel ( + struct TALER_EXCHANGE_PurseCreateDepositHandle *pch); + + +/** + * Response generated for a purse deletion request. + */ +struct TALER_EXCHANGE_PurseDeleteResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; +}; + + +/** + * Function called with information about the deletion + * of a purse. + * + * @param cls closure + * @param pdr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseDeleteCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseDeleteResponse *pdr); + + +/** + * @brief Handle for a DELETE /purses/$PID request. + */ +struct TALER_EXCHANGE_PurseDeleteHandle; + + +/** + * Asks the exchange to delete a purse. Will only succeed if + * the purse was not yet merged and did not yet time out. + * + * @param ctx CURL context + * @param url exchange base URL + * @param purse_priv private key of the purse + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseDeleteHandle * +TALER_EXCHANGE_purse_delete ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + TALER_EXCHANGE_PurseDeleteCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_delete() operation. + * + * @param pdh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_delete_cancel ( + struct TALER_EXCHANGE_PurseDeleteHandle *pdh); + + +/** + * Response generated for an account merge request. + */ +struct TALER_EXCHANGE_AccountMergeResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Reserve signature affirming the merge. + */ + const struct TALER_ReserveSignatureP *reserve_sig; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + /** + * Signature by the exchange affirming the merge. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * Online signing key used by the exchange. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Timestamp of the exchange for @e exchange_sig. + */ + struct GNUNET_TIME_Timestamp etime; + + } ok; + + /** + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row target that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with information about an account merge + * operation. + * + * @param cls closure + * @param amr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_AccountMergeCallback) ( + void *cls, + const struct TALER_EXCHANGE_AccountMergeResponse *amr); + + +/** + * @brief Handle for a POST /purses/$PID/merge request. + */ +struct TALER_EXCHANGE_AccountMergeHandle; + + +/** + * Inform the exchange that a purse should be merged + * with a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_exchange_url base URL of the exchange with the reserve + * @param reserve_priv private key of the reserve to merge into + * @param purse_pub public key of the purse to merge + * @param merge_priv private key granting us the right to merge + * @param h_contract_terms hash of the purses' contract + * @param min_age minimum age of deposits into the purse + * @param purse_value_after_fees amount that should be in the purse + * @param purse_expiration when will the purse expire + * @param merge_timestamp when is the merge happening (current time) + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_AccountMergeHandle * +TALER_EXCHANGE_account_merge ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const char *reserve_exchange_url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint8_t min_age, + const struct TALER_Amount *purse_value_after_fees, + struct GNUNET_TIME_Timestamp purse_expiration, + struct GNUNET_TIME_Timestamp merge_timestamp, + TALER_EXCHANGE_AccountMergeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_account_merge() operation. + * + * @param amh handle of the operation to cancel + */ +void +TALER_EXCHANGE_account_merge_cancel ( + struct TALER_EXCHANGE_AccountMergeHandle *amh); + + +/** + * Response generated for a purse creation request. + */ +struct TALER_EXCHANGE_PurseCreateMergeResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Reserve signature generated for the request + * (client-side). + */ + const struct TALER_ReserveSignatureP *reserve_sig; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Details returned on #MHD_HTTP_OK. + */ + struct + { + + } ok; + + /** + * Details if the status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + } unavailable_for_legal_reasons; + + } details; + +}; + +/** + * Function called with information about the creation + * of a new purse. + * + * @param cls closure + * @param pcr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseCreateMergeCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseCreateMergeResponse *pcr); + + +/** + * @brief Handle for a POST /reserves/$RID/purse request. + */ +struct TALER_EXCHANGE_PurseCreateMergeHandle; + + +/** + * Inform the exchange that a purse should be created + * and merged with a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve + * @param purse_priv private key of the purse + * @param merge_priv private key of the merge capability + * @param contract_priv private key to get the contract + * @param contract_terms contract the purse is about + * @param upload_contract true to upload the contract + * @param pay_for_purse true to pay for purse creation + * @param merge_timestamp when should the merge happen (use current time) + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseCreateMergeHandle * +TALER_EXCHANGE_purse_create_with_merge ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_PurseContractPrivateKeyP *purse_priv, + const struct TALER_PurseMergePrivateKeyP *merge_priv, + const struct TALER_ContractDiffiePrivateP *contract_priv, + const json_t *contract_terms, + bool upload_contract, + bool pay_for_purse, + struct GNUNET_TIME_Timestamp merge_timestamp, + TALER_EXCHANGE_PurseCreateMergeCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_create_with_merge() operation. + * + * @param pcm handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_create_with_merge_cancel ( + struct TALER_EXCHANGE_PurseCreateMergeHandle *pcm); + + +/** + * Response generated for purse deposit request. + */ +struct TALER_EXCHANGE_PurseDepositResponse +{ + /** + * Full HTTP response. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on the HTTP status. + */ + union + { + /** + * Detailed returned on #MHD_HTTP_OK. + */ + struct + { + + /** + * When does the purse expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * How much was actually deposited into the purse. + */ + struct TALER_Amount total_deposited; + + /** + * How much should be in the purse in total in the end. + */ + struct TALER_Amount purse_value_after_fees; + + /** + * Hash of the contract (needed to verify signature). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + } ok; + } details; + +}; + +/** + * Function called with information about a purse-deposit + * operation. + * + * @param cls closure + * @param pdr HTTP response data + */ +typedef void +(*TALER_EXCHANGE_PurseDepositCallback) ( + void *cls, + const struct TALER_EXCHANGE_PurseDepositResponse *pdr); + + +/** + * @brief Handle for a POST /purses/$PID/deposit request. + */ +struct TALER_EXCHANGE_PurseDepositHandle; + + +/** + * Inform the exchange that a deposit should be made into + * a purse. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param purse_exchange_url base URL of the exchange hosting the purse + * @param purse_pub public key of the purse to merge + * @param min_age minimum age we need to prove for the purse + * @param num_deposits length of the @a deposits array + * @param deposits array of deposits to make into the purse + * @param cb function to call with the exchange's result + * @param cb_cls closure for @a cb + * @return the request handle; NULL upon error + */ +struct TALER_EXCHANGE_PurseDepositHandle * +TALER_EXCHANGE_purse_deposit ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const char *purse_exchange_url, + const struct TALER_PurseContractPublicKeyP *purse_pub, + uint8_t min_age, + unsigned int num_deposits, + const struct TALER_EXCHANGE_PurseDeposit deposits[static num_deposits], + TALER_EXCHANGE_PurseDepositCallback cb, + void *cb_cls); + + +/** + * Cancel #TALER_EXCHANGE_purse_deposit() operation. + * + * @param amh handle of the operation to cancel + */ +void +TALER_EXCHANGE_purse_deposit_cancel ( + struct TALER_EXCHANGE_PurseDepositHandle *amh); + + +/* ********************* /reserves/$RID/open *********************** */ + + +/** + * @brief A /reserves/$RID/open Handle + */ +struct TALER_EXCHANGE_ReservesOpenHandle; + + +/** + * @brief Reserve open result details. + */ +struct TALER_EXCHANGE_ReserveOpenResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + /** + * New expiration time + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Actual cost of the open operation. + */ + struct TALER_Amount open_cost; + + } ok; + + + /** + * Information returned if the payment provided is insufficient, if + * @e hr.http_status is #MHD_HTTP_PAYMENT_REQUIRED + */ + struct + { + /** + * Current expiration time of the reserve. + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Actual cost of the open operation that should have been paid. + */ + struct TALER_Amount open_cost; + + } payment_required; + + /** + * Information returned if status is + * #MHD_HTTP_CONFLICT. + */ + struct + { + /** + * Public key of the coin that caused the conflict. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + } conflict; + + /** + * Information returned if KYC is required to proceed, set if + * @e hr.http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve open request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesOpenCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveOpenResult *ror); + + +/** + * Submit a request to open a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param keys exchange keys + * @param reserve_priv private key of the reserve to open + * @param reserve_contribution amount to pay from the reserve's balance for the operation + * @param coin_payments_length length of the @a coin_payments array + * @param coin_payments array of coin payments to use for opening the reserve + * @param expiration_time desired new expiration time for the reserve + * @param min_purses minimum number of purses to allow being concurrently opened per reserve + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesOpenHandle * +TALER_EXCHANGE_reserves_open ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const struct TALER_Amount *reserve_contribution, + unsigned int coin_payments_length, + const struct TALER_EXCHANGE_PurseDeposit coin_payments[ + static coin_payments_length], + struct GNUNET_TIME_Timestamp expiration_time, + uint32_t min_purses, + TALER_EXCHANGE_ReservesOpenCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param[in] roh the reserve open request handle + */ +void +TALER_EXCHANGE_reserves_open_cancel ( + struct TALER_EXCHANGE_ReservesOpenHandle *roh); + + +/* ********************* /reserves/$RID/attest *********************** */ + + +/** + * @brief A Get /reserves/$RID/attest Handle + */ +struct TALER_EXCHANGE_ReservesGetAttestHandle; + + +/** + * @brief Reserve GET attest result details. + */ +struct TALER_EXCHANGE_ReserveGetAttestResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Length of the @e attributes array. + */ + unsigned int attributes_length; + + /** + * Array of attributes available about the user. + */ + const char **attributes; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve attest request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesGetAttestCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveGetAttestResult *ror); + + +/** + * Submit a request to get the list of attestable attributes for a reserve. + * + * @param ctx CURL context + * @param url exchange base URL + * @param reserve_pub public key of the reserve to get available attributes for + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesGetAttestHandle * +TALER_EXCHANGE_reserves_get_attestable ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePublicKeyP *reserve_pub, + TALER_EXCHANGE_ReservesGetAttestCallback cb, + void *cb_cls); + + +/** + * Cancel a request to get attestable attributes. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rgah the reserve get attestable request handle + */ +void +TALER_EXCHANGE_reserves_get_attestable_cancel ( + struct TALER_EXCHANGE_ReservesGetAttestHandle *rgah); + + +/** + * @brief A POST /reserves/$RID/attest Handle + */ +struct TALER_EXCHANGE_ReservesPostAttestHandle; + + +/** + * @brief Reserve attest result details. + */ +struct TALER_EXCHANGE_ReservePostAttestResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + /** + * Time when the exchange made the signature. + */ + struct GNUNET_TIME_Timestamp exchange_time; + + /** + * Expiration time of the attested attributes. + */ + struct GNUNET_TIME_Timestamp expiration_time; + + /** + * Signature by the exchange affirming the attributes. + */ + struct TALER_ExchangeSignatureP exchange_sig; + + /** + * Online signing key used by the exchange. + */ + struct TALER_ExchangePublicKeyP exchange_pub; + + /** + * Attributes being confirmed by the exchange. + */ + const json_t *attributes; + + } ok; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve attest request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesPostAttestCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReservePostAttestResult *ror); + + +/** + * Submit a request to attest attributes about the owner of a reserve. + * + * @param ctx CURL context + * @param url exchange base URL + * @param keys exchange key data + * @param reserve_priv private key of the reserve to attest + * @param attributes_length length of the @a attributes array + * @param attributes array of names of attributes to get attestations for + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesAttestHandle * +TALER_EXCHANGE_reserves_attest ( + struct GNUNET_CURL_Context *ctx, + const char *url, + struct TALER_EXCHANGE_Keys *keys, + const struct TALER_ReservePrivateKeyP *reserve_priv, + unsigned int attributes_length, + const char *attributes[const static attributes_length], + TALER_EXCHANGE_ReservesPostAttestCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve attestation request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rah the reserve attest request handle + */ +void +TALER_EXCHANGE_reserves_attest_cancel ( + struct TALER_EXCHANGE_ReservesAttestHandle *rah); + + +/* ********************* /reserves/$RID/close *********************** */ + + +/** + * @brief A /reserves/$RID/close Handle + */ +struct TALER_EXCHANGE_ReservesCloseHandle; + + +/** + * @brief Reserve close result details. + */ +struct TALER_EXCHANGE_ReserveCloseResult +{ + + /** + * High-level HTTP response details. + */ + struct TALER_EXCHANGE_HttpResponse hr; + + /** + * Details depending on @e hr.http_status. + */ + union + { + + /** + * Information returned on success, if + * @e hr.http_status is #MHD_HTTP_OK + */ + struct + { + + /** + * Amount wired to the target account. + */ + struct TALER_Amount wire_amount; + } ok; + + /** + * Information returned if KYC is required to proceed, set if + * @e hr.http_status is #MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS. + */ + struct + { + /** + * Requirement row that the merchant should use + * to check for its KYC status. + */ + uint64_t requirement_row; + + /** + * Hash of the payto-URI of the account to KYC; + */ + struct TALER_PaytoHashP h_payto; + + } unavailable_for_legal_reasons; + + } details; + +}; + + +/** + * Callbacks of this type are used to serve the result of submitting a + * reserve close request to a exchange. + * + * @param cls closure + * @param ror HTTP response data + */ +typedef void +(*TALER_EXCHANGE_ReservesCloseCallback) ( + void *cls, + const struct TALER_EXCHANGE_ReserveCloseResult *ror); + + +/** + * Submit a request to close a reserve. + * + * @param ctx curl context + * @param url exchange base URL + * @param reserve_priv private key of the reserve to close + * @param target_payto_uri where to send the payment, NULL to send to reserve origin + * @param cb the callback to call when a reply for this request is available + * @param cb_cls closure for the above callback + * @return a handle for this request; NULL if the inputs are invalid (i.e. + * signatures fail to verify). In this case, the callback is not called. + */ +struct TALER_EXCHANGE_ReservesCloseHandle * +TALER_EXCHANGE_reserves_close ( + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct TALER_ReservePrivateKeyP *reserve_priv, + const char *target_payto_uri, + TALER_EXCHANGE_ReservesCloseCallback cb, + void *cb_cls); + + +/** + * Cancel a reserve status request. This function cannot be used + * on a request handle if a response is already served for it. + * + * @param rch the reserve request handle + */ +void +TALER_EXCHANGE_reserves_close_cancel ( + struct TALER_EXCHANGE_ReservesCloseHandle *rch); #endif /* _TALER_EXCHANGE_SERVICE_H */ diff --git a/src/include/taler_exchangedb_lib.h b/src/include/taler_exchangedb_lib.h index 33ead98bb..d93cf9d6c 100644 --- a/src/include/taler_exchangedb_lib.h +++ b/src/include/taler_exchangedb_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA + Copyright (C) 2014-2020 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 @@ -27,250 +27,6 @@ #include "taler_exchangedb_plugin.h" #include "taler_bank_service.h" -/** - * Subdirectroy under the exchange's base directory which contains - * the exchange's signing keys. - */ -#define TALER_EXCHANGEDB_DIR_SIGNING_KEYS "signkeys" - -/** - * Subdirectory under the exchange's base directory which contains - * the exchange's denomination keys. - */ -#define TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS "denomkeys" - - -/** - * @brief Iterator over signing keys. - * - * @param cls closure - * @param filename name of the file the key came from - * @param ski the sign key - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -typedef int -(*TALER_EXCHANGEDB_SigningKeyIterator)( - void *cls, - const char *filename, - const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski); - - -/** - * Call @a it for each signing key found in the @a exchange_base_dir. - * - * @param exchange_base_dir base directory for the exchange, - * the signing keys must be in the #TALER_EXCHANGEDB_DIR_SIGNING_KEYS - * subdirectory - * @param it function to call on each signing key - * @param it_cls closure for @a it - * @return number of files found (may not match - * number of keys given to @a it as malformed - * files are simply skipped), -1 on error - */ -int -TALER_EXCHANGEDB_signing_keys_iterate (const char *exchange_base_dir, - TALER_EXCHANGEDB_SigningKeyIterator it, - void *it_cls); - - -/** - * Exports a signing key to the given file. - * - * @param exchange_base_dir base directory for the keys - * @param start start time of the validity for the key - * @param ski the signing key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_EXCHANGEDB_signing_key_write ( - const char *exchange_base_dir, - struct GNUNET_TIME_Absolute start, - const struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP *ski); - - -/** - * @brief Iterator over denomination keys. - * - * @param cls closure - * @param alias coin alias - * @param dki the denomination key - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -typedef int -(*TALER_EXCHANGEDB_DenominationKeyIterator)( - void *cls, - const char *alias, - const struct TALER_EXCHANGEDB_DenominationKey *dki); - - -/** - * @brief Iterator over revoked denomination keys. - * - * @param cls closure - * @param denom_hash hash of the denomination public key - * @param revocation_master_sig signature showing @a denom_hash was revoked - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -typedef int -(*TALER_EXCHANGEDB_RevocationIterator)( - void *cls, - const struct GNUNET_HashCode *denom_hash, - const struct TALER_MasterSignatureP *revocation_master_sig); - - -/** - * Call @a it for each denomination key found in the @a exchange_base_dir. - * - * @param exchange_base_dir base directory for the exchange, - * the signing keys must be in the #TALER_EXCHANGEDB_DIR_DENOMINATION_KEYS - * subdirectory - * @param it function to call on each denomination key found - * @param it_cls closure for @a it - * @return -1 on error, 0 if no files were found, otherwise - * a positive number (however, even with a positive - * number it is possible that @a it was never called - * as maybe none of the files were well-formed) - */ -int -TALER_EXCHANGEDB_denomination_keys_iterate ( - const char *exchange_base_dir, - TALER_EXCHANGEDB_DenominationKeyIterator it, - void *it_cls); - - -/** - * Call @a it for each revoked denomination key found in the @a revocation_dir. - * - * @param revocation_dir base directory where revocations are stored - * @param master_pub master public key (used to check revocations) - * @param it function to call on each revoked denomination key found - * @param it_cls closure for @a it - * @return -1 on error, 0 if no files were found, otherwise - * a positive number (however, even with a positive - * number it is possible that @a it was never called - * as maybe none of the files were well-formed) - */ -int -TALER_EXCHANGEDB_revocations_iterate ( - const char *revocation_dir, - const struct TALER_MasterPublicKeyP *master_pub, - TALER_EXCHANGEDB_RevocationIterator it, - void *it_cls); - - -/** - * Mark the given denomination key as revoked and request the wallets - * to initiate recoup. - * - * @param revocation_dir where to write the revocation certificate - * @param denom_hash hash of the denomination key to revoke - * @param mpriv master private key to sign with - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_EXCHANGEDB_denomination_key_revoke ( - const char *revocation_dir, - const struct GNUNET_HashCode *denom_hash, - const struct TALER_MasterPrivateKeyP *mpriv); - - -/** - * Exports a denomination key to the given file. - * - * @param filename the file where to write the denomination key - * @param dki the denomination key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_EXCHANGEDB_denomination_key_write ( - const char *filename, - const struct TALER_EXCHANGEDB_DenominationKey *dki); - - -/** - * Import a denomination key from the given file. - * - * @param filename the file to import the key from - * @param[out] dki set to the imported denomination key - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure - */ -int -TALER_EXCHANGEDB_denomination_key_read ( - const char *filename, - struct TALER_EXCHANGEDB_DenominationKey *dki); - - -/** - * @brief Iterator over auditor information. - * - * @param cls closure - * @param apub the auditor's public key - * @param auditor_url URL of the auditor - * @param mpub the exchange's public key (as expected by the auditor) - * @param dki_len length of @a asig and @a dki arrays - * @param asigs array of the auditor's signatures over the @a dks, of length @a dki_len - * @param dki array of denomination coin data signed by the auditor, of length @a dki_len - * @return #GNUNET_OK to continue to iterate, - * #GNUNET_NO to stop iteration with no error, - * #GNUNET_SYSERR to abort iteration with error! - */ -typedef int -(*TALER_EXCHANGEDB_AuditorIterator)( - void *cls, - const struct TALER_AuditorPublicKeyP *apub, - const char *auditor_url, - const struct TALER_MasterPublicKeyP *mpub, - unsigned int dki_len, - const struct TALER_AuditorSignatureP *asigs, - const struct TALER_DenominationKeyValidityPS *dki); - - -/** - * Call @a it with information for each auditor found in the - * directory with auditor information as specified in @a cfg. - * - * @param cfg configuration to use - * @param it function to call with auditor information - * @param it_cls closure for @a it - * @return -1 on error, 0 if no files were found, otherwise - * a positive number (however, even with a positive - * number it is possible that @a it was never called - * as maybe none of the files were well-formed) - */ -int -TALER_EXCHANGEDB_auditor_iterate (const struct GNUNET_CONFIGURATION_Handle *cfg, - TALER_EXCHANGEDB_AuditorIterator it, - void *it_cls); - - -/** - * Write auditor information to the given file. - * - * @param filename the file where to write the auditor information to - * @param apub the auditor's public key - * @param auditor_url the URL of the auditor - * @param asigs the auditor's signatures, array of length @a dki_len - * @param mpub the exchange's public key (as expected by the auditor) - * @param dki_len length of @a dki and @a asigs arrays - * @param dki array of denomination coin data signed by the auditor - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure. - */ -int -TALER_EXCHANGEDB_auditor_write ( - const char *filename, - const struct TALER_AuditorPublicKeyP *apub, - const char *auditor_url, - const struct TALER_AuditorSignatureP *asigs, - const struct TALER_MasterPublicKeyP *mpub, - uint32_t dki_len, - const struct TALER_DenominationKeyValidityPS *dki); - /** * Initialize the plugin. @@ -290,99 +46,17 @@ TALER_EXCHANGEDB_plugin_load (const struct GNUNET_CONFIGURATION_Handle *cfg); void TALER_EXCHANGEDB_plugin_unload (struct TALER_EXCHANGEDB_Plugin *plugin); - /** - * Sorted list of fees to be paid for aggregate wire transfers. - * Sorted by @e start_date or @e end_date --- both work fine as - * the resulting order must be the same. + * Information about an account from the configuration. */ -struct TALER_EXCHANGEDB_AggregateFees +struct TALER_EXCHANGEDB_AccountInfo { /** - * This is a linked list. + * Authentication data. Only parsed if + * #TALER_EXCHANGEDB_ALO_AUTHDATA was set. */ - struct TALER_EXCHANGEDB_AggregateFees *next; - - /** - * Fee to be paid for wire transfers to a merchant. - */ - struct TALER_Amount wire_fee; - - /** - * Fee to be paid when we close a reserve and send funds back. - */ - struct TALER_Amount closing_fee; - - /** - * Time when this fee goes into effect (inclusive) - */ - struct GNUNET_TIME_Absolute start_date; - - /** - * Time when this fee stops being in effect (exclusive). - */ - struct GNUNET_TIME_Absolute end_date; - - /** - * Signature affirming the above fee structure. - */ - struct TALER_MasterSignatureP master_sig; -}; - - -/** - * Read the current fee structure from disk. - * - * @param cfg configuration to use - * @param wireplugin name of the wire plugin to read fees for - * @return sorted list of aggregation fees, NULL on error - */ -struct TALER_EXCHANGEDB_AggregateFees * -TALER_EXCHANGEDB_fees_read (const struct GNUNET_CONFIGURATION_Handle *cfg, - const char *wireplugin); - - -/** - * Convert @a af to @a wf. - * - * @param wiremethod name of the wire method the fees are for - * @param[in,out] af aggregate fees, host format (updated to round time) - * @param[out] wf aggregate fees, disk / signature format - */ -void -TALER_EXCHANGEDB_fees_2_wf (const char *wiremethod, - struct TALER_EXCHANGEDB_AggregateFees *af, - struct TALER_MasterWireFeePS *wf); - - -/** - * Write given fee structure to disk. - * - * @param filename where to write the fees - * @param wireplugin name of the plugin for which we write the fees - * @param af fee structure to write - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_EXCHANGEDB_fees_write (const char *filename, - const char *wireplugin, - struct TALER_EXCHANGEDB_AggregateFees *af); - - -/** - * Free @a af data structure - * - * @param af list to free - */ -void -TALER_EXCHANGEDB_fees_free (struct TALER_EXCHANGEDB_AggregateFees *af); + const struct TALER_BANK_AuthenticationData *auth; - -/** - * Information about an account from the configuration. - */ -struct TALER_EXCHANGEDB_AccountInfo -{ /** * Section in the configuration file that specifies the * account. Must start with "exchange-account-". @@ -395,57 +69,22 @@ struct TALER_EXCHANGEDB_AccountInfo const char *method; /** - * payto://-URL of the account. - */ - const char *payto_uri; - - /** - * Filename containing the signed /wire response, or NULL - * if not given. - */ - const char *wire_response_filename; - - /** - * #GNUNET_YES if this account is enabed to be debited + * true if this account is enabled to be debited * by the taler-exchange-aggregator. */ - int debit_enabled; + bool debit_enabled; /** - * #GNUNET_YES 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. */ - int credit_enabled; + bool credit_enabled; }; /** - * Function called with information about a wire account. - * - * @param cls closure - * @param ai account information - */ -typedef void -(*TALER_EXCHANGEDB_AccountCallback)( - void *cls, - const struct TALER_EXCHANGEDB_AccountInfo *ai); - -/** - * Parse the configuration to find account information. - * - * @param cfg configuration to use - * @param cb callback to invoke - * @param cb_cls closure for @a cb - */ -void -TALER_EXCHANGEDB_find_accounts (const struct GNUNET_CONFIGURATION_Handle *cfg, - TALER_EXCHANGEDB_AccountCallback cb, - void *cb_cls); - - -/** * Calculate the total value of all transactions performed. * Stores @a off plus the cost of all transactions in @a tl * in @a ret. @@ -455,69 +94,35 @@ TALER_EXCHANGEDB_find_accounts (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param[out] ret where the resulting total is to be stored * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors */ -int +enum GNUNET_GenericReturnValue TALER_EXCHANGEDB_calculate_transaction_list_totals ( struct TALER_EXCHANGEDB_TransactionList *tl, const struct TALER_Amount *off, struct TALER_Amount *ret); -/* ***************** convenience functions ******** */ - /** - * Information we keep for each supported account of the exchange. + * Function called with information about a wire account. + * + * @param cls closure + * @param ai account information */ -struct TALER_EXCHANGEDB_WireAccount -{ - /** - * Accounts are kept in a DLL. - */ - struct TALER_EXCHANGEDB_WireAccount *next; - - /** - * Plugins are kept in a DLL. - */ - struct TALER_EXCHANGEDB_WireAccount *prev; - - /** - * Authentication data. - */ - struct TALER_BANK_AuthenticationData auth; - - /** - * Wire transfer fee structure. - */ - struct TALER_EXCHANGEDB_AggregateFees *af; - - /** - * Name of the section that configures this account. - */ - char *section_name; - - /** - * Name of the wire method underlying the account. - */ - char *method; - -}; +typedef void +(*TALER_EXCHANGEDB_AccountCallback)( + void *cls, + const struct TALER_EXCHANGEDB_AccountInfo *ai); /** - * Update wire transfer fee data structure in @a wa. + * Return information about all accounts that + * were loaded by #TALER_EXCHANGEDB_load_accounts(). * - * @param cfg configuration to use - * @param db_plugin database plugin to use - * @param wa wire account data structure to update - * @param now timestamp to update fees to - * @param session DB session to use - * @return fee valid at @a now, or NULL if unknown + * @param cb callback to invoke + * @param cb_cls closure for @a cb */ -struct TALER_EXCHANGEDB_AggregateFees * -TALER_EXCHANGEDB_update_fees (const struct GNUNET_CONFIGURATION_Handle *cfg, - struct TALER_EXCHANGEDB_Plugin *db_plugin, - struct TALER_EXCHANGEDB_WireAccount *wa, - struct GNUNET_TIME_Absolute now, - struct TALER_EXCHANGEDB_Session *session); +void +TALER_EXCHANGEDB_find_accounts (TALER_EXCHANGEDB_AccountCallback cb, + void *cb_cls); /** @@ -528,7 +133,7 @@ TALER_EXCHANGEDB_update_fees (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param method wire method we need an account for * @return NULL on error */ -struct TALER_EXCHANGEDB_WireAccount * +const struct TALER_EXCHANGEDB_AccountInfo * TALER_EXCHANGEDB_find_account_by_method (const char *method); @@ -540,19 +145,48 @@ TALER_EXCHANGEDB_find_account_by_method (const char *method); * @param url wire address we need an account for * @return NULL on error */ -struct TALER_EXCHANGEDB_WireAccount * +const struct TALER_EXCHANGEDB_AccountInfo * TALER_EXCHANGEDB_find_account_by_payto_uri (const char *url); /** + * Options for #TALER_EXCHANGEDB_load_accounts() + */ +enum TALER_EXCHANGEDB_AccountLoaderOptions +{ + TALER_EXCHANGEDB_ALO_NONE = 0, + + /** + * Load accounts enabled for DEBITs. + */ + TALER_EXCHANGEDB_ALO_DEBIT = 1, + + /** + * Load accounts enabled for CREDITs. + */ + TALER_EXCHANGEDB_ALO_CREDIT = 2, + + /** + * Load authentication data from the + * "taler-accountcredentials-" section + * to access the account at the bank. + */ + TALER_EXCHANGEDB_ALO_AUTHDATA = 4 +}; + + +/** * Load account information opf the exchange from * @a cfg. * * @param cfg configuration to load from + * @param options loader options * @return #GNUNET_OK on success, #GNUNET_NO if no accounts are configured */ -int -TALER_EXCHANGEDB_load_accounts (const struct GNUNET_CONFIGURATION_Handle *cfg); +enum GNUNET_GenericReturnValue +TALER_EXCHANGEDB_load_accounts ( + const struct GNUNET_CONFIGURATION_Handle *cfg, + enum TALER_EXCHANGEDB_AccountLoaderOptions options); /** diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index 4fd580724..2d5857677 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2020 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -18,47 +18,89 @@ * @brief Low-level (statement-level) database access for the exchange * @author Florian Dold * @author Christian Grothoff + * @author Özgür Kesim */ #ifndef TALER_EXCHANGEDB_PLUGIN_H #define TALER_EXCHANGEDB_PLUGIN_H #include <jansson.h> #include <gnunet/gnunet_util_lib.h> #include <gnunet/gnunet_db_lib.h> +#include "taler_json_lib.h" #include "taler_signatures.h" +#include "taler_extensions_policy.h" +/** + * The conflict that can occur for the age restriction + */ +enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict +{ + /** + * Value OK, no conflict + */ + TALER_AgeCommitmentHash_NoConflict = 0, -GNUNET_NETWORK_STRUCT_BEGIN + /** + * Given hash had a value, but NULL (or zero) was expected + */ + TALER_AgeCommitmentHash_NullExpected = 1, + + /** + * Given hash was NULL, but value was expected + */ + TALER_AgeCommitmentHash_ValueExpected = 2, + + /** + * Given hash differs from value in the known coin + */ + TALER_AgeCommitmentHash_ValueDiffers = 3, +}; /** - * @brief On disk format used for a exchange signing key. Signing keys are used - * by the exchange to affirm its messages, but not to create coins. - * Includes the private key followed by the public information about - * the signing key. + * Per-coin information returned when doing a batch insert. */ -struct TALER_EXCHANGEDB_PrivateSigningKeyInformationP +struct TALER_EXCHANGEDB_CoinInfo { /** - * Private key part of the exchange's signing key. + * Row of the coin in the known_coins table. + */ + uint64_t known_coin_id; + + /** + * Hash of the denomination, relevant on @e denom_conflict. */ - struct TALER_ExchangePrivateKeyP signkey_priv; + struct TALER_DenominationHashP denom_hash; /** - * Signature over @e issue + * Hash of the age commitment, relevant on @e age_conflict. */ - struct TALER_MasterSignatureP master_sig; + struct TALER_AgeCommitmentHash h_age_commitment; /** - * Public information about a exchange signing key. + * True if the coin was known previously. */ - struct TALER_ExchangeSigningKeyValidityPS issue; + bool existed; + /** + * True if the known coin has a different denomination; + * application will find denomination of the already + * known coin in @e denom_hash. + */ + bool denom_conflict; + + /** + * Indicates if and what kind of conflict with the age + * restriction of the known coin was present; + * application will find age commitment of the already + * known coin in @e h_age_commitment. + */ + enum TALER_EXCHANGEDB_AgeCommitmentHash_Conflict age_conflict; }; /** * Information about a denomination key. */ -struct TALER_EXCHANGEDB_DenominationKeyInformationP +struct TALER_EXCHANGEDB_DenominationKeyInformation { /** @@ -67,14 +109,732 @@ struct TALER_EXCHANGEDB_DenominationKeyInformationP struct TALER_MasterSignatureP signature; /** - * Signed properties of the denomination key. + * Start time of the validity period for this key. + */ + struct GNUNET_TIME_Timestamp start; + + /** + * The exchange will sign fresh coins between @e start and this time. + * @e expire_withdraw will be somewhat larger than @e start to + * ensure a sufficiently large anonymity set, while also allowing + * the Exchange to limit the financial damage in case of a key being + * compromised. Thus, exchanges with low volume are expected to have a + * longer withdraw period (@e expire_withdraw - @e start) than exchanges + * with high transaction volume. The period may also differ between + * types of coins. A exchange may also have a few denomination keys + * with the same value with overlapping validity periods, to address + * issues such as clock skew. + */ + struct GNUNET_TIME_Timestamp expire_withdraw; + + /** + * Coins signed with the denomination key must be spent or refreshed + * between @e start and this expiration time. After this time, the + * exchange will refuse transactions involving this key as it will + * "drop" the table with double-spending information (shortly after) + * this time. Note that wallets should refresh coins significantly + * before this time to be on the safe side. @e expire_deposit must be + * significantly larger than @e expire_withdraw (by months or even + * years). + */ + struct GNUNET_TIME_Timestamp expire_deposit; + + /** + * When do signatures with this denomination key become invalid? + * After this point, these signatures cannot be used in (legal) + * disputes anymore, as the Exchange is then allowed to destroy its side + * of the evidence. @e expire_legal is expected to be significantly + * larger than @e expire_deposit (by a year or more). + */ + struct GNUNET_TIME_Timestamp expire_legal; + + /** + * The value of the coins signed with this denomination key. + */ + struct TALER_Amount value; + + /** + * Fees for the coin. + */ + struct TALER_DenomFeeSet fees; + + /** + * Hash code of the denomination public key. (Used to avoid having + * the variable-size RSA key in this struct.) + */ + struct TALER_DenominationHashP denom_hash; + + /** + * If denomination was setup for age restriction, non-zero age mask. + * Note that the mask is not part of the signature. + */ + struct TALER_AgeMask age_mask; +}; + + +GNUNET_NETWORK_STRUCT_BEGIN + +/** + * Events signalling that a coin deposit status + * changed. + */ +struct TALER_CoinDepositEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_DEPOSIT_STATUS_CHANGED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the merchant. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + +}; + +/** + * Events signalling a reserve got funding. + */ +struct TALER_ReserveEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_RESERVE_INCOMING. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the reserve the event is about. + */ + struct TALER_ReservePublicKeyP reserve_pub; +}; + + +/** + * Signature of events signalling a purse changed its status. + */ +struct TALER_PurseEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_PURSE_MERGED or + * #TALER_DBEVENT_EXCHANGE_PURSE_DEPOSITED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the purse the event is about. */ - struct TALER_DenominationKeyValidityPS properties; + struct TALER_PurseContractPublicKeyP purse_pub; +}; + + +/** + * Signature of events signalling a KYC process was completed. + */ +struct TALER_KycCompletedEventP +{ + /** + * Of type #TALER_DBEVENT_EXCHANGE_KYC_COMPLETED. + */ + struct GNUNET_DB_EventHeaderP header; + + /** + * Public key of the reserve the event is about. + */ + struct TALER_PaytoHashP h_payto; }; GNUNET_NETWORK_STRUCT_END +/** + * Meta data about an exchange online signing key. + */ +struct TALER_EXCHANGEDB_SignkeyMetaData +{ + /** + * Start time of the validity period for this key. + */ + struct GNUNET_TIME_Timestamp start; + + /** + * The exchange will sign messages with this key between @e start and this time. + */ + struct GNUNET_TIME_Timestamp expire_sign; + + /** + * When do signatures with this sign key become invalid? + * After this point, these signatures cannot be used in (legal) + * disputes anymore, as the Exchange is then allowed to destroy its side + * of the evidence. @e expire_legal is expected to be significantly + * larger than @e expire_sign (by a year or more). + */ + struct GNUNET_TIME_Timestamp expire_legal; + +}; + + +/** + * Enumeration of all of the tables replicated by exchange-auditor + * database replication. + */ +enum TALER_EXCHANGEDB_ReplicatedTable +{ + /* From exchange-0002.sql: */ + TALER_EXCHANGEDB_RT_DENOMINATIONS, + TALER_EXCHANGEDB_RT_DENOMINATION_REVOCATIONS, + TALER_EXCHANGEDB_RT_WIRE_TARGETS, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_PROCESSES, + TALER_EXCHANGEDB_RT_LEGITIMIZATION_REQUIREMENTS, + TALER_EXCHANGEDB_RT_RESERVES, + TALER_EXCHANGEDB_RT_RESERVES_IN, + TALER_EXCHANGEDB_RT_RESERVES_CLOSE, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_REQUESTS, + TALER_EXCHANGEDB_RT_RESERVES_OPEN_DEPOSITS, + TALER_EXCHANGEDB_RT_RESERVES_OUT, + TALER_EXCHANGEDB_RT_AUDITORS, + TALER_EXCHANGEDB_RT_AUDITOR_DENOM_SIGS, + TALER_EXCHANGEDB_RT_EXCHANGE_SIGN_KEYS, + TALER_EXCHANGEDB_RT_SIGNKEY_REVOCATIONS, + TALER_EXCHANGEDB_RT_KNOWN_COINS, + TALER_EXCHANGEDB_RT_REFRESH_COMMITMENTS, + TALER_EXCHANGEDB_RT_REFRESH_REVEALED_COINS, + TALER_EXCHANGEDB_RT_REFRESH_TRANSFER_KEYS, + TALER_EXCHANGEDB_RT_BATCH_DEPOSITS, + TALER_EXCHANGEDB_RT_COIN_DEPOSITS, + TALER_EXCHANGEDB_RT_REFUNDS, + TALER_EXCHANGEDB_RT_WIRE_OUT, + TALER_EXCHANGEDB_RT_AGGREGATION_TRACKING, + TALER_EXCHANGEDB_RT_WIRE_FEE, + TALER_EXCHANGEDB_RT_GLOBAL_FEE, + TALER_EXCHANGEDB_RT_RECOUP, + TALER_EXCHANGEDB_RT_RECOUP_REFRESH, + TALER_EXCHANGEDB_RT_EXTENSIONS, + TALER_EXCHANGEDB_RT_POLICY_DETAILS, + TALER_EXCHANGEDB_RT_POLICY_FULFILLMENTS, + TALER_EXCHANGEDB_RT_PURSE_REQUESTS, + TALER_EXCHANGEDB_RT_PURSE_DECISION, + TALER_EXCHANGEDB_RT_PURSE_MERGES, + TALER_EXCHANGEDB_RT_PURSE_DEPOSITS, + TALER_EXCHANGEDB_RT_ACCOUNT_MERGES, + TALER_EXCHANGEDB_RT_HISTORY_REQUESTS, + TALER_EXCHANGEDB_RT_CLOSE_REQUESTS, + TALER_EXCHANGEDB_RT_WADS_OUT, + TALER_EXCHANGEDB_RT_WADS_OUT_ENTRIES, + TALER_EXCHANGEDB_RT_WADS_IN, + TALER_EXCHANGEDB_RT_WADS_IN_ENTRIES, + TALER_EXCHANGEDB_RT_PROFIT_DRAINS, + /* From exchange-0003.sql: */ + TALER_EXCHANGEDB_RT_AML_STAFF, + TALER_EXCHANGEDB_RT_AML_HISTORY, + TALER_EXCHANGEDB_RT_KYC_ATTRIBUTES, + TALER_EXCHANGEDB_RT_PURSE_DELETION, + TALER_EXCHANGEDB_RT_AGE_WITHDRAW, +}; + + +/** + * Record of a single entry in a replicated table. + */ +struct TALER_EXCHANGEDB_TableData +{ + /** + * Data of which table is returned here? + */ + enum TALER_EXCHANGEDB_ReplicatedTable table; + + /** + * Serial number of the record. + */ + uint64_t serial; + + /** + * Table-specific details. + */ + union + { + + /** + * Details from the 'denominations' table. + */ + struct + { + uint32_t denom_type; + uint32_t age_mask; + struct TALER_DenominationPublicKey denom_pub; + struct TALER_MasterSignatureP master_sig; + struct GNUNET_TIME_Timestamp valid_from; + struct GNUNET_TIME_Timestamp expire_withdraw; + struct GNUNET_TIME_Timestamp expire_deposit; + struct GNUNET_TIME_Timestamp expire_legal; + struct TALER_Amount coin; + struct TALER_DenomFeeSet fees; + } denominations; + + struct + { + struct TALER_MasterSignatureP master_sig; + uint64_t denominations_serial; + } denomination_revocations; + + struct + { + char *payto_uri; + } wire_targets; + + struct + { + struct TALER_PaytoHashP h_payto; + struct GNUNET_TIME_Timestamp expiration_time; + char *provider_section; + char *provider_user_id; + char *provider_legitimization_id; + } legitimization_processes; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_ReservePublicKeyP reserve_pub; + bool no_reserve_pub; + char *required_checks; + } legitimization_requirements; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp expiration_date; + struct GNUNET_TIME_Timestamp gc_date; + } reserves; + + struct + { + uint64_t wire_reference; + struct TALER_Amount credit; + struct TALER_PaytoHashP sender_account_h_payto; + char *exchange_account_section; + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_ReservePublicKeyP reserve_pub; + } reserves_in; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp request_timestamp; + struct GNUNET_TIME_Timestamp expiration_date; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount reserve_payment; + uint32_t requested_purse_limit; + } reserves_open_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount contribution; + } reserves_open_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_WireTransferIdentifierRawP wtid; + struct TALER_PaytoHashP sender_account_h_payto; + struct TALER_Amount amount; + struct TALER_Amount closing_fee; + } reserves_close; + + struct + { + struct TALER_BlindedCoinHashP h_blind_ev; + uint64_t denominations_serial; + struct TALER_BlindedDenominationSignature denom_sig; + uint64_t reserve_uuid; + struct TALER_ReserveSignatureP reserve_sig; + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_Amount amount_with_fee; + } reserves_out; + + struct + { + struct TALER_AuditorPublicKeyP auditor_pub; + char *auditor_url; + char *auditor_name; + bool is_active; + struct GNUNET_TIME_Timestamp last_change; + } auditors; + + struct + { + uint64_t auditor_uuid; + uint64_t denominations_serial; + struct TALER_AuditorSignatureP auditor_sig; + } auditor_denom_sigs; + + struct + { + struct TALER_ExchangePublicKeyP exchange_pub; + struct TALER_MasterSignatureP master_sig; + struct TALER_EXCHANGEDB_SignkeyMetaData meta; + } exchange_sign_keys; + + struct + { + uint64_t esk_serial; + struct TALER_MasterSignatureP master_sig; + } signkey_revocations; + + struct + { + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_AgeCommitmentHash age_hash; + uint64_t denominations_serial; + struct TALER_DenominationSignature denom_sig; + } known_coins; + + struct + { + struct TALER_RefreshCommitmentP rc; + struct TALER_CoinSpendPublicKeyP old_coin_pub; + struct TALER_CoinSpendSignatureP old_coin_sig; + struct TALER_Amount amount_with_fee; + uint32_t noreveal_index; + } refresh_commitments; + + struct + { + uint64_t melt_serial_id; + uint32_t freshcoin_index; + struct TALER_CoinSpendSignatureP link_sig; + uint64_t denominations_serial; + void *coin_ev; + size_t coin_ev_size; + struct TALER_ExchangeWithdrawValues ewv; + // h_coin_ev omitted, to be recomputed! + struct TALER_BlindedDenominationSignature ev_sig; + } refresh_revealed_coins; + + struct + { + uint64_t melt_serial_id; + struct TALER_TransferPublicKeyP tp; + struct TALER_TransferPrivateKeyP tprivs[TALER_CNC_KAPPA - 1]; + } refresh_transfer_keys; + + struct + { + uint64_t shard; + 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_PrivateContractHashP h_contract_terms; + struct GNUNET_HashCode wallet_data_hash; + bool no_wallet_data_hash; + struct TALER_WireSaltP wire_salt; + struct TALER_PaytoHashP wire_target_h_payto; + bool policy_blocked; + uint64_t policy_details_serial_id; + bool no_policy_details; + } batch_deposits; + + struct + { + uint64_t batch_deposit_serial_id; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + struct TALER_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; + } refunds; + + struct + { + struct GNUNET_TIME_Timestamp execution_date; + struct TALER_WireTransferIdentifierRawP wtid_raw; + struct TALER_PaytoHashP wire_target_h_payto; + char *exchange_account_section; + struct TALER_Amount amount; + } wire_out; + + struct + { + uint64_t batch_deposit_serial_id; + struct TALER_WireTransferIdentifierRawP wtid_raw; + } aggregation_tracking; + + struct + { + char *wire_method; + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_WireFeeSet fees; + struct TALER_MasterSignatureP master_sig; + } wire_fee; + + struct + { + struct GNUNET_TIME_Timestamp start_date; + struct GNUNET_TIME_Timestamp end_date; + struct TALER_GlobalFeeSet fees; + struct GNUNET_TIME_Relative purse_timeout; + struct GNUNET_TIME_Relative history_expiration; + uint32_t purse_account_limit; + struct TALER_MasterSignatureP master_sig; + } global_fee; + + struct + { + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp timestamp; + uint64_t reserve_out_serial_id; + } recoup; + + struct + { + uint64_t known_coin_id; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_CoinSpendSignatureP coin_sig; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp timestamp; + uint64_t rrc_serial; + } recoup_refresh; + + struct + { + char *name; + char *manifest; + } extensions; + + struct + { + struct GNUNET_HashCode hash_code; + json_t *policy_json; + bool no_policy_json; + struct GNUNET_TIME_Timestamp deadline; + struct TALER_Amount commitment; + struct TALER_Amount accumulated_total; + struct TALER_Amount fee; + struct TALER_Amount transferable; + uint16_t fulfillment_state; /* will also be recomputed */ + uint64_t fulfillment_id; + bool no_fulfillment_id; + } policy_details; + + struct + { + struct GNUNET_TIME_Timestamp fulfillment_timestamp; + char *fulfillment_proof; + struct GNUNET_HashCode h_fulfillment_proof; + struct GNUNET_HashCode *policy_hash_codes; + size_t policy_hash_codes_count; + } policy_fulfillments; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergePublicKeyP merge_pub; + struct GNUNET_TIME_Timestamp purse_creation; + struct GNUNET_TIME_Timestamp purse_expiration; + struct TALER_PrivateContractHashP h_contract_terms; + uint32_t age_limit; + uint32_t flags; + struct TALER_Amount amount_with_fee; + struct TALER_Amount purse_fee; + struct TALER_PurseContractSignatureP purse_sig; + } purse_requests; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct GNUNET_TIME_Timestamp action_timestamp; + bool refunded; + } purse_decision; + + struct + { + uint64_t partner_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseMergeSignatureP merge_sig; + struct GNUNET_TIME_Timestamp merge_timestamp; + } purse_merges; + + struct + { + uint64_t partner_serial_id; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_Amount amount_with_fee; + struct TALER_CoinSpendSignatureP coin_sig; + } purse_deposits; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PaytoHashP wallet_h_payto; + } account_merges; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + struct GNUNET_TIME_Timestamp request_timestamp; + struct TALER_Amount history_fee; + } history_requests; + + struct + { + struct TALER_ReservePublicKeyP reserve_pub; + struct GNUNET_TIME_Timestamp close_timestamp; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_Amount close; + struct TALER_Amount close_fee; + char *payto_uri; + } close_requests; + + struct + { + struct TALER_WadIdentifierP wad_id; + uint64_t partner_serial_id; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp execution_time; + } wads_out; + + struct + { + uint64_t wad_out_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_out_entries; + + struct + { + struct TALER_WadIdentifierP wad_id; + char *origin_exchange_url; + struct TALER_Amount amount; + struct GNUNET_TIME_Timestamp arrival_time; + } wads_in; + + struct + { + uint64_t wad_in_serial_id; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PrivateContractHashP h_contract; + struct GNUNET_TIME_Timestamp purse_expiration; + struct GNUNET_TIME_Timestamp merge_timestamp; + struct TALER_Amount amount_with_fee; + struct TALER_Amount wad_fee; + struct TALER_Amount deposit_fees; + struct TALER_ReserveSignatureP reserve_sig; + struct TALER_PurseContractSignatureP purse_sig; + } wads_in_entries; + + struct + { + struct TALER_WireTransferIdentifierRawP wtid; + char *account_section; + char *payto_uri; + struct GNUNET_TIME_Timestamp trigger_date; + struct TALER_Amount amount; + struct TALER_MasterSignatureP master_sig; + } profit_drains; + + struct + { + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_MasterSignatureP master_sig; + char *decider_name; + bool is_active; + bool read_only; + struct GNUNET_TIME_Timestamp last_change; + } aml_staff; + + struct + { + struct TALER_PaytoHashP h_payto; + struct TALER_Amount new_threshold; + enum TALER_AmlDecisionState new_status; + struct GNUNET_TIME_Timestamp decision_time; + char *justification; + char *kyc_requirements; /* NULL allowed! */ + uint64_t kyc_req_row; + struct TALER_AmlOfficerPublicKeyP decider_pub; + struct TALER_AmlOfficerSignatureP decider_sig; + } aml_history; + + struct + { + struct TALER_PaytoHashP h_payto; + struct GNUNET_ShortHashCode kyc_prox; + char *provider; + struct GNUNET_TIME_Timestamp collection_time; + struct GNUNET_TIME_Timestamp expiration_time; + void *encrypted_attributes; + size_t encrypted_attributes_size; + } kyc_attributes; + + struct + { + struct TALER_PurseContractPublicKeyP purse_pub; + struct TALER_PurseContractSignatureP purse_sig; + } purse_deletion; + + struct + { + struct TALER_AgeWithdrawCommitmentHashP h_commitment; + struct TALER_Amount amount_with_fee; + uint16_t max_age; + uint32_t noreveal_index; + struct TALER_ReservePublicKeyP reserve_pub; + struct TALER_ReserveSignatureP reserve_sig; + uint64_t num_coins; + uint64_t *denominations_serials; + void *h_blind_evs; + struct TALER_BlindedDenominationSignature denom_sigs; + } age_withdraw; + + } details; + +}; + + +/** + * Function called on data to replicate in the auditor's database. + * + * @param cls closure + * @param td record from an exchange table + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_SYSERR to fail with an error + */ +typedef int +(*TALER_EXCHANGEDB_ReplicationCallback)( + void *cls, + const struct TALER_EXCHANGEDB_TableData *td); + /** * @brief All information about a denomination key (which is used to @@ -98,7 +858,7 @@ struct TALER_EXCHANGEDB_DenominationKey /** * Signed public information about a denomination key. */ - struct TALER_EXCHANGEDB_DenominationKeyInformationP issue; + struct TALER_EXCHANGEDB_DenominationKeyInformation issue; }; @@ -123,7 +883,7 @@ struct TALER_EXCHANGEDB_BankTransfer * (This is the execution date of the exchange's database, * the execution date of the bank should be in @e wire). */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Detailed wire information about the sending account @@ -134,12 +894,7 @@ struct TALER_EXCHANGEDB_BankTransfer /** * Data uniquely identifying the wire transfer (wire transfer-type specific) */ - void *wire_reference; - - /** - * Number of bytes in @e wire_reference. - */ - size_t wire_reference_size; + uint64_t wire_reference; }; @@ -157,7 +912,7 @@ struct TALER_EXCHANGEDB_ClosingTransfer struct TALER_ReservePublicKeyP reserve_pub; /** - * Amount that was transferred to the exchange. + * Amount that was transferred from the exchange. */ struct TALER_Amount amount; @@ -169,7 +924,7 @@ struct TALER_EXCHANGEDB_ClosingTransfer /** * When did the exchange execute the transaction? */ - struct GNUNET_TIME_Absolute execution_date; + struct GNUNET_TIME_Timestamp execution_date; /** * Detailed wire information about the receiving account @@ -205,17 +960,203 @@ struct TALER_EXCHANGEDB_Reserve * The expiration date of this reserve; funds will be wired back * at this time. */ - struct GNUNET_TIME_Absolute expiry; + struct GNUNET_TIME_Timestamp expiry; /** * The legal expiration date of this reserve; we will forget about * it at this time. */ - struct GNUNET_TIME_Absolute gc; + struct GNUNET_TIME_Timestamp gc; +}; + + +/** + * Meta data about a denomination public key. + */ +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; + + /** + * The exchange will sign fresh coins between @e start and this time. + * @e expire_withdraw will be somewhat larger than @e start to + * ensure a sufficiently large anonymity set, while also allowing + * the Exchange to limit the financial damage in case of a key being + * compromised. Thus, exchanges with low volume are expected to have a + * longer withdraw period (@e expire_withdraw - @e start) than exchanges + * with high transaction volume. The period may also differ between + * types of coins. A exchange may also have a few denomination keys + * with the same value with overlapping validity periods, to address + * issues such as clock skew. + */ + struct GNUNET_TIME_Timestamp expire_withdraw; + + /** + * Coins signed with the denomination key must be spent or refreshed + * between @e start and this expiration time. After this time, the + * exchange will refuse transactions involving this key as it will + * "drop" the table with double-spending information (shortly after) + * this time. Note that wallets should refresh coins significantly + * before this time to be on the safe side. @e expire_deposit must be + * significantly larger than @e expire_withdraw (by months or even + * years). + */ + struct GNUNET_TIME_Timestamp expire_deposit; + + /** + * When do signatures with this denomination key become invalid? + * After this point, these signatures cannot be used in (legal) + * disputes anymore, as the Exchange is then allowed to destroy its side + * of the evidence. @e expire_legal is expected to be significantly + * larger than @e expire_deposit (by a year or more). + */ + struct GNUNET_TIME_Timestamp expire_legal; + + /** + * The value of the coins signed with this denomination key. + */ + struct TALER_Amount value; + + /** + * The fees the exchange charges for operations with + * coins of this denomination. + */ + struct TALER_DenomFeeSet fees; + + /** + * Age restriction for the denomination. (can be zero). If not zero, the bits + * set in the mask mark the edges at the beginning of a next age group. F.e. + * for the age groups + * 0-7, 8-9, 10-11, 12-14, 14-15, 16-17, 18-21, 21-* + * the following bits are set: + * + * 31 24 16 8 0 + * | | | | | + * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + * + * A value of 0 means that the denomination does not support the extension for + * age-restriction. + */ + struct TALER_AgeMask age_mask; }; /** + * Signature of a function called with information about the exchange's + * denomination keys. + * + * @param cls closure with a `struct TEH_KeyStateHandle *` + * @param denom_pub public key of the denomination + * @param h_denom_pub hash of @a denom_pub + * @param meta meta data information about the denomination type (value, expirations, fees) + * @param master_sig master signature affirming the validity of this denomination + * @param recoup_possible true if the key was revoked and clients can currently recoup + * coins of this denomination + */ +typedef void +(*TALER_EXCHANGEDB_DenominationsCallback)( + void *cls, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig, + bool recoup_possible); + + +/** + * Signature of a function called with information about the exchange's + * online signing keys. + * + * @param cls closure with a `struct TEH_KeyStateHandle *` + * @param exchange_pub public key of the exchange + * @param meta meta data information about the signing type (expirations) + * @param master_sig master signature affirming the validity of this denomination + */ +typedef void +(*TALER_EXCHANGEDB_ActiveSignkeysCallback)( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_EXCHANGEDB_SignkeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Function called on all KYC process names that the given + * account has already passed. + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + */ +typedef void +(*TALER_EXCHANGEDB_SatisfiedProviderCallback)( + void *cls, + const char *kyc_provider_section_name); + + +/** + * Function called on all legitimization operations + * we have performed for the given account so far + * (and that have not yet expired). + * + * @param cls closure + * @param kyc_provider_section_name configuration section + * of the respective KYC process + * @param provider_user_id UID at a provider (can be NULL) + * @param legi_id legitimization process ID (can be NULL) + */ +typedef void +(*TALER_EXCHANGEDB_LegitimizationProcessCallback)( + void *cls, + const char *kyc_provider_section_name, + const char *provider_user_id, + const char *legi_id); + + +/** + * Function called with information about the exchange's auditors. + * + * @param cls closure with a `struct TEH_KeyStateHandle *` + * @param auditor_pub the public key of the auditor + * @param auditor_url URL of the REST API of the auditor + * @param auditor_name human readable official name of the auditor + */ +typedef void +(*TALER_EXCHANGEDB_AuditorsCallback)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const char *auditor_url, + const char *auditor_name); + + +/** + * Function called with information about the denominations + * audited by the exchange's auditors. + * + * @param cls closure with a `struct TEH_KeyStateHandle *` + * @param auditor_pub the public key of an auditor + * @param h_denom_pub hash of a denomination key audited by this auditor + * @param auditor_sig signature from the auditor affirming this + */ +typedef void +(*TALER_EXCHANGEDB_AuditorDenominationsCallback)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorSignatureP *auditor_sig); + + +/** * @brief Information we keep for a withdrawn coin to reproduce * the /withdraw operation if needed, and to have proof * that a reserve was drained by this amount. @@ -224,14 +1165,14 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin { /** - * Our signature over the (blinded) coin. + * Our (blinded) signature over the (blinded) coin. */ - struct TALER_DenominationSignature sig; + struct TALER_BlindedDenominationSignature sig; /** * Hash of the denomination key (which coin was generated). */ - struct GNUNET_HashCode denom_pub_hash; + struct TALER_DenominationHashP denom_pub_hash; /** * Value of the coin being exchangeed (matching the denomination key) @@ -264,7 +1205,7 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin * Hash over the blinded message, needed to verify * the @e reserve_sig. */ - struct GNUNET_HashCode h_coin_envelope; + struct TALER_BlindedCoinHashP h_coin_envelope; /** * Signature confirming the withdrawal, matching @e reserve_pub, @@ -275,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. */ @@ -290,7 +1304,7 @@ struct TALER_EXCHANGEDB_Recoup * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - struct TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -311,8 +1325,25 @@ struct TALER_EXCHANGEDB_Recoup /** * When did the recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; + +}; + +/** + * Public key to which a nonce is locked. + */ +union TALER_EXCHANGEDB_NonceLockTargetP +{ + /** + * Nonce is locked to this coin key. + */ + struct TALER_CoinSpendPublicKeyP coin; + + /** + * Nonce is locked to this reserve key. + */ + struct TALER_ReservePublicKeyP reserve; }; @@ -327,7 +1358,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry * Blinding factor supplied to prove to the exchange that * the coin came from this reserve. */ - struct TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -336,6 +1367,11 @@ struct TALER_EXCHANGEDB_RecoupListEntry struct TALER_CoinSpendSignatureP coin_sig; /** + * Hash of the public denomination key used to sign the coin. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** * Public key of the reserve the coin was paid back into. */ struct TALER_ReservePublicKeyP reserve_pub; @@ -348,7 +1384,7 @@ struct TALER_EXCHANGEDB_RecoupListEntry /** * When did the /recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; }; @@ -368,9 +1404,9 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry /** * Blinding factor supplied to prove to the exchange that - * the coin came from this reserve. + * the coin came from this @e old_coin_pub. */ - struct TALER_DenominationBlindingKeyP coin_blind; + union GNUNET_CRYPTO_BlindingSecretP coin_blind; /** * Signature of the coin of type @@ -391,7 +1427,174 @@ struct TALER_EXCHANGEDB_RecoupRefreshListEntry /** * When did the recoup operation happen? */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; + +}; + + +/** + * Details about a purse merge operation. + */ +struct TALER_EXCHANGEDB_PurseMerge +{ + + /** + * Public key of the reserve the coin was merged into. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Amount in the purse, with fees. + */ + struct TALER_Amount amount_with_fee; + + /** + * Fee paid for the purse. + */ + struct TALER_Amount purse_fee; + + /** + * Hash over the contract. + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Merge capability key. + */ + struct TALER_PurseMergePublicKeyP merge_pub; + + /** + * Purse public key. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Signature by the reserve approving the merge. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * When was the merge made. + */ + struct GNUNET_TIME_Timestamp merge_timestamp; + + /** + * When was the purse set to expire. + */ + struct GNUNET_TIME_Timestamp purse_expiration; + + /** + * Minimum age required for depositing into the purse. + */ + uint32_t min_age; + + /** + * Flags of the purse. + */ + enum TALER_WalletAccountMergeFlags flags; + + /** + * true if the purse was actually successfully merged, + * false if the @e purse_fee was charged but the + * @e amount was not credited to the reserve. + */ + bool merged; +}; + + +/** + * Details about a (paid for) reserve history request. + */ +struct TALER_EXCHANGEDB_HistoryRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request. + */ + struct TALER_Amount history_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; +}; + + +/** + * Details about a (paid for) reserve open request. + */ +struct TALER_EXCHANGEDB_OpenRequest +{ + /** + * Public key of the reserve the open request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * Fee paid for the request from the reserve. + */ + struct TALER_Amount open_fee; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * How long was the reserve supposed to be open. + */ + struct GNUNET_TIME_Timestamp reserve_expiration; + + /** + * Signature by the reserve approving the open request, + * with purpose #TALER_SIGNATURE_WALLET_RESERVE_OPEN. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * How many open purses should be included with the + * open reserve? + */ + uint32_t purse_limit; + +}; + + +/** + * Details about an (explicit) reserve close request. + */ +struct TALER_EXCHANGEDB_CloseRequest +{ + /** + * Public key of the reserve the history request was for. + */ + struct TALER_ReservePublicKeyP reserve_pub; + + /** + * When was the request made. + */ + struct GNUNET_TIME_Timestamp request_timestamp; + + /** + * Hash of the payto://-URI of the target account + * for the closure, or all zeros for the reserve + * origin account. + */ + struct TALER_PaytoHashP target_account_h_payto; + + /** + * Signature by the reserve approving the history request. + */ + struct TALER_ReserveSignatureP reserve_sig; }; @@ -422,7 +1625,27 @@ enum TALER_EXCHANGEDB_ReserveOperation * customer's bank account. This happens when the exchange * closes a reserve with a non-zero amount left in it. */ - TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3 + TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK = 3, + + /** + * Event where a purse was merged into a reserve. + */ + TALER_EXCHANGEDB_RO_PURSE_MERGE = 4, + + /** + * Event where a wallet paid for a full reserve history. + */ + TALER_EXCHANGEDB_RO_HISTORY_REQUEST = 5, + + /** + * Event where a wallet paid to open a reserve for longer. + */ + TALER_EXCHANGEDB_RO_OPEN_REQUEST = 6, + + /** + * Event where a wallet requested a reserve to be closed. + */ + TALER_EXCHANGEDB_RO_CLOSE_REQUEST = 7 }; @@ -473,12 +1696,156 @@ struct TALER_EXCHANGEDB_ReserveHistory */ struct TALER_EXCHANGEDB_ClosingTransfer *closing; + /** + * Details about a purse merge operation. + */ + struct TALER_EXCHANGEDB_PurseMerge *merge; + + /** + * Details about a (paid for) reserve history request. + */ + struct TALER_EXCHANGEDB_HistoryRequest *history; + + /** + * Details about a (paid for) open reserve request. + */ + struct TALER_EXCHANGEDB_OpenRequest *open_request; + + /** + * Details about an (explicit) reserve close request. + */ + struct TALER_EXCHANGEDB_CloseRequest *close_request; + } details; }; /** + * @brief Data about a coin for a deposit operation. + */ +struct TALER_EXCHANGEDB_CoinDepositInformation +{ + /** + * Information about the coin that is being deposited. + */ + struct TALER_CoinPublicInfo coin; + + /** + * ECDSA signature affirming that the customer intends + * this coin to be deposited at the merchant identified + * by @e h_wire in relation to the proposal data identified + * by @e h_contract_terms. + */ + struct TALER_CoinSpendSignatureP csig; + + /** + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount amount_with_fee; + +}; + + +/** + * @brief Data from a batch deposit operation. + */ +struct TALER_EXCHANGEDB_BatchDeposit +{ + + /** + * Public key of the merchant. Enables later identification + * of the merchant in case of a need to rollback transactions. + */ + struct TALER_MerchantPublicKeyP merchant_pub; + + /** + * Hash over the proposal data between merchant and customer + * (remains unknown to the Exchange). + */ + struct TALER_PrivateContractHashP h_contract_terms; + + /** + * Hash over additional inputs by the wallet. + */ + struct GNUNET_HashCode wallet_data_hash; + + /** + * Unsalted hash over @e receiver_wire_account. + */ + struct TALER_PaytoHashP wire_target_h_payto; + + /** + * Salt used by the merchant to compute "h_wire". + */ + struct TALER_WireSaltP wire_salt; + + /** + * Time when this request was generated. Used, for example, to + * assess when (roughly) the income was achieved for tax purposes. + * Note that the Exchange will only check that the timestamp is not "too + * far" into the future (i.e. several days). The fact that the + * timestamp falls within the validity period of the coin's + * denomination key is irrelevant for the validity of the deposit + * request, as obviously the customer and merchant could conspire to + * set any timestamp. Also, the Exchange must accept very old deposit + * requests, as the merchant might have been unable to transmit the + * deposit request in a timely fashion (so back-dating is not + * prevented). + */ + struct GNUNET_TIME_Timestamp wallet_timestamp; + + /** + * How much time does the merchant have to issue a refund request? + * Zero if refunds are not allowed. After this time, the coin + * cannot be refunded. + */ + struct GNUNET_TIME_Timestamp refund_deadline; + + /** + * How much time does the merchant have to execute the wire transfer? + * This time is advisory for aggregating transactions, not a hard + * constraint (as the merchant can theoretically pick any time, + * including one in the past). + */ + struct GNUNET_TIME_Timestamp wire_deadline; + + /** + * Row ID of the policy details; 0 if no policy applies. + */ + uint64_t policy_details_serial_id; + + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + const char *receiver_wire_account; + + /** + * Array about the coins that are being deposited. + */ + const struct TALER_EXCHANGEDB_CoinDepositInformation *cdis; + + /** + * Length of the @e cdis array. + */ + unsigned int num_cdis; + + /** + * False if @e wallet_data_hash was provided + */ + bool no_wallet_data_hash; + + /** + * True if further processing is blocked by policy. + */ + bool policy_blocked; + +}; + + +/** * @brief Data from a deposit operation. The combination of * the coin's public key, the merchant's public key and the * transaction ID must be unique. While a coin can (theoretically) be @@ -510,24 +1877,26 @@ struct TALER_EXCHANGEDB_Deposit struct TALER_MerchantPublicKeyP merchant_pub; /** - * Hash over the proposa data between merchant and customer + * Hash over the proposal data between merchant and customer * (remains unknown to the Exchange). */ - struct GNUNET_HashCode h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** - * Hash of the (canonical) representation of @e wire, used - * to check the signature on the request. Generated by - * the exchange from the detailed wire data provided by the - * merchant. + * Salt used by the merchant to compute "h_wire". */ - struct GNUNET_HashCode h_wire; + struct TALER_WireSaltP wire_salt; /** - * Detailed information about the receiver for executing the transaction. - * Includes URL in payto://-format and salt. + * Hash over inputs from the wallet to customize the contract. + */ + 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 */ - json_t *receiver_wire_account; + struct TALER_ExtensionPolicyHashP h_policy; /** * Time when this request was generated. Used, for example, to @@ -542,14 +1911,14 @@ struct TALER_EXCHANGEDB_Deposit * deposit request in a timely fashion (so back-dating is not * prevented). */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * How much time does the merchant have to issue a refund request? * Zero if refunds are not allowed. After this time, the coin * cannot be refunded. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct GNUNET_TIME_Timestamp refund_deadline; /** * How much time does the merchant have to execute the wire transfer? @@ -557,7 +1926,7 @@ struct TALER_EXCHANGEDB_Deposit * constraint (as the merchant can theoretically pick any time, * including one in the past). */ - struct GNUNET_TIME_Absolute wire_deadline; + struct GNUNET_TIME_Timestamp wire_deadline; /** * Fraction of the coin's remaining value to be deposited, including @@ -570,6 +1939,22 @@ struct TALER_EXCHANGEDB_Deposit */ struct TALER_Amount deposit_fee; + /** + * Information about the receiver for executing the transaction. URI in + * payto://-format. + */ + char *receiver_wire_account; + + /** + * True if @e policy_json was provided + */ + bool has_policy; + + /** + * True if @e wallet_data_hash is not in use. + */ + bool no_wallet_data_hash; + }; @@ -598,21 +1983,45 @@ struct TALER_EXCHANGEDB_DepositListEntry * Hash over the proposa data between merchant and customer * (remains unknown to the Exchange). */ - struct GNUNET_HashCode h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** - * Hash of the (canonical) representation of @e wire, used - * to check the signature on the request. Generated by - * the exchange from the detailed wire data provided by the - * merchant. + * Hash over inputs from the wallet to customize the contract. */ - struct GNUNET_HashCode h_wire; + struct GNUNET_HashCode wallet_data_hash; /** - * Detailed information about the receiver for executing the transaction. - * Includes URL in payto://-format and salt. + * Hash of the public denomination key used to sign the coin. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Age commitment hash, if applicable to the denomination. Should be all + * zeroes if age commitment is not applicable to the denonimation. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Salt used to compute h_wire from the @e receiver_wire_account. + */ + struct TALER_WireSaltP wire_salt; + + /** + * Hash over the policy data for this deposit (remains unknown to the + * Exchange). Needed for the verification of the deposit's signature + */ + struct TALER_ExtensionPolicyHashP h_policy; + + /** + * Fraction of the coin's remaining value to be deposited, including + * depositing fee (if any). The coin is identified by @e coin_pub. */ - json_t *receiver_wire_account; + struct TALER_Amount amount_with_fee; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; /** * Time when this request was generated. Used, for example, to @@ -627,14 +2036,14 @@ struct TALER_EXCHANGEDB_DepositListEntry * deposit request in a timely fashion (so back-dating is not * prevented). */ - struct GNUNET_TIME_Absolute timestamp; + struct GNUNET_TIME_Timestamp timestamp; /** * How much time does the merchant have to issue a refund request? * Zero if refunds are not allowed. After this time, the coin * cannot be refunded. */ - struct GNUNET_TIME_Absolute refund_deadline; + struct GNUNET_TIME_Timestamp refund_deadline; /** * How much time does the merchant have to execute the wire transfer? @@ -642,18 +2051,33 @@ struct TALER_EXCHANGEDB_DepositListEntry * constraint (as the merchant can theoretically pick any time, * including one in the past). */ - struct GNUNET_TIME_Absolute wire_deadline; + struct GNUNET_TIME_Timestamp wire_deadline; /** - * Fraction of the coin's remaining value to be deposited, including - * depositing fee (if any). The coin is identified by @e coin_pub. + * Detailed information about the receiver for executing the transaction. + * URL in payto://-format. */ - struct TALER_Amount amount_with_fee; + char *receiver_wire_account; /** - * Depositing fee. + * true, if age commitment is not applicable */ - struct TALER_Amount deposit_fee; + bool no_age_commitment; + + /** + * true, if wallet data hash is not present + */ + bool no_wallet_data_hash; + + /** + * True if a policy was provided with the deposit request + */ + bool has_policy; + + /** + * Has the deposit been wired? + */ + bool done; }; @@ -678,7 +2102,7 @@ struct TALER_EXCHANGEDB_RefundListEntry * Hash over the proposal data between merchant and customer * (remains unknown to the Exchange). */ - struct GNUNET_HashCode h_contract_terms; + struct TALER_PrivateContractHashP h_contract_terms; /** * Merchant-generated REFUND transaction ID to detect duplicate @@ -782,6 +2206,23 @@ struct TALER_EXCHANGEDB_MeltListEntry struct TALER_RefreshCommitmentP rc; /** + * Hash of the public denomination key used to sign the coin. + */ + struct TALER_DenominationHashP h_denom_pub; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. May be all zeroes if no age restriction + * applies. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * true, if no h_age_commitment is applicable + */ + bool no_age_commitment; + + /** * How much value is being melted? This amount includes the fees, * so the final amount contributed to the melt is this value minus * the fee for melting the coin. We include the fee in what is @@ -806,6 +2247,158 @@ struct TALER_EXCHANGEDB_MeltListEntry /** + * Information about a /purses/$PID/deposit operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_PurseDepositListEntry +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if the coin was refunded. + */ + bool refunded; + + /** + * Set to true if there was no age commitment. + */ + bool no_age_commitment; + +}; + + +/** + * @brief Specification for a purse refund operation in a coin's transaction list. + */ +struct TALER_EXCHANGEDB_PurseRefundListEntry +{ + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Fraction of the original deposit's value to be refunded, including + * refund fee (if any). The coin is identified by @e coin_pub. + */ + struct TALER_Amount refund_amount; + + /** + * Refund fee to be covered by the customer. + */ + struct TALER_Amount refund_fee; + +}; + + +/** + * Information about a /reserves/$RID/open operation in a coin transaction history. + */ +struct TALER_EXCHANGEDB_ReserveOpenListEntry +{ + + /** + * Signature of the reserve. + */ + struct TALER_ReserveSignatureP reserve_sig; + + /** + * Contribution of the coin to the open fee, including + * deposit fee. + */ + struct TALER_Amount coin_contribution; + + /** + * Signature by the coin affirming the open deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + +}; + + +/** + * Information about a /purses/$PID/deposit operation. + */ +struct TALER_EXCHANGEDB_PurseDeposit +{ + + /** + * Exchange hosting the purse, NULL for this exchange. + */ + char *exchange_base_url; + + /** + * Public key of the purse. + */ + struct TALER_PurseContractPublicKeyP purse_pub; + + /** + * Contribution of the coin to the purse, including + * deposit fee. + */ + struct TALER_Amount amount; + + /** + * Depositing fee. + */ + struct TALER_Amount deposit_fee; + + /** + * Signature by the coin affirming the deposit. + */ + struct TALER_CoinSpendSignatureP coin_sig; + + /** + * Public key of the coin. + */ + struct TALER_CoinSpendPublicKeyP coin_pub; + + /** + * Hash of the age commitment used to sign the coin, if age restriction was + * applicable to the denomination. May be all zeroes if no age restriction + * applies. + */ + struct TALER_AgeCommitmentHash h_age_commitment; + + /** + * Set to true if @e h_age_commitment is not available. + */ + bool no_age_commitment; + +}; + +/** * Information about a melt operation. */ struct TALER_EXCHANGEDB_Melt @@ -842,13 +2435,34 @@ struct TALER_EXCHANGEDB_LinkList /** * Signature over the blinded envelope. */ - struct TALER_DenominationSignature ev_sig; + struct TALER_BlindedDenominationSignature ev_sig; + + /** + * Exchange-provided values during the coin generation. + */ + struct TALER_ExchangeWithdrawValues alg_values; /** * Signature of the original coin being refreshed over the * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK */ struct TALER_CoinSpendSignatureP orig_coin_link_sig; + + /** + * Session nonce, if cipher has one. + */ + union GNUNET_CRYPTO_BlindSessionNonce nonce; + + /** + * Offset that generated this coin in the refresh + * operation. + */ + uint32_t coin_refresh_offset; + + /** + * Set to true if @e nonce was initialized. + */ + bool have_nonce; }; @@ -887,7 +2501,22 @@ enum TALER_EXCHANGEDB_TransactionType /** * Recoup-refresh operation (on the new coin, eliminating its value) */ - TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5 + TALER_EXCHANGEDB_TT_RECOUP_REFRESH = 5, + + /** + * Purse deposit operation. + */ + TALER_EXCHANGEDB_TT_PURSE_DEPOSIT = 6, + + /** + * Purse deposit operation. + */ + TALER_EXCHANGEDB_TT_PURSE_REFUND = 7, + + /** + * Reserve open deposit operation. + */ + TALER_EXCHANGEDB_TT_RESERVE_OPEN = 8 }; @@ -957,46 +2586,27 @@ struct TALER_EXCHANGEDB_TransactionList */ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *recoup_refresh; - } details; - -}; + /** + * Coin was deposited into a purse. + * (#TALER_EXCHANGEDB_TT_PURSE_DEPOSIT) + */ + struct TALER_EXCHANGEDB_PurseDepositListEntry *purse_deposit; + /** + * Coin was refunded upon purse expiration + * (#TALER_EXCHANGEDB_TT_PURSE_REFUND) + */ + struct TALER_EXCHANGEDB_PurseRefundListEntry *purse_refund; -/** - * @brief Handle for a database session (per-thread, for transactions). - */ -struct TALER_EXCHANGEDB_Session; + /** + * Coin was used to pay to open a reserve. + * (#TALER_EXCHANGEDB_TT_RESERVE_OPEN) + */ + struct TALER_EXCHANGEDB_ReserveOpenListEntry *reserve_open; + } details; -/** - * Function called with details about deposits that have been made, - * with the goal of executing the corresponding wire transaction. - * - * @param cls closure - * @param rowid unique ID for the deposit in our DB, used for marking - * it as 'tiny' or 'done' - * @param merchant_pub public key of the merchant - * @param coin_pub public key of the coin - * @param amount_with_fee amount that was deposited including fee - * @param deposit_fee amount the exchange gets to keep as transaction fees - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @param wire_deadline by which the merchant advised that he would like the - * wire transfer to be executed - * @param receiver_wire_account wire details for the merchant, includes - * 'url' in payto://-format; NULL from iterate_matching_deposits() - * @return transaction status code, #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT to continue to iterate - */ -typedef enum GNUNET_DB_QueryStatus -(*TALER_EXCHANGEDB_DepositIterator)( - void *cls, - uint64_t rowid, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *deposit_fee, - const struct GNUNET_HashCode *h_contract_terms, - struct GNUNET_TIME_Absolute wire_deadline, - const json_t *receiver_wire_account); +}; /** @@ -1017,42 +2627,200 @@ 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. * * @param cls closure * @param rowid unique serial ID for the deposit in our DB - * @param timestamp when did the deposit happen - * @param merchant_pub public key of the merchant + * @param exchange_timestamp when did the deposit happen + * @param deposit deposit details * @param denom_pub denomination public key of @a coin_pub - * @param coin_pub public key of the coin - * @param coin_sig signature from the coin - * @param amount_with_fee amount that was deposited including fee - * @param h_contract_terms hash of the proposal data known to merchant and customer - * @param refund_deadline by which the merchant advised that he might want - * to get a refund - * @param wire_deadline by which the merchant advised that he would like the - * wire transfer to be executed - * @param receiver_wire_account wire details for the merchant including 'url' in payto://-format; - * NULL from iterate_matching_deposits() * @param done flag set if the deposit was already executed (or not) * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_DepositCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, - const struct TALER_MerchantPublicKeyP *merchant_pub, + struct GNUNET_TIME_Timestamp exchange_timestamp, + const struct TALER_EXCHANGEDB_Deposit *deposit, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_CoinSpendSignatureP *coin_sig, + bool done); + + +/** + * Function called with details about purse deposits that have been made, with + * the goal of auditing the deposit's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param deposit deposit details + * @param reserve_pub which reserve is the purse merged into, NULL if unknown + * @param flags purse flags + * @param auditor_balance purse balance (according to the + * auditor during auditing) + * @param purse_total target amount the purse should reach + * @param denom_pub denomination public key of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDepositCallback)( + void *cls, + uint64_t rowid, + const struct TALER_EXCHANGEDB_PurseDeposit *deposit, + const struct TALER_ReservePublicKeyP *reserve_pub, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *auditor_balance, + const struct TALER_Amount *purse_total, + const struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Function called with details about + * account merge requests that have been made, with + * the goal of auditing the account merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param reserve_pub reserve affected by the merge + * @param purse_pub purse being merged + * @param h_contract_terms hash over contract of the purse + * @param purse_expiration when would the purse expire + * @param amount total amount in the purse + * @param min_age minimum age of all coins deposited into the purse + * @param flags how was the purse created + * @param purse_fee if a purse fee was paid, how high is it + * @param merge_timestamp when was the merge approved + * @param reserve_sig signature by reserve approving the merge + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_AccountMergeCallback)( + void *cls, + uint64_t rowid, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_Amount *amount, + uint32_t min_age, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig); + + +/** + * Function called with details about purse + * merges that have been made, with + * the goal of auditing the purse merge execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param partner_base_url where is the reserve, NULL for this exchange + * @param amount total amount expected in the purse + * @param balance current balance in the purse (according to the auditor) + * @param flags purse flags + * @param merge_pub merge capability key + * @param reserve_pub reserve the merge affects + * @param merge_sig signature affirming the merge + * @param purse_pub purse key + * @param merge_timestamp when did the merge happen + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseMergeCallback)( + void *cls, + uint64_t rowid, + const char *partner_base_url, + const struct TALER_Amount *amount, + const struct TALER_Amount *balance, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_PurseMergePublicKeyP *merge_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp merge_timestamp); + + +/** + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param purse_pub public key of the purse + * @param reserve_pub public key of the target reserve, NULL if not known / refunded + * @param purse_value what is the (target) value of the purse + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *purse_value); + + +/** + * Function called with details about purse decisions that have been made, with + * the goal of auditing the purse's execution. + * + * @param cls closure + * @param rowid unique serial ID for the deposit in our DB + * @param purse_pub public key of the purse + * @param refunded true if decision was to refund + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_AllPurseDecisionCallback)( + void *cls, + uint64_t rowid, + const struct TALER_PurseContractPublicKeyP *purse_pub, + bool refunded); + + +/** + * Function called with details about purse refunds that have been made, with + * the goal of auditing the purse refund's execution. + * + * @param cls closure + * @param rowid row of the refund event + * @param amount_with_fee amount of the deposit into the purse + * @param coin_pub coin that is to be refunded the @a given amount_with_fee + * @param denom_pub denomination of @a coin_pub + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRefundCoinCallback)( + void *cls, + uint64_t rowid, const struct TALER_Amount *amount_with_fee, - const struct GNUNET_HashCode *h_contract_terms, - struct GNUNET_TIME_Absolute refund_deadline, - struct GNUNET_TIME_Absolute wire_deadline, - const json_t *receiver_wire_account, - int done); + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_DenominationPublicKey *denom_pub); /** @@ -1062,6 +2830,7 @@ typedef int * @param cls closure * @param rowid unique serial ID for the refresh session in our DB * @param denom_pub denomination public key of @a coin_pub + * @param h_age_commitment age commitment that went into the signing of the coin, may be NULL * @param coin_pub public key of the coin * @param coin_sig signature from the coin * @param amount_with_fee amount that was deposited including fee @@ -1069,11 +2838,12 @@ typedef int * @param rc what is the commitment * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RefreshesCallback)( void *cls, uint64_t rowid, const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_AgeCommitmentHash *h_age_commitment, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_CoinSpendSignatureP *coin_sig, const struct TALER_Amount *amount_with_fee, @@ -1089,7 +2859,7 @@ typedef int * @param amount_with_fee amount being refunded * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RefundCoinCallback)( void *cls, const struct TALER_Amount *amount_with_fee); @@ -1102,9 +2872,9 @@ typedef int struct TALER_EXCHANGEDB_RefreshRevealedCoin { /** - * Public denomination key of the coin. + * Hash of the public denomination key of the coin. */ - struct TALER_DenominationPublicKey denom_pub; + struct TALER_DenominationHashP h_denom_pub; /** * Signature of the original coin being refreshed over the @@ -1113,41 +2883,117 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin struct TALER_CoinSpendSignatureP orig_coin_link_sig; /** - * Blinded message to be signed (in envelope), with @e coin_env_size bytes. + * Hash of the blinded new coin, that is @e coin_ev. */ - char *coin_ev; + struct TALER_BlindedCoinHashP coin_envelope_hash; /** - * Number of bytes in @e coin_ev. + * Signature generated by the exchange over the coin (in blinded format). */ - size_t coin_ev_size; + struct TALER_BlindedDenominationSignature coin_sig; /** - * Signature generated by the exchange over the coin (in blinded format). + * Values contributed from the exchange to the + * coin generation (see /csr). */ - struct TALER_DenominationSignature coin_sig; + struct TALER_ExchangeWithdrawValues exchange_vals; + + /** + * Blinded message to be signed (in envelope). + */ + struct TALER_BlindedPlanchet blinded_planchet; + }; /** + * Information per Clause-Schnorr (CS) fresh coin to + * be persisted for idempotency during refreshes-reveal. + */ +struct TALER_EXCHANGEDB_CsRevealFreshCoinData +{ + /** + * Denomination of the fresh coin. + */ + struct TALER_DenominationHashP new_denom_pub_hash; + + /** + * Blind signature of the fresh coin (possibly updated + * in case if a replay!). + */ + struct TALER_BlindedDenominationSignature bsig; + + /** + * Offset of the fresh coin in the reveal operation. + * (May not match the array offset as we may have + * a mixture of RSA and CS coins being created, and + * this request is only made for the CS subset). + */ + uint32_t coin_off; +}; + + +/** + * Generic KYC status for some operation. + */ +struct TALER_EXCHANGEDB_KycStatus +{ + /** + * Number that identifies the KYC requirement the operation + * was about. + */ + uint64_t requirement_row; + + /** + * True if the KYC status is "satisfied". + */ + bool ok; + +}; + + +struct TALER_EXCHANGEDB_ReserveInInfo +{ + const struct TALER_ReservePublicKeyP *reserve_pub; + const struct TALER_Amount *balance; + struct GNUNET_TIME_Timestamp execution_time; + const char *sender_account_details; + const char *exchange_account_name; + uint64_t wire_reference; +}; + + +/** + * Function called on each @a amount that was found to + * be relevant for a KYC check. + * + * @param cls closure to allow the KYC module to + * total up amounts and evaluate rules + * @param amount encountered transaction amount + * @param date when was the amount encountered + * @return #GNUNET_OK to continue to iterate, + * #GNUNET_NO to abort iteration + * #GNUNET_SYSERR on internal error (also abort itaration) + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_KycAmountCallback)( + void *cls, + const struct TALER_Amount *amount, + struct GNUNET_TIME_Absolute date); + + +/** * Function called with information about a refresh order. * * @param cls closure - * @param rowid unique serial ID for the row in our database * @param num_freshcoins size of the @a rrcs array * @param rrcs array of @a num_freshcoins information about coins to be created - * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 - * @param tprivs array of @e num_tprivs transfer private keys - * @param tp transfer public key information */ typedef void (*TALER_EXCHANGEDB_RefreshCallback)( void *cls, uint32_t num_freshcoins, - const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, - unsigned int num_tprivs, - const struct TALER_TransferPrivateKeyP *tprivs, - const struct TALER_TransferPublicKeyP *tp); + const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs); /** @@ -1162,10 +3008,11 @@ typedef void * @param merchant_sig signature of the merchant * @param h_contract_terms hash of the proposal data known to merchant and customer * @param rtransaction_id refund transaction ID chosen by the merchant + * @param full_refund true if the refunds total up to the entire value of the deposit * @param amount_with_fee amount that was deposited including fee * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RefundCallback)( void *cls, uint64_t rowid, @@ -1173,8 +3020,9 @@ typedef int const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, const struct TALER_MerchantSignatureP *merchant_sig, - const struct GNUNET_HashCode *h_contract_terms, + const struct TALER_PrivateContractHashP *h_contract_terms, uint64_t rtransaction_id, + bool full_refund, const struct TALER_Amount *amount_with_fee); @@ -1183,14 +3031,14 @@ typedef int * * @param cls closure * @param rowid unique serial ID for the refresh session in our DB - * @param reserve_pub public key of the reserve (also the WTID) + * @param reserve_pub public key of the reserve (also the wire subject) * @param credit amount that was received * @param sender_account_details information about the sender's bank account, in payto://-format * @param wire_reference unique identifier for the wire transfer * @param execution_date when did we receive the funds * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveInCallback)( void *cls, uint64_t rowid, @@ -1198,7 +3046,76 @@ typedef int const struct TALER_Amount *credit, const char *sender_account_details, uint64_t wire_reference, - struct GNUNET_TIME_Absolute execution_date); + struct GNUNET_TIME_Timestamp execution_date); + + +/** + * Provide information about a wire account. + * + * @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 char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterSignatureP *master_sig, + const char *bank_label, + int64_t priority); + + +/** + * Provide information about wire fees. + * + * @param cls closure + * @param fees the wire fees we charge + * @param start_date from when are these fees valid (start date) + * @param end_date until when are these fees valid (end date, exclusive) + * @param master_sig master key signature affirming that this is the correct + * fee (of purpose #TALER_SIGNATURE_MASTER_WIRE_FEES) + */ +typedef void +(*TALER_EXCHANGEDB_WireFeeCallback)( + void *cls, + const struct TALER_WireFeeSet *fees, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig); + + +/** + * Provide information about global fees. + * + * @param cls closure + * @param fees the global fees we charge + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account + * @param start_date from when are these fees valid (start date) + * @param end_date until when are these fees valid (end date, exclusive) + * @param master_sig master key signature affirming that this is the correct + * fee (of purpose #TALER_SIGNATURE_MASTER_GLOBAL_FEES) + */ +typedef void +(*TALER_EXCHANGEDB_GlobalFeeCallback)( + void *cls, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_MasterSignatureP *master_sig); /** @@ -1214,15 +3131,15 @@ typedef int * @param amount_with_fee amount that was withdrawn * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_WithdrawCallback)( void *cls, uint64_t rowid, - const struct GNUNET_HashCode *h_blind_ev, + const struct TALER_BlindedCoinHashP *h_blind_ev, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_ReserveSignatureP *reserve_sig, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const struct TALER_Amount *amount_with_fee); @@ -1242,37 +3159,14 @@ typedef void /** - * Function called with the results of the lookup of the wire transfer - * identifier information. Only called if we are at least aware of the - * transaction existing. - * - * @param cls closure - * @param wtid wire transfer identifier, NULL - * if the transaction was not yet done - * @param coin_contribution how much did the coin we asked about - * contribute to the total transfer value? (deposit value including fee) - * @param coin_fee how much did the exchange charge for the deposit fee - * @param execution_time when was the transaction done, or - * when we expect it to be done (if @a wtid was NULL) - */ -typedef void -(*TALER_EXCHANGEDB_WireTransferByCoinCallback)( - void *cls, - const struct TALER_WireTransferIdentifierRawP *wtid, - const struct TALER_Amount *coin_contribution, - const struct TALER_Amount *coin_fee, - struct GNUNET_TIME_Absolute execution_time); - - -/** * Function called with the results of the lookup of the * transaction data associated with a wire transfer identifier. * * @param cls closure * @param rowid which row in the table is the information from (for diagnostics) * @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls) - * @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls) - * @param account_details which account did the transfer go to? + * @param account_payto_uri which account did the transfer go to? + * @param h_payto hash over @a account_payto_uri as it is in the DB * @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls) * @param h_contract_terms which proposal was this payment about * @param denom_pub denomination of @a coin_pub @@ -1285,10 +3179,10 @@ typedef void void *cls, uint64_t rowid, const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_wire, - const json_t *account_details, - struct GNUNET_TIME_Absolute exec_time, - const struct GNUNET_HashCode *h_contract_terms, + const char *account_payto_uri, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Timestamp exec_time, + const struct TALER_PrivateContractHashP *h_contract_terms, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_Amount *coin_value, @@ -1303,21 +3197,41 @@ typedef void * @param rowid identifier of the respective row in the database * @param date timestamp of the wire transfer (roughly) * @param wtid wire transfer subject - * @param wire wire transfer details of the receiver, including "url" in payto://-format + * @param payto_uri details of the receiver, URI in payto://-format * @param amount amount that was wired * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_WireTransferOutCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute date, + struct GNUNET_TIME_Timestamp date, const struct TALER_WireTransferIdentifierRawP *wtid, - const json_t *wire, + const char *payto_uri, const struct TALER_Amount *amount); /** + * Function called on transient aggregations matching + * a particular hash of a payto URI. + * + * @param cls + * @param payto_uri corresponding payto URI + * @param wtid wire transfer identifier of transient aggregation + * @param merchant_pub public key of the merchant + * @param total amount aggregated so far + * @return true to continue iterating + */ +typedef bool +(*TALER_EXCHANGEDB_TransientAggregationCallback)( + void *cls, + const char *payto_uri, + const struct TALER_WireTransferIdentifierRawP *wtid, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_Amount *total); + + +/** * Callback with data about a prepared wire transfer. * * @param cls closure @@ -1328,7 +3242,7 @@ typedef int * @param finished did we complete the transfer yet? * @return #GNUNET_OK to continue, #GNUNET_SYSERR to stop iteration */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_WirePreparationCallback)(void *cls, uint64_t rowid, const char *wire_method, @@ -1351,17 +3265,17 @@ typedef int * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RecoupCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct TALER_Amount *amount, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); /** @@ -1380,18 +3294,45 @@ typedef int * @param coin_blind blinding factor used to blind the coin * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_RecoupRefreshCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute timestamp, + struct GNUNET_TIME_Timestamp timestamp, const struct TALER_Amount *amount, const struct TALER_CoinSpendPublicKeyP *old_coin_pub, - const struct GNUNET_HashCode *old_denom_pub_hash, + const struct TALER_DenominationHashP *old_denom_pub_hash, const struct TALER_CoinPublicInfo *coin, const struct TALER_DenominationPublicKey *denom_pub, const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind); + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind); + + +/** + * Function called about reserve opening operations. + * + * @param cls closure + * @param rowid row identifier used to uniquely identify the reserve closing operation + * @param reserve_payment how much to pay from the + * reserve's own balance for opening the reserve + * @param request_timestamp when was the request created + * @param reserve_expiration desired expiration time for the reserve + * @param purse_limit minimum number of purses the client + * wants to have concurrently open for this reserve + * @param reserve_pub public key of the reserve + * @param reserve_sig signature affirming the operation + * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_ReserveOpenCallback)( + void *cls, + uint64_t rowid, + const struct TALER_Amount *reserve_payment, + struct GNUNET_TIME_Timestamp request_timestamp, + struct GNUNET_TIME_Timestamp reserve_expiration, + uint32_t purse_limit, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_ReserveSignatureP *reserve_sig); /** @@ -1406,21 +3347,36 @@ typedef int * @param reserve_pub public key of the reserve * @param receiver_account where did we send the funds, in payto://-format * @param wtid identifier used for the wire transfer + * @param close_request_row row with the responsible close + * request, 0 if regular expiration triggered close * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop */ -typedef int +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveClosedCallback)( void *cls, uint64_t rowid, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const struct TALER_Amount *amount_with_fee, const struct TALER_Amount *closing_fee, const struct TALER_ReservePublicKeyP *reserve_pub, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid); + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t close_request_row); /** + * Function called with the amounts historically + * withdrawn from the same origin account. + * + * @param cls closure + * @param val one of the withdrawn amounts + */ +typedef void +(*TALER_EXCHANGEDB_WithdrawHistoryCallback)( + void *cls, + const struct TALER_Amount *val); + +/** * Function called with details about expired reserves. * * @param cls closure @@ -1428,15 +3384,20 @@ typedef int * @param left amount left in the reserve * @param account_details information about the reserve's bank account, in payto://-format * @param expiration_date when did the reserve expire - * @return transaction status code to pass on + * @param close_request_row row that caused the reserve + * to be closed, 0 if it expired without request + * @return #GNUNET_OK on success, + * #GNUNET_NO to retry + * #GNUNET_SYSERR on hard failures (exit) */ -typedef enum GNUNET_DB_QueryStatus +typedef enum GNUNET_GenericReturnValue (*TALER_EXCHANGEDB_ReserveExpiredCallback)( void *cls, const struct TALER_ReservePublicKeyP *reserve_pub, const struct TALER_Amount *left, const char *account_details, - struct GNUNET_TIME_Absolute expiration_date); + struct GNUNET_TIME_Timestamp expiration_date, + uint64_t close_request_row); /** @@ -1448,7 +3409,7 @@ typedef enum GNUNET_DB_QueryStatus * @param coin information about the coin * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP * @param coin_blind blinding key of the coin - * @param h_blind_ev blinded envelope, as calculated by the exchange + * @param h_blinded_ev blinded envelope, as calculated by the exchange * @param amount total amount to be paid back */ typedef void @@ -1457,49 +3418,128 @@ typedef void uint64_t rowid, const struct TALER_CoinPublicInfo *coin, const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind, - const struct GNUNET_HashCode *h_blinded_ev, + const union GNUNET_CRYPTO_BlindingSecretP *coin_blind, + const struct TALER_BlindedCoinHashP *h_blinded_ev, const struct TALER_Amount *amount); /** - * Function called on deposits that are past their due date - * and have not yet seen a wire transfer. + * Function called on (batch) deposits will need a wire + * transfer. * * @param cls closure - * @param rowid deposit table row of the coin's deposit - * @param coin_pub public key of the coin - * @param amount value of the deposit, including fee - * @param wire where should the funds be wired, including 'url' in payto://-format - * @param deadline what was the requested wire transfer deadline - * @param tiny did the exchange defer this transfer because it is too small? - * @param done did the exchange claim that it made a transfer? + * @param batch_deposit_serial_id where in the table are we + * @param total_amount value of all missing deposits, including fees + * @param wire_target_h_payto hash of the recipient account's payto URI + * @param deadline what was the earliest requested wire transfer deadline */ typedef void (*TALER_EXCHANGEDB_WireMissingCallback)( void *cls, + uint64_t batch_deposit_serial_id, + const struct TALER_Amount *total_amount, + const struct TALER_PaytoHashP *wire_target_h_payto, + struct GNUNET_TIME_Timestamp deadline); + + +/** + * Function called on aggregations that were done for + * a (batch) deposit. + * + * @param cls closure + * @param tracking_serial_id where in the table are we + * @param batch_deposit_serial_id which batch deposit was aggregated + */ +typedef void +(*TALER_EXCHANGEDB_AggregationCallback)( + void *cls, + uint64_t tracking_serial_id, + uint64_t batch_deposit_serial_id); + + +/** + * Function called on purse requests. + * + * @param cls closure + * @param rowid purse request table row of the purse + * @param purse_pub public key of the purse + * @param merge_pub public key representing the merge capability + * @param purse_creation when was the purse created? + * @param purse_expiration when would an unmerged purse expire + * @param h_contract_terms contract associated with the purse + * @param age_limit the age limit for deposits into the purse + * @param target_amount amount to be put into the purse + * @param purse_sig signature of the purse over the initialization data + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_EXCHANGEDB_PurseRequestCallback)( + void *cls, uint64_t rowid, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_Amount *amount, - const json_t *wire, - struct GNUNET_TIME_Absolute deadline, - /* bool? */ int tiny, - /* bool? */ int done); + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_creation, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + const struct TALER_Amount *target_amount, + const struct TALER_PurseContractSignatureP *purse_sig); /** * Function called with information about the exchange's denomination keys. + * Note that the 'master' field in @a issue will not yet be initialized when + * this function is called! * * @param cls closure * @param denom_pub public key of the denomination - * @param issue detailed information about the denomination (value, expiration times, fees) + * @param issue detailed information about the denomination (value, expiration times, fees); */ typedef void (*TALER_EXCHANGEDB_DenominationCallback)( void *cls, - const struct - TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); + + +/** + * Return AML status. + * + * @param cls closure + * @param row_id current row in AML status table + * @param h_payto account for which the attribute data is stored + * @param threshold currently monthly threshold that would trigger an AML check + * @param status what is the current AML decision + */ +typedef void +(*TALER_EXCHANGEDB_AmlStatusCallback)( + void *cls, + uint64_t row_id, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold, + enum TALER_AmlDecisionState status); + + +/** + * Return historic AML decision. + * + * @param cls closure + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + */ +typedef void +(*TALER_EXCHANGEDB_AmlHistoryCallback)( + void *cls, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig); /** @@ -1520,16 +3560,6 @@ struct TALER_EXCHANGEDB_Plugin */ char *library_name; - /** - * Get the thread-local (!) database-handle. - * Connect to the db if the connection does not exist yet. - * - * @param cls the @e cls of this struct with the plugin-specific state - * @returns the database connection, or NULL on error - */ - struct TALER_EXCHANGEDB_Session * - (*get_session) (void *cls); - /** * Drop the Taler tables. This should only be used in testcases. @@ -1537,45 +3567,71 @@ struct TALER_EXCHANGEDB_Plugin * @param cls the @e cls of this struct with the plugin-specific state * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ - int - (*drop_tables) (void *cls); - + enum GNUNET_GenericReturnValue + (*drop_tables)(void *cls); /** * Create the necessary tables if they are not present * * @param cls the @e cls of this struct with the plugin-specific state + * @param support_partitions true to enable partitioning support (disables foreign key constraints) + * @param num_partitions number of partitions to create, + * (0 to not actually use partitions, 1 to only + * setup a default partition, >1 for real partitions) * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure */ - int - (*create_tables) (void *cls); + enum GNUNET_GenericReturnValue + (*create_tables)(void *cls, + bool support_partitions, + uint32_t num_partitions); /** * Start a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param name unique name identifying the transaction (for debugging), * must point to a constant * @return #GNUNET_OK on success */ - int - (*start) (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const char *name); + enum GNUNET_GenericReturnValue + (*start)(void *cls, + const char *name); + + + /** + * Start a READ COMMITTED transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param name unique name identifying the transaction (for debugging) + * must point to a constant + * @return #GNUNET_OK on success + */ + enum GNUNET_GenericReturnValue + (*start_read_committed)(void *cls, + const char *name); + + /** + * Start a READ ONLY serializable transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param name unique name identifying the transaction (for debugging) + * must point to a constant + * @return #GNUNET_OK on success + */ + enum GNUNET_GenericReturnValue + (*start_read_only)(void *cls, + const char *name); /** * Commit a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @return transaction status */ enum GNUNET_DB_QueryStatus - (*commit)(void *cls, - struct TALER_EXCHANGEDB_Session *session); + (*commit)(void *cls); /** @@ -1584,22 +3640,65 @@ struct TALER_EXCHANGEDB_Plugin * Does not return anything, as we will continue regardless of the outcome. * * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param session the database connection + * @return #GNUNET_OK if everything is fine + * #GNUNET_NO if a transaction was rolled back + * #GNUNET_SYSERR on hard errors */ - void - (*preflight) (void *cls, - struct TALER_EXCHANGEDB_Session *session); + enum GNUNET_GenericReturnValue + (*preflight)(void *cls); /** * Abort/rollback a transaction. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use */ void - (*rollback) (void *cls, - struct TALER_EXCHANGEDB_Session *session); + (*rollback) (void *cls); + + + /** + * Register callback to be invoked on events of type @a es. + * + * @param cls database context to use + * @param timeout how long to wait at most + * @param es specification of the event to listen for + * @param cb function to call when the event happens, possibly + * multiple 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, + struct GNUNET_TIME_Relative timeout, + const struct GNUNET_DB_EventHeaderP *es, + GNUNET_DB_EventCallback cb, + void *cb_cls); + + /** + * Stop notifications. + * + * @param cls database context to use + * @param eh handle to unregister. + */ + void + (*event_listen_cancel)(void *cls, + 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); /** @@ -1608,7 +3707,6 @@ struct TALER_EXCHANGEDB_Plugin * with this key have. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param denom_pub the public key used for signing coins of this denomination * @param issue issuing information with value, fees and other info about the denomination * @return status of the query @@ -1616,16 +3714,14 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_denomination_info)( void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_DenominationPublicKey *denom_pub, - const struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); /** * Fetch information about a denomination key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param denom_pub_hash hash of the public key used for signing coins of this denomination * @param[out] issue set to issue information with value, fees and other info about the coin * @return transaction status code @@ -1633,14 +3729,15 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*get_denomination_info)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, - struct TALER_EXCHANGEDB_DenominationKeyInformationP *issue); + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_EXCHANGEDB_DenominationKeyInformation *issue); /** * Function called on every known denomination key. Runs in its - * own read-only transaction (hence no session provided). + * own read-only transaction (hence no session provided). Note that + * the "master" field in the callback's 'issue' argument will NOT + * be initialized yet. * * @param cls the @e cls of this struct with the plugin-specific state * @param cb function to call on each denomination key @@ -1652,11 +3749,74 @@ struct TALER_EXCHANGEDB_Plugin TALER_EXCHANGEDB_DenominationCallback cb, void *cb_cls); + + /** + * Function called to invoke @a cb on every known denomination key (revoked + * and non-revoked) that has been signed by the master key. Runs in its own + * read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each denomination key + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_denominations)(void *cls, + TALER_EXCHANGEDB_DenominationsCallback cb, + void *cb_cls); + + /** + * Function called to invoke @a cb on every non-revoked exchange signing key + * that has been signed by the master key. Revoked and (for signing!) + * expired keys are skipped. Runs in its own read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each signing key + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_active_signkeys)(void *cls, + TALER_EXCHANGEDB_ActiveSignkeysCallback cb, + void *cb_cls); + + + /** + * Function called to invoke @a cb on every active auditor. Disabled + * auditors are skipped. Runs in its own read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each active auditor + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_active_auditors)(void *cls, + TALER_EXCHANGEDB_AuditorsCallback cb, + void *cb_cls); + + + /** + * Function called to invoke @a cb on every denomination with an active + * auditor. Disabled auditors and denominations without auditor are + * skipped. Runs in its own read-only transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param cb function to call on each active auditor-denomination pair + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_auditor_denominations)( + void *cls, + TALER_EXCHANGEDB_AuditorDenominationsCallback cb, + void *cb_cls); + + /** * Get the summary of a reserve. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session the database connection handle * @param[in,out] reserve the reserve data. The public key of the reserve should be set * in this structure; it is used to query the database. The balance * and expiration are then filled accordingly. @@ -1664,107 +3824,447 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*reserves_get)(void *cls, - struct TALER_EXCHANGEDB_Session *session, struct TALER_EXCHANGEDB_Reserve *reserve); /** - * Insert a incoming transaction into reserves. New reserves are + * Get the origin of funds of a reserve. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve + * @param[out] h_payto set to hash of the wire source payto://-URI + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*reserves_get_origin)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_PaytoHashP *h_payto); + + + /** + * Extract next KYC alert. Deletes the alert. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param trigger_type which type of alert to drain + * @param[out] h_payto set to hash of payto-URI where KYC status changed + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*drain_kyc_alert)(void *cls, + uint32_t trigger_type, + struct TALER_PaytoHashP *h_payto); + + + /** + * Insert a batch of incoming transaction into reserves. New reserves are * also created through this function. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session the database session handle - * @param reserve_pub public key of the reserve - * @param balance the amount that has to be added to the reserve - * @param execution_time when was the amount added - * @param sender_account_details information about the sender's bank account, in payto://-format - * @param wire_reference unique reference identifying the wire transfer - * @return transaction status code + * @param reserves + * @param reserves_length length of the @a reserves array + * @param[out] results array of transaction status codes of length @a reserves_length, + * set to the status of the */ enum GNUNET_DB_QueryStatus - (*reserves_in_insert)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_Amount *balance, - struct GNUNET_TIME_Absolute execution_time, - const char *sender_account_details, - const char *exchange_account_name, - uint64_t wire_reference); + (*reserves_in_insert)( + void *cls, + const struct TALER_EXCHANGEDB_ReserveInInfo *reserves, + unsigned int reserves_length, + enum GNUNET_DB_QueryStatus *results); /** - * Obtain the most recent @a wire_reference that was inserted via @e reserves_in_insert. - * Used by the wirewatch process when resuming. + * Locate a nonce for use with a particular public key. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session the database connection handle - * @param exchange_account_name name of the section in the exchange's configuration - * for the account that we are tracking here - * @param[out] wire_reference set to unique reference identifying the wire transfer - * @return transaction status code + * @param nonce the nonce to be locked + * @param denom_pub_hash hash of the public key of the denomination + * @param target public key the nonce is to be locked to + * @return statement execution status */ enum GNUNET_DB_QueryStatus - (*get_latest_reserve_in_reference)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const char *exchange_account_name, - uint64_t *wire_reference); + (*lock_nonce)(void *cls, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + const struct TALER_DenominationHashP *denom_pub_hash, + const union TALER_EXCHANGEDB_NonceLockTargetP *target); /** - * Locate the response for a withdraw request under the - * key of the hash of the blinded message. Used to ensure - * idempotency of the request. + * Locate the response for a withdraw request under a hash that uniquely + * identifies the withdraw operation. Used to ensure idempotency of the + * request. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection to use - * @param h_blind hash of the blinded coin to be signed (will match - * `h_coin_envelope` in the @a collectable to be returned) - * @param collectable corresponding collectable coin (blind signature) + * @param bch hash that uniquely identifies the withdraw operation + * @param[out] collectable corresponding collectable coin (blind signature) * if a coin is found * @return statement execution status */ enum GNUNET_DB_QueryStatus (*get_withdraw_info)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *h_blind, - struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + const struct TALER_BlindedCoinHashP *bch, + struct TALER_EXCHANGEDB_CollectableBlindcoin * + collectable); /** - * Store collectable coin under the corresponding hash of the blinded - * message. + * FIXME: merge do_batch_withdraw and do_batch_withdraw_insert into one API, + * which takes as input (among others) + * - denom_serial[] + * - blinded_coin_evs[] + * - denom_sigs[] + * The implementation should persist the data as _arrays_ in the DB. + */ + + /** + * Perform reserve update as part of a batch withdraw operation, checking + * for sufficient balance. Persisting the withdrawal details is done + * separately! * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection to use + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param now current time (rounded) + * @param reserve_pub public key of the reserve to debit + * @param amount total amount to withdraw + * @param do_age_check if set, the batch-withdrawal can only succeed when the reserve has no age restriction (birthday) set. + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if no age requirements were defined on the reserve or @e do_age_check was false + * @param[out] allowed_maximum_age when @e age_ok is false, set to the allowed maximum age for withdrawal from the reserve. The client MUST then use the age-withdraw endpoint + * @param[out] ruuid set to the reserve's UUID (reserves table row) + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_batch_withdraw)( + void *cls, + struct GNUNET_TIME_Timestamp now, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *amount, + bool do_age_check, + bool *found, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, + uint64_t *ruuid); + + + /** + * Perform insert as part of a batch withdraw operation, and 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) - * if a coin is found + * @param now current time (rounded) + * @param ruuid reserve UUID + * @param[out] denom_unknown set if the denomination is unknown in the DB + * @param[out] conflict if the envelope was already in the DB + * @param[out] nonce_reuse if @a nonce was non-NULL and reused + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_batch_withdraw_insert)( + void *cls, + const union GNUNET_CRYPTO_BlindSessionNonce *nonce, + const struct TALER_EXCHANGEDB_CollectableBlindcoin *collectable, + struct GNUNET_TIME_Timestamp now, + uint64_t ruuid, + bool *denom_unknown, + bool *conflict, + bool *nonce_reuse); + + /** + * Locate the response for a age-withdraw request under a hash of the + * commitment and reserve_pub that uniquely identifies the age-withdraw + * operation. Used to ensure idempotency of the request. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the reserve for which the age-withdraw request is made + * @param ach hash that uniquely identifies the age-withdraw operation + * @param[out] aw corresponding details of the previous age-withdraw request if an entry was found * @return statement execution status */ enum GNUNET_DB_QueryStatus - (*insert_withdraw_info)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct - TALER_EXCHANGEDB_CollectableBlindcoin *collectable); + (*get_age_withdraw)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_AgeWithdrawCommitmentHashP *ach, + struct TALER_EXCHANGEDB_AgeWithdraw *aw); + + /** + * Perform an age-withdraw operation, checking for sufficient balance and + * fulfillment of age requirements and possibly persisting the withdrawal + * details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param commitment corresponding commitment for the age-withdraw + * @param[out] found set to true if the reserve was found + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] age_ok set to true if age requirements were met + * @param[out] allowed_maximum_age if @e age_ok is FALSE, this is set to the allowed maximum age + * @param[out] reserve_birthday if @e age_ok is FALSE, this is set to the reserve's birthday + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_age_withdraw)( + void *cls, + const struct TALER_EXCHANGEDB_AgeWithdraw *commitment, + struct GNUNET_TIME_Timestamp now, + bool *found, + bool *balance_ok, + struct TALER_Amount *reserve_balance, + bool *age_ok, + uint16_t *allowed_maximum_age, + uint32_t *reserve_birthday, + bool *conflict); + + /** + * Retrieve the details to a policy given by its hash_code + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param hc Hash code that identifies the policy + * @param[out] detail retrieved policy details + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*get_policy_details)( + void *cls, + const struct GNUNET_HashCode *hc, + struct TALER_PolicyDetails *detail); + + /** + * Persist the policy details that extends a deposit. The particular policy + * - referenced by details->hash_code - might already exist in the table, in + * which case the call will update the contents of the record with @e details + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param details The parsed `struct TALER_PolicyDetails` according to the responsible policy extension. + * @param[out] policy_details_serial_id The ID of the entry in the policy_details table + * @param[out] accumulated_total The total amount accumulated in that policy + * @param[out] fulfillment_state The state of policy. If the state was Insufficient prior to the call and the provided deposit raises the accumulated_total above the commitment, it will be set to Ready. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*persist_policy_details)( + void *cls, + const struct TALER_PolicyDetails *details, + uint64_t *policy_details_serial_id, + struct TALER_Amount *accumulated_total, + enum TALER_PolicyFulfillmentState *fulfillment_state); /** - * Get all of the transaction history associated with the specified - * reserve. + * Perform deposit operation, checking for sufficient balance + * of the coin and possibly persisting the deposit details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param bd batch deposit operation details + * @param[in,out] exchange_timestamp time to use for the deposit (possibly updated) + * @param[out] balance_ok set to true if the balance was sufficient + * @param[out] bad_balance_index set to the first index of a coin for which the balance was insufficient, + * only used if @a balance_ok is set to false. + * @param[out] ctr_conflict set to true if the same contract terms hash was previously submitted with other meta data (deadlines, wallet_data_hash, wire data etc.) + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_deposit)( + void *cls, + const struct TALER_EXCHANGEDB_BatchDeposit *bd, + struct GNUNET_TIME_Timestamp *exchange_timestamp, + bool *balance_ok, + uint32_t *bad_balance_index, + bool *ctr_conflict); + + + /** + * Perform melt operation, checking for sufficient balance + * of the coin and possibly persisting the melt details. + * + * @param cls the plugin-specific state + * @param rms client-contributed input for CS denominations that must be checked for idempotency, or NULL for non-CS withdrawals + * @param[in,out] refresh refresh operation details; the noreveal_index + * is set in case the coin was already melted before + * @param known_coin_id row of the coin in the known_coins table + * @param[in,out] zombie_required true if the melt must only succeed if the coin is a zombie, set to false if the requirement was satisfied + * @param[out] balance_ok set to true if the balance was sufficient + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_melt)( + void *cls, + const struct TALER_RefreshMasterSecretP *rms, + struct TALER_EXCHANGEDB_Refresh *refresh, + uint64_t known_coin_id, + bool *zombie_required, + bool *balance_ok); + + + /** + * Add a proof of fulfillment of an policy + * + * @param cls the plugin-specific state + * @param[in,out] fulfillment The proof of fulfillment and serial_ids of the policy_details along with their new state and potential new amounts. + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*add_policy_fulfillment_proof)( + void *cls, + struct TALER_PolicyFulfillmentTransactionData *fulfillment); + + + /** + * Check if the given @a nonce was properly locked to the given @a old_coin_pub. If so, check if we already + * created CS signatures for the given @a nonce and @a new_denom_pub_hashes, + * and if so, return them in @a s_scalars. Otherwise, persist the + * signatures from @a s_scalars in the database. + * + * @param cls the plugin-specific state + * @param nonce the client-provided nonce where we must prevent reuse + * @param old_coin_pub public key the nonce was locked to + * @param num_fresh_coins array length, number of fresh coins revealed + * @param[in,out] crfcds array of data about the fresh coins, of length @a num_fresh_coins + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*cs_refreshes_reveal)( + void *cls, + const struct GNUNET_CRYPTO_CsSessionNonce *nonce, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + unsigned int num_fresh_coins, + struct TALER_EXCHANGEDB_CsRevealFreshCoinData *crfcds); + + + /** + * Perform refund operation, checking for sufficient deposits + * of the coin and possibly persisting the refund details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param refund refund operation details + * @param deposit_fee deposit fee applicable for the coin, possibly refunded + * @param known_coin_id row of the coin in the known_coins table + * @param[out] not_found set if the deposit was not found + * @param[out] refund_ok set if the refund succeeded (below deposit amount) + * @param[out] gone if the merchant was already paid + * @param[out] conflict set if the refund ID was re-used + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_refund)( + void *cls, + const struct TALER_EXCHANGEDB_Refund *refund, + const struct TALER_Amount *deposit_fee, + uint64_t known_coin_id, + bool *not_found, + bool *refund_ok, + bool *gone, + bool *conflict); + + + /** + * Perform recoup operation, checking for sufficient deposits + * of the coin and possibly persisting the recoup details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param reserve_pub public key of the reserve to credit + * @param reserve_out_serial_id row in the reserves_out table justifying the recoup + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_recoup)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t reserve_out_serial_id, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); + + + /** + * Perform recoup-refresh operation, checking for sufficient deposits of the + * coin and possibly persisting the recoup-refresh details. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param old_coin_pub public key of the old coin to credit + * @param rrc_serial row in the refresh_revealed_coins table justifying the recoup-refresh + * @param coin_bks coin blinding key secret to persist + * @param coin_pub public key of the coin being recouped + * @param known_coin_id row of the @a coin_pub in the known_coins table + * @param coin_sig signature of the coin requesting the recoup + * @param[in,out] recoup_timestamp recoup timestamp, set if recoup existed + * @param[out] recoup_ok set if the recoup-refresh succeeded (balance ok) + * @param[out] internal_failure set on internal failures + * @return query execution status + */ + enum GNUNET_DB_QueryStatus + (*do_recoup_refresh)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t rrc_serial, + const union GNUNET_CRYPTO_BlindingSecretP *coin_bks, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t known_coin_id, + const struct TALER_CoinSpendSignatureP *coin_sig, + struct GNUNET_TIME_Timestamp *recoup_timestamp, + bool *recoup_ok, + bool *internal_failure); + + + /** + * Compile a list of (historic) transactions performed with the given reserve + * (withdraw, incoming wire, open, close operations). Should return 0 if the @a + * reserve_pub is unknown, otherwise determine @a etag_out and if it is past @a + * etag_in return the history after @a start_off. @a etag_out should be set + * to the last row ID of the given @a reserve_pub in the reserve history table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @param reserve_pub public key of the reserve + * @param start_off maximum starting offset in history to exclude from returning + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub + * @param[out] balance set to the reserve balance * @param[out] rhp set to known transaction history (NULL if reserve is unknown) * @return transaction status */ enum GNUNET_DB_QueryStatus (*get_reserve_history)(void *cls, - struct TALER_EXCHANGEDB_Session *session, 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); /** + * The current reserve balance of 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 set to the reserve balance + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_reserve_balance)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance); + + + /** * Free memory associated with the given reserve history. * * @param cls the @e cls of this struct with the plugin-specific state @@ -1779,104 +4279,195 @@ struct TALER_EXCHANGEDB_Plugin * Count the number of known coins by denomination. * * @param cls database connection plugin state - * @param session database session * @param denom_pub_hash denomination to count by * @return number of coins if non-negative, otherwise an `enum GNUNET_DB_QueryStatus` */ long long (*count_known_coins) (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash); + const struct TALER_DenominationHashP *denom_pub_hash); /** * Make sure the given @a coin is known to the database. * * @param cls database connection plugin state - * @param session database session * @param coin the coin that must be made known + * @param[out] known_coin_id set to the unique row of the coin + * @param[out] denom_pub_hash set to the conflicting denomination hash on conflict + * @param[out] age_hash set to the conflicting age hash on conflict * @return database transaction status, non-negative on success */ - enum GNUNET_DB_QueryStatus + enum TALER_EXCHANGEDB_CoinKnownStatus + { + /** + * The coin was successfully added. + */ + TALER_EXCHANGEDB_CKS_ADDED = 1, + + /** + * The coin was already present. + */ + TALER_EXCHANGEDB_CKS_PRESENT = 0, + + /** + * Serialization failure. + */ + TALER_EXCHANGEDB_CKS_SOFT_FAIL = -1, + + /** + * Hard database failure. + */ + TALER_EXCHANGEDB_CKS_HARD_FAIL = -2, + + /** + * Conflicting coin (different denomination key) already in database. + */ + TALER_EXCHANGEDB_CKS_DENOM_CONFLICT = -3, + + /** + * Conflicting coin (expected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NULL = -4, + + /** + * Conflicting coin (unexpected NULL age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_EXPECTED_NON_NULL = -5, + + /** + * Conflicting coin (different age hash) already in database. + */ + TALER_EXCHANGEDB_CKS_AGE_CONFLICT_VALUE_DIFFERS = -6, + + } (*ensure_coin_known)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin); + const struct TALER_CoinPublicInfo *coin, + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_AgeCommitmentHash *age_hash); + + + /** + * Make sure the array of given @a coin is known to the database. + * + * @param cls database connection plugin state + * @param coin array of coins that must be made known + * @param[out] result array where to store information about each coin + * @param coin_length length of the @a coin and @a result arraysf + * @param batch_size desired (maximum) batch size + * @return database transaction status, non-negative on success + */ + enum GNUNET_DB_QueryStatus + (*batch_ensure_coin_known)( + void *cls, + const struct TALER_CoinPublicInfo *coin, + struct TALER_EXCHANGEDB_CoinInfo *result, + unsigned int coin_length, + unsigned int batch_size); /** * Retrieve information about the given @a coin from the database. * * @param cls database connection plugin state - * @param session database session - * @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 (*get_known_coin)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_CoinSpendPublicKeyP *coin_pub, struct TALER_CoinPublicInfo *coin_info); + /** + * Retrieve the signature and corresponding denomination for a given @a coin + * from the database + * + * @param cls database connection plugin state + * @param coin_pub the public key of the coin we search for + * @param[out] denom_pub the public key of the denomination that the coin was signed with + * @param[out] denom_sig the signature with the denomination's private key over the coin_pub + */ + enum GNUNET_DB_QueryStatus + (*get_signature_for_known_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_DenominationPublicKey *denom_pub, + struct TALER_DenominationSignature *denom_sig); /** * Retrieve the denomination of a known coin. * * @param cls the plugin closure - * @param session the database session handle * @param coin_pub the public key of the coin to search for + * @param[out] known_coin_id set to the ID of the coin in the known_coins table * @param[out] denom_hash where to store the hash of the coins denomination * @return transaction status code */ enum GNUNET_DB_QueryStatus (*get_coin_denomination)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct GNUNET_HashCode *denom_hash); + uint64_t *known_coin_id, + struct TALER_DenominationHashP *denom_hash); /** - * Check if we have the specified deposit already in the database. + * Try to retrieve the salted hash of the merchant's bank account to a + * deposit contract. Used in case of conflicts for a given (merchant_pub, + * h_contract_terms) to provide the client the necessary input to retrieve + * more details about the conflict. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection - * @param deposit deposit to search for - * @param check_extras whether to check extra fields or not - * @return 1 if we know this operation, - * 0 if this exact deposit is unknown to us, - * otherwise transaction error status + * @param cls the plugin closure + * @param merchant_pub public key of the merchant + * @param h_contract_terms contract to check for + * @param[out] h_wire hash of the wire details */ enum GNUNET_DB_QueryStatus - (*have_deposit)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_EXCHANGEDB_Deposit *deposit, - int check_extras); + (*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); /** - * Insert information about deposited coin into the database. + * Check if we have the specified deposit already in the database. * - * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param deposit deposit information to store - * @return query result status + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param h_contract_terms contract to check for + * @param h_wire wire hash to check for + * @param coin_pub public key of the coin to check for + * @param merchant merchant public key to check for + * @param refund_deadline expected refund deadline + * @param[out] deposit_fee set to the deposit fee the exchange charged + * @param[out] exchange_timestamp set to the time when the exchange received the deposit + * @return 1 if we know this operation, + * 0 if this exact deposit is unknown to us, + * otherwise transaction error status */ + // FIXME: rename! enum GNUNET_DB_QueryStatus - (*insert_deposit)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_EXCHANGEDB_Deposit *deposit); + (*have_deposit2)( + void *cls, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant, + struct GNUNET_TIME_Timestamp refund_deadline, + struct TALER_Amount *deposit_fee, + struct GNUNET_TIME_Timestamp *exchange_timestamp); /** * Insert information about refunded coin into the database. + * Used in tests and for benchmarking. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database * @param refund refund information to store * @return query result status */ enum GNUNET_DB_QueryStatus (*insert_refund)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_EXCHANGEDB_Refund *refund); @@ -1884,7 +4475,6 @@ struct TALER_EXCHANGEDB_Plugin * Select refunds by @a coin_pub, @a merchant_pub and @a h_contract. * * @param cls closure of plugin - * @param session database handle to use * @param coin_pub coin to get refunds for * @param merchant_pub merchant to get refunds for * @param h_contract_pub contract (hash) to get refunds for @@ -1893,174 +4483,169 @@ struct TALER_EXCHANGEDB_Plugin * @return query result status */ enum GNUNET_DB_QueryStatus - (*select_refunds_by_coin)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract, - TALER_EXCHANGEDB_RefundCoinCallback cb, - void *cb_cls); + (*select_refunds_by_coin)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_PrivateContractHashP *h_contract, + TALER_EXCHANGEDB_RefundCoinCallback cb, + void *cb_cls); /** - * Mark a deposit as tiny, thereby declaring that it cannot be executed by - * itself (only included in a larger aggregation) and should no longer be - * returned by @e iterate_ready_deposits() + * Obtain information about deposits that are ready to be executed. + * Such deposits must not be marked as "done", and the + * execution time, the refund deadlines must both be in the past and + * the KYC status must be 'ok'. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param deposit_rowid identifies the deposit row to modify - * @return query result status + * @param start_shard_row minimum shard row to select + * @param end_shard_row maximum shard row to select (inclusive) + * @param[out] merchant_pub set to the public key of a merchant with a ready deposit + * @param[out] payto_uri set to the account of the merchant, to be freed by caller + * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*mark_deposit_tiny)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - uint64_t rowid); + (*get_ready_deposit)(void *cls, + uint64_t start_shard_row, + uint64_t end_shard_row, + struct TALER_MerchantPublicKeyP *merchant_pub, + char **payto_uri); /** - * Test if a deposit was marked as done, thereby declaring that it - * cannot be refunded anymore. + * Aggregate all matching deposits for @a h_payto and + * @a merchant_pub, returning the total amounts. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param coin_pub the coin to check for deposit - * @param merchant_pub merchant to receive the deposit - * @param h_contract_terms contract terms of the deposit - * @param h_wire hash of the merchant's wire details - * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if is is marked done, - * #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if not, - * otherwise transaction error status (incl. deposit unknown) + * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant + * @param wtid wire transfer ID to set for the aggregate + * @param[out] total set to the sum of the total deposits minus applicable deposit fees and refunds + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*test_deposit_done)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - const struct TALER_MerchantPublicKeyP *merchant_pub, - const struct GNUNET_HashCode *h_contract_terms, - const struct GNUNET_HashCode *h_wire); + (*aggregate)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); /** - * Mark a deposit as done, thereby declaring that it cannot be - * executed at all anymore, and should no longer be returned by - * @e iterate_ready_deposits() or @e iterate_matching_deposits(). + * Create a new entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param deposit_rowid identifies the deposit row to modify - * @return query result status + * @param h_payto destination of the wire transfer + * @param exchange_account_section exchange account to use + * @param merchant_pub public key of the merchant + * @param wtid the raw wire transfer identifier to be used + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total amount to be wired in the future + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*mark_deposit_done)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - uint64_t rowid); + (*create_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *exchange_account_section, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); /** - * Obtain information about deposits that are ready to be executed. - * Such deposits must not be marked as "tiny" or "done", and the - * execution time and refund deadlines must both be in the past. + * Select existing entry in the transient aggregation table. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param deposit_cb function to call for ONE such deposit - * @param deposit_cb_cls closure for @a deposit_cb - * @return transaction status code + * @param h_payto destination of the wire transfer + * @param merchant_pub public key of the merchant + * @param exchange_account_section exchange account to use + * @param[out] wtid set to the raw wire transfer identifier to be used + * @param[out] total existing amount to be wired in the future + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*get_ready_deposit)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - TALER_EXCHANGEDB_DepositIterator deposit_cb, - void *deposit_cb_cls); + (*select_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_MerchantPublicKeyP *merchant_pub, + const char *exchange_account_section, + struct TALER_WireTransferIdentifierRawP *wtid, + struct TALER_Amount *total); -/** - * Maximum number of results we return from iterate_matching_deposits(). - * - * Limit on the number of transactions we aggregate at once. Note - * that the limit must be big enough to ensure that when transactions - * of the smallest possible unit are aggregated, they do surpass the - * "tiny" threshold beyond which we never trigger a wire transaction! - */ -#define TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT 10000 + /** + * Find existing entry in the transient aggregation table. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto destination of the wire transfer + * @param cb function to call on each matching entry + * @param cb_cls closure for @a cb + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*find_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_TransientAggregationCallback cb, + void *cb_cls); + /** - * Obtain information about other pending deposits for the same - * destination. Those deposits must not already be "done". + * Update existing entry in the transient aggregation table. + * @a h_payto is only needed for query performance. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to the database - * @param h_wire destination of the wire transfer - * @param merchant_pub public key of the merchant - * @param deposit_cb function to call for each deposit - * @param deposit_cb_cls closure for @a deposit_cb - * @param limit maximum number of matching deposits to return; should - * be #TALER_EXCHANGEDB_MATCHING_DEPOSITS_LIMIT, larger values - * are not supported, smaller values would be inefficient. - * @return number of rows processed, 0 if none exist, - * transaction status code on error + * @param h_payto destination of the wire transfer + * @param wtid the raw wire transfer identifier to update + * @param kyc_requirement_row row in legitimization_requirements that need to be satisfied to continue, or 0 for none + * @param total new total amount to be wired in the future + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*iterate_matching_deposits)( + (*update_aggregation_transient)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *h_wire, - const struct TALER_MerchantPublicKeyP *merchant_pub, - TALER_EXCHANGEDB_DepositIterator deposit_cb, - void *deposit_cb_cls, - uint32_t limit); + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t kyc_requirement_row, + const struct TALER_Amount *total); /** - * Store new melt commitment data. + * Delete existing entry in the transient aggregation table. + * @a h_payto is only needed for query performance. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database handle to use - * @param refresh_session operational data to store - * @return query status for the transaction + * @param h_payto destination of the wire transfer + * @param wtid the raw wire transfer identifier to update + * @return transaction status */ enum GNUNET_DB_QueryStatus - (*insert_melt)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_EXCHANGEDB_Refresh *refresh_session); + (*delete_aggregation_transient)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_WireTransferIdentifierRawP *wtid); /** * Lookup melt commitment data under the given @a rc. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database handle to use * @param rc commitment to use for the lookup * @param[out] melt where to store the result; note that * melt->session.coin.denom_sig will be set to NULL * and is not fetched by this routine (as it is not needed by the client) + * @param[out] melt_serial_id set to the row ID of @a rc in the refresh_commitments table * @return transaction status */ enum GNUNET_DB_QueryStatus (*get_melt)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_RefreshCommitmentP *rc, - struct TALER_EXCHANGEDB_Melt *melt); - - - /** - * Lookup noreveal index of a previous melt operation under the given - * @a rc. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - * @param session database handle to use - * @param rc commitment hash to use to locate the operation - * @param[out] noreveal_index returns the "gamma" value selected by the - * exchange which is the index of the transfer key that is - * not to be revealed to the exchange - * @return transaction status - */ - enum GNUNET_DB_QueryStatus - (*get_melt_index)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_RefreshCommitmentP *rc, - uint32_t *noreveal_index); + struct TALER_EXCHANGEDB_Melt *melt, + uint64_t *melt_serial_id); /** @@ -2069,8 +4654,7 @@ struct TALER_EXCHANGEDB_Plugin * we learned or created in the reveal step. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection - * @param rc identify commitment and thus refresh operation + * @param melt_serial_id row ID of the commitment / melt operation in refresh_commitments * @param num_rrcs number of coins to generate, size of the @a rrcs array * @param rrcs information about the new coins * @param num_tprivs number of entries in @a tprivs, should be #TALER_CNC_KAPPA - 1 @@ -2081,8 +4665,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_refresh_reveal)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_RefreshCommitmentP *rc, + uint64_t melt_serial_id, uint32_t num_rrcs, const struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrcs, unsigned int num_tprivs, @@ -2091,11 +4674,10 @@ struct TALER_EXCHANGEDB_Plugin /** - * Lookup in the database for the @a num_freshcoins coins that we + * Lookup in the database for the fresh coins that we * created in the given refresh operation. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection * @param rc identify commitment and thus refresh operation * @param cb function to call with the results * @param cb_cls closure for @a cb @@ -2103,7 +4685,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*get_refresh_reveal)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_RefreshCommitmentP *rc, TALER_EXCHANGEDB_RefreshCallback cb, void *cb_cls); @@ -2116,7 +4697,6 @@ struct TALER_EXCHANGEDB_Plugin * the private keys of the new coins after the melt. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection * @param coin_pub public key of the coin * @param ldc function to call for each session the coin was melted into * @param ldc_cls closure for @a tdc @@ -2124,29 +4704,41 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*get_link_data)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_CoinSpendPublicKeyP *coin_pub, TALER_EXCHANGEDB_LinkCallback ldc, void *tdc_cls); /** - * 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 session database connection * @param coin_pub coin to investigate - * @param include_recoup include recoup transactions of the coin? - * @param[out] tlp set to list of transactions, NULL if coin is fresh + * @param start_off starting offset from which on to return entries + * @param etag_in up to this offset the client already has a response, do not + * return anything unless @a etag_out will be larger + * @param[out] etag_out set to the latest history offset known for this @a coin_pub + * @param[out] balance set to current balance of the coin + * @param[out] h_denom_pub set to denomination public key of the coin + * @param[out] tlp set to list of transactions, set to NULL if coin has no + * transaction history past @a start_off or if @a etag_in is equal + * to the value written to @a etag_out. * @return database transaction status */ enum GNUNET_DB_QueryStatus - (*get_coin_transactions)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - int include_recoup, - struct TALER_EXCHANGEDB_TransactionList **tlp); + (*get_coin_transactions)( + void *cls, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + uint64_t start_off, + uint64_t etag_in, + uint64_t *etag_out, + struct TALER_Amount *balance, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_TransactionList **tlp); /** @@ -2165,7 +4757,6 @@ struct TALER_EXCHANGEDB_Plugin * into a wire transfer by the respective @a raw_wtid. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session database connection * @param wtid the raw wire transfer identifier we used * @param cb function to call on each transaction found * @param cb_cls closure for @a cb @@ -2173,7 +4764,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*lookup_wire_transfer)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_WireTransferIdentifierRawP *wtid, TALER_EXCHANGEDB_AggregationDataCallback cb, void *cb_cls); @@ -2185,100 +4775,135 @@ struct TALER_EXCHANGEDB_Plugin * to be executed. * * @param cls closure - * @param session database connection * @param h_contract_terms hash of the proposal data * @param h_wire hash of merchant wire details * @param coin_pub public key of deposited coin * @param merchant_pub merchant public key - * @param cb function to call with the result - * @param cb_cls closure to pass to @a cb + * @param[out] pending set to true if the transaction is still pending + * @param[out] wtid wire transfer identifier, only set if @a pending is false + * @param[out] coin_contribution how much did the coin we asked about + * contribute to the total transfer value? (deposit value including fee) + * @param[out] coin_fee how much did the exchange charge for the deposit fee + * @param[out] execution_time when was the transaction done, or + * when we expect it to be done (if @a pending is false) + * @param[out] kyc set to the kyc status of the receiver (if @a pending) + * @param[out] aml_decision set to the current AML status for the target account * @return transaction status code */ enum GNUNET_DB_QueryStatus (*lookup_transfer_by_deposit)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *h_contract_terms, - const struct GNUNET_HashCode *h_wire, + const struct TALER_PrivateContractHashP *h_contract_terms, + const struct TALER_MerchantWireHashP *h_wire, const struct TALER_CoinSpendPublicKeyP *coin_pub, const struct TALER_MerchantPublicKeyP *merchant_pub, - TALER_EXCHANGEDB_WireTransferByCoinCallback cb, - void *cb_cls); + bool *pending, + struct TALER_WireTransferIdentifierRawP *wtid, + struct GNUNET_TIME_Timestamp *exec_time, + struct TALER_Amount *amount_with_fee, + struct TALER_Amount *deposit_fee, + struct TALER_EXCHANGEDB_KycStatus *kyc, + enum TALER_AmlDecisionState *aml_decision); /** - * Function called to insert aggregation information into the DB. + * Insert wire transfer fee into database. * * @param cls closure - * @param session database connection - * @param wtid the raw wire transfer identifier we used - * @param deposit_serial_id row in the deposits table for which this is aggregation data + * @param wire_method which wire method is the fee about? + * @param start_date when does the fee go into effect + * @param end_date when does the fee end being valid + * @param fees how high is are the wire fees + * @param master_sig signature over the above by the exchange master key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_aggregation_tracking)( - void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_WireTransferIdentifierRawP *wtid, - unsigned long long deposit_serial_id); + (*insert_wire_fee)(void *cls, + const char *wire_method, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_WireFeeSet *fees, + const struct TALER_MasterSignatureP *master_sig); /** - * Insert wire transfer fee into database. + * Insert global fee set into database. * * @param cls closure - * @param session database connection - * @param wire_method which wire method is the fee about? - * @param start_date when does the fee go into effect - * @param end_date when does the fee end being valid - * @param wire_fee how high is the wire transfer fee - * @param closing_fee how high is the closing fee + * @param start_date when does the fees go into effect + * @param end_date when does the fees end being valid + * @param fees how high is are the global fees + * @param purse_timeout when do purses time out + * @param history_expiration how long are account histories preserved + * @param purse_account_limit how many purses are free per account * @param master_sig signature over the above by the exchange master key * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*insert_wire_fee)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const char *wire_method, - struct GNUNET_TIME_Absolute start_date, - struct GNUNET_TIME_Absolute end_date, - const struct TALER_Amount *wire_fee, - const struct TALER_Amount *closing_fee, - const struct TALER_MasterSignatureP *master_sig); + (*insert_global_fee)(void *cls, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + const struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + uint32_t purse_account_limit, + + const struct TALER_MasterSignatureP *master_sig); /** * Obtain wire fee from database. * * @param cls closure - * @param session database connection * @param type type of wire transfer the fee applies for * @param date for which date do we want the fee? * @param[out] start_date when does the fee go into effect * @param[out] end_date when does the fee end being valid - * @param[out] wire_fee how high is the wire transfer fee - * @param[out] closing_fee how high is the closing fee + * @param[out] fees how high are the wire fees * @param[out] master_sig signature over the above by the exchange master key * @return query status of the transaction */ enum GNUNET_DB_QueryStatus (*get_wire_fee)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const char *type, - struct GNUNET_TIME_Absolute date, - struct GNUNET_TIME_Absolute *start_date, - struct GNUNET_TIME_Absolute *end_date, - struct TALER_Amount *wire_fee, - struct TALER_Amount *closing_fee, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_WireFeeSet *fees, struct TALER_MasterSignatureP *master_sig); /** + * Obtain global fees from database. + * + * @param cls closure + * @param date for which date do we want the fee? + * @param[out] start_date when does the fee go into effect + * @param[out] end_date when does the fee end being valid + * @param[out] fees how high are the global fees + * @param[out] purse_timeout when do purses time out + * @param[out] history_expiration how long are account histories preserved + * @param[out] purse_account_limit how many purses are free per account + * @param[out] master_sig signature over the above by the exchange master key + * @return query status of the transaction + */ + enum GNUNET_DB_QueryStatus + (*get_global_fee)(void *cls, + struct GNUNET_TIME_Timestamp date, + struct GNUNET_TIME_Timestamp *start_date, + struct GNUNET_TIME_Timestamp *end_date, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit, + struct TALER_MasterSignatureP *master_sig); + + + /** * Obtain information about expired reserves and their * remaining balances. * * @param cls closure of the plugin - * @param session database connection * @param now timestamp based on which we decide expiration * @param rec function to call on expired reserves * @param rec_cls closure for @a rec @@ -2286,41 +4911,186 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*get_expired_reserves)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - struct GNUNET_TIME_Absolute now, + struct GNUNET_TIME_Timestamp now, TALER_EXCHANGEDB_ReserveExpiredCallback rec, void *rec_cls); /** + * Obtain information about force-closed reserves + * where the close was not yet done (and their remaining + * balances). Updates the returned reserve's close + * status to "done". + * + * @param cls closure of the plugin + * @param rec function to call on (to be) closed reserves + * @param rec_cls closure for @a rec + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_unfinished_close_requests)( + void *cls, + TALER_EXCHANGEDB_ReserveExpiredCallback rec, + void *rec_cls); + + + /** + * Insert reserve open coin deposit data into database. + * Subtracts the @a coin_total from the coin's balance. + * + * @param cls closure + * @param cpi public information about the coin + * @param coin_sig signature with @e coin_pub of type #TALER_SIGNATURE_WALLET_RESERVE_OPEN_DEPOSIT + * @param known_coin_id ID of the coin in the known_coins table + * @param coin_total amount to be spent of the coin (including deposit fee) + * @param reserve_sig signature by the reserve affirming the open operation + * @param reserve_pub public key of the reserve being opened + * @param[out] insufficient_funds set to true if the coin's balance is insufficient, otherwise to false + * @return transaction status code, 0 if operation is already in the DB + */ + enum GNUNET_DB_QueryStatus + (*insert_reserve_open_deposit)( + void *cls, + const struct TALER_CoinPublicInfo *cpi, + const struct TALER_CoinSpendSignatureP *coin_sig, + uint64_t known_coin_id, + const struct TALER_Amount *coin_total, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *insufficient_funds); + + + /** + * Insert reserve close operation into database. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param total_paid total amount paid (coins and reserve) + * @param reserve_payment amount to be paid from the reserve + * @param min_purse_limit minimum number of purses we should be able to open + * @param reserve_sig signature by the reserve for the operation + * @param desired_expiration when should the reserve expire (earliest time) + * @param now when did we the client initiate the action + * @param open_fee annual fee to be charged for the open operation by the exchange + * @param[out] no_funds set to true if reserve balance is insufficient + * @param[out] reserve_balance set to original balance of the reserve + * @param[out] open_cost set to the actual cost + * @param[out] final_expiration when will the reserve expire now + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_reserve_open)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const struct TALER_Amount *total_paid, + const struct TALER_Amount *reserve_payment, + uint32_t min_purse_limit, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp desired_expiration, + struct GNUNET_TIME_Timestamp now, + const struct TALER_Amount *open_fee, + bool *no_funds, + struct TALER_Amount *reserve_balance, + struct TALER_Amount *open_cost, + struct GNUNET_TIME_Timestamp *final_expiration); + + + /** + * Select information needed to see if we can close + * a reserve. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param[out] balance current reserve balance + * @param[out] payto_uri set to URL of account that + * originally funded the reserve; + * could be set to NULL if not known + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + struct TALER_Amount *balance, + char **payto_uri); + + + /** + * Select information about reserve close requests. + * + * @param cls closure + * @param reserve_pub which reserve is this about? + * @param rowid row ID of the close request + * @param[out] reserve_sig reserve signature affirming + * @param[out] request_timestamp when was the request made + * @param[out] close_balance reserve balance at close time + * @param[out] close_fee closing fee to be charged + * @param[out] payto_uri set to URL of account that + * should receive the money; + * could be set to NULL for origin + * @return transaction status code, 0 if reserve unknown + */ + enum GNUNET_DB_QueryStatus + (*select_reserve_close_request_info)( + void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t rowid, + struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *close_balance, + struct TALER_Amount *close_fee, + char **payto_uri); + + + /** + * Select information needed for KYC checks on reserve close: historic + * reserve closures going to the same account. + * + * @param cls closure + * @param h_payto which target account is this about? + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*iterate_reserve_close_info)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** * Insert reserve close operation into database. * * @param cls closure - * @param session database connection * @param reserve_pub which reserve is this about? * @param execution_date when did we perform the transfer? * @param receiver_account to which account do we transfer, in payto://-format * @param wtid identifier for the wire transfer * @param amount_with_fee amount we charged to the reserve * @param closing_fee how high is the closing fee + * @param close_request_row identifies explicit close request, 0 for none * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_reserve_closed)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const struct TALER_ReservePublicKeyP *reserve_pub, - struct GNUNET_TIME_Absolute execution_date, + struct GNUNET_TIME_Timestamp execution_date, const char *receiver_account, - const struct TALER_WireTransferIdentifierRawP *wtid, + const struct + TALER_WireTransferIdentifierRawP *wtid, const struct TALER_Amount *amount_with_fee, - const struct TALER_Amount *closing_fee); + const struct TALER_Amount *closing_fee, + uint64_t close_request_row); /** * Function called to insert wire transfer commit data into the DB. * * @param cls closure - * @param session database connection * @param type type of the wire transfer (i.e. "iban") * @param buf buffer with wire transfer preparation data * @param buf_size number of bytes in @a buf @@ -2328,7 +5098,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*wire_prepare_data_insert)(void *cls, - struct TALER_EXCHANGEDB_Session *session, const char *type, const char *buf, size_t buf_size); @@ -2338,54 +5107,63 @@ struct TALER_EXCHANGEDB_Plugin * Function called to mark wire transfer commit data as finished. * * @param cls closure - * @param session database connection * @param rowid which entry to mark as finished * @return transaction status code */ enum GNUNET_DB_QueryStatus (*wire_prepare_data_mark_finished)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t rowid); /** + * Function called to mark wire transfer as failed. + * + * @param cls closure + * @param rowid which entry to mark as failed + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*wire_prepare_data_mark_failed)(void *cls, + uint64_t rowid); + + + /** * Function called to get an unfinished wire transfer - * preparation data. Fetches at most one item. + * preparation data. * * @param cls closure - * @param session database connection - * @param cb function to call for ONE unfinished item + * @param start_row offset to query table at + * @param limit maximum number of results to return + * @param cb function to call for unfinished work * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus (*wire_prepare_data_get)(void *cls, - struct TALER_EXCHANGEDB_Session *session, + uint64_t start_row, + uint64_t limit, TALER_EXCHANGEDB_WirePreparationIterator cb, void *cb_cls); /** - * Start a transaction where we transiently violate the foreign + * Starts a READ COMMITTED transaction where we transiently violate the foreign * constraints on the "wire_out" table as we insert aggregations * and only add the wire transfer out at the end. * * @param cls the @e cls of this struct with the plugin-specific state - * @param session connection to use * @return #GNUNET_OK on success */ - int - (*start_deferred_wire_out) (void *cls, - struct TALER_EXCHANGEDB_Session *session); + enum GNUNET_GenericReturnValue + (*start_deferred_wire_out)(void *cls); /** * Store information about an outgoing wire transfer that was executed. * * @param cls closure - * @param session database connection * @param date time of the wire transfer - * @param wtid subject of the wire transfer + * @param h_payto identifies the receiver account of the wire transfer * @param wire_account details about the receiver account of the wire transfer, * including 'url' in payto://-format * @param amount amount that was transmitted @@ -2396,10 +5174,9 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*store_wire_transfer_out)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - struct GNUNET_TIME_Absolute date, + struct GNUNET_TIME_Timestamp date, const struct TALER_WireTransferIdentifierRawP *wtid, - const json_t *wire_account, + const struct TALER_PaytoHashP *h_payto, const char *exchange_account_section, const struct TALER_Amount *amount); @@ -2412,8 +5189,8 @@ struct TALER_EXCHANGEDB_Plugin * @return #GNUNET_OK on success, * #GNUNET_SYSERR on DB errors */ - int - (*gc) (void *cls); + enum GNUNET_GenericReturnValue + (*gc)(void *cls); /** @@ -2421,25 +5198,150 @@ struct TALER_EXCHANGEDB_Plugin * order. * * @param cls closure - * @param session database connection * @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_deposits_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - uint64_t serial_id, - TALER_EXCHANGEDB_DepositCallback cb, - void *cb_cls); + (*select_coin_deposits_above_serial_id)(void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_DepositCallback cb, + void *cb_cls); + + + /** + * Function called to return meta data about a purses + * above a certain serial ID. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param serial_id number to select requests by + * @param cb function to call on each request + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_requests_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseRequestCallback cb, + void *cb_cls); + + + /** + * Select purse deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseDepositCallback cb, + void *cb_cls); + + + /** + * Select account merges above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_account_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AccountMergeCallback cb, + void *cb_cls); + + + /** + * Select purse merges deposits above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_merges_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_PurseMergeCallback cb, + void *cb_cls); + + + /** + * Select purse refunds above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param refunded which refund status to select for + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + bool refunded, + TALER_EXCHANGEDB_PurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select all purse refunds above @a serial_id in monotonically increasing + * order. + * + * @param cls closure + * @param serial_id highest serial ID to exclude (select strictly larger) + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_all_purse_decisions_above_serial_id)( + void *cls, + uint64_t serial_id, + TALER_EXCHANGEDB_AllPurseDecisionCallback cb, + void *cb_cls); + + + /** + * Select coins deposited into a purse. + * + * @param cls closure + * @param purse_pub public key of the purse + * @param cb function to call on each result + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_deposits_by_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + TALER_EXCHANGEDB_PurseRefundCoinCallback cb, + void *cb_cls); + /** * Select refresh sessions above @a serial_id in monotonically increasing * order. * * @param cls closure - * @param session database connection * @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 @@ -2447,7 +5349,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*select_refreshes_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_RefreshesCallback cb, void *cb_cls); @@ -2458,7 +5359,6 @@ struct TALER_EXCHANGEDB_Plugin * order. * * @param cls closure - * @param session database connection * @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 @@ -2466,7 +5366,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*select_refunds_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_RefundCallback cb, void *cb_cls); @@ -2477,7 +5376,6 @@ struct TALER_EXCHANGEDB_Plugin * in monotonically increasing order. * * @param cls closure - * @param session database connection * @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 @@ -2485,7 +5383,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*select_reserves_in_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_ReserveInCallback cb, void *cb_cls); @@ -2496,7 +5393,6 @@ struct TALER_EXCHANGEDB_Plugin * in monotonically increasing order by @a account_name. * * @param cls closure - * @param session database connection * @param account_name name of the account for which we do the selection * @param serial_id highest serial ID to exclude (select strictly larger) * @param cb function to call on each result @@ -2506,7 +5402,6 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_reserves_in_above_serial_id_by_account)( void *cls, - struct TALER_EXCHANGEDB_Session *session, const char *account_name, uint64_t serial_id, TALER_EXCHANGEDB_ReserveInCallback cb, @@ -2518,7 +5413,6 @@ struct TALER_EXCHANGEDB_Plugin * in monotonically increasing order. * * @param cls closure - * @param session database connection * @param account_name name of the account for which we do the selection * @param serial_id highest serial ID to exclude (select strictly larger) * @param cb function to call on each result @@ -2528,7 +5422,6 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_withdrawals_above_serial_id)( void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_WithdrawCallback cb, void *cb_cls); @@ -2539,7 +5432,6 @@ struct TALER_EXCHANGEDB_Plugin * executed, ordered by serial ID (monotonically increasing). * * @param cls closure - * @param session database connection * @param serial_id lowest serial ID to include (select larger or equal) * @param cb function to call for ONE unfinished item * @param cb_cls closure for @a cb @@ -2547,9 +5439,9 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*select_wire_out_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, - TALER_EXCHANGEDB_WireTransferOutCallback cb, + TALER_EXCHANGEDB_WireTransferOutCallback + cb, void *cb_cls); /** @@ -2557,7 +5449,6 @@ struct TALER_EXCHANGEDB_Plugin * executed, ordered by serial ID (monotonically increasing). * * @param cls closure - * @param session database connection * @param account_name name to select by * @param serial_id lowest serial ID to include (select larger or equal) * @param cb function to call for ONE unfinished item @@ -2567,7 +5458,6 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_wire_out_above_serial_id_by_account)( void *cls, - struct TALER_EXCHANGEDB_Session *session, const char *account_name, uint64_t serial_id, TALER_EXCHANGEDB_WireTransferOutCallback cb, @@ -2579,7 +5469,6 @@ struct TALER_EXCHANGEDB_Plugin * received, ordered by serial ID (monotonically increasing). * * @param cls closure - * @param session database connection * @param serial_id lowest serial ID to include (select larger or equal) * @param cb function to call for ONE unfinished item * @param cb_cls closure for @a cb @@ -2587,7 +5476,6 @@ struct TALER_EXCHANGEDB_Plugin */ enum GNUNET_DB_QueryStatus (*select_recoup_above_serial_id)(void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_RecoupCallback cb, void *cb_cls); @@ -2598,7 +5486,6 @@ struct TALER_EXCHANGEDB_Plugin * refreshed coins, ordered by serial ID (monotonically increasing). * * @param cls closure - * @param session database connection * @param serial_id lowest serial ID to include (select larger or equal) * @param cb function to call for ONE unfinished item * @param cb_cls closure for @a cb @@ -2607,86 +5494,45 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*select_recoup_refresh_above_serial_id)( void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, TALER_EXCHANGEDB_RecoupRefreshCallback cb, void *cb_cls); /** - * Function called to select reserve close operations the aggregator - * triggered, ordered by serial ID (monotonically increasing). + * Function called to select reserve open operations, ordered by serial ID + * (monotonically increasing). * * @param cls closure - * @param session database connection * @param serial_id lowest serial ID to include (select larger or equal) * @param cb function to call * @param cb_cls closure for @a cb * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*select_reserve_closed_above_serial_id)( + (*select_reserve_open_above_serial_id)( void *cls, - struct TALER_EXCHANGEDB_Session *session, uint64_t serial_id, - TALER_EXCHANGEDB_ReserveClosedCallback cb, + TALER_EXCHANGEDB_ReserveOpenCallback cb, void *cb_cls); /** - * Function called to add a request for an emergency recoup for a - * coin. The funds are to be added back to the reserve. - * - * @param cls closure - * @param session database connection - * @param reserve_pub public key of the reserve that is being refunded - * @param coin public information about a coin - * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP - * @param coin_blind blinding key of the coin - * @param h_blind_ev blinded envelope, as calculated by the exchange - * @param amount total amount to be paid back - * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) - * @param timestamp the timestamp to store - * @return transaction result status - */ - enum GNUNET_DB_QueryStatus - (*insert_recoup_request)( - void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_ReservePublicKeyP *reserve_pub, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_Amount *amount, - const struct GNUNET_HashCode *h_blind_ev, - struct GNUNET_TIME_Absolute timestamp); - - - /** - * Function called to add a request for an emergency recoup for a - * refreshed coin. The funds are to be added back to the original coin. - * - * @param cls closure - * @param session database connection - * @param coin public information about the refreshed coin - * @param coin_sig signature of the coin of type #TALER_SIGNATURE_WALLET_COIN_RECOUP - * @param coin_blind blinding key of the coin - * @param h_blind_ev blinded envelope, as calculated by the exchange - * @param amount total amount to be paid back - * @param h_blind_ev hash of the blinded coin's envelope (must match reserves_out entry) - * @param timestamp a timestamp to store - * @return transaction result status - */ + * Function called to select reserve close operations the aggregator + * triggered, ordered by serial ID (monotonically increasing). + * + * @param cls closure + * @param serial_id lowest serial ID to include (select larger or equal) + * @param cb function to call + * @param cb_cls closure for @a cb + * @return transaction status code + */ enum GNUNET_DB_QueryStatus - (*insert_recoup_refresh_request)( + (*select_reserve_closed_above_serial_id)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct TALER_CoinPublicInfo *coin, - const struct TALER_CoinSpendSignatureP *coin_sig, - const struct TALER_DenominationBlindingKeyP *coin_blind, - const struct TALER_Amount *amount, - const struct GNUNET_HashCode *h_blind_ev, - struct GNUNET_TIME_Absolute timestamp); + uint64_t serial_id, + TALER_EXCHANGEDB_ReserveClosedCallback cb, + void *cb_cls); /** @@ -2694,16 +5540,17 @@ struct TALER_EXCHANGEDB_Plugin * from given the hash of the blinded coin. * * @param cls closure - * @param session a session - * @param h_blind_ev hash of the blinded coin + * @param bch hash identifying the withdraw operation * @param[out] reserve_pub set to information about the reserve (on success only) + * @param[out] reserve_out_serial_id set to row of the @a h_blind_ev in reserves_out * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_reserve_by_h_blind)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *h_blind_ev, - struct TALER_ReservePublicKeyP *reserve_pub); + (*get_reserve_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *bch, + struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *reserve_out_serial_id); /** @@ -2711,16 +5558,17 @@ struct TALER_EXCHANGEDB_Plugin * given the hash of the blinded (fresh) coin. * * @param cls closure - * @param session a session * @param h_blind_ev hash of the blinded coin * @param[out] old_coin_pub set to information about the old coin (on success only) + * @param[out] rrc_serial set to the row of the @a h_blind_ev in the refresh_revealed_coins table * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_old_coin_by_h_blind)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *h_blind_ev, - struct TALER_CoinSpendPublicKeyP *old_coin_pub); + (*get_old_coin_by_h_blind)( + void *cls, + const struct TALER_BlindedCoinHashP *h_blind_ev, + struct TALER_CoinSpendPublicKeyP *old_coin_pub, + uint64_t *rrc_serial); /** @@ -2728,7 +5576,6 @@ struct TALER_EXCHANGEDB_Plugin * in the database. * * @param cls closure - * @param session a session * @param denom_pub_hash hash of the revoked denomination key * @param master_sig signature affirming the revocation * @return transaction status code @@ -2736,8 +5583,7 @@ struct TALER_EXCHANGEDB_Plugin enum GNUNET_DB_QueryStatus (*insert_denomination_revocation)( void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, + const struct TALER_DenominationHashP *denom_pub_hash, const struct TALER_MasterSignatureP *master_sig); @@ -2746,40 +5592,1652 @@ struct TALER_EXCHANGEDB_Plugin * the database. * * @param cls closure - * @param session a session * @param denom_pub_hash hash of the revoked denomination key * @param[out] master_sig signature affirming the revocation * @param[out] rowid row where the information is stored * @return transaction status code */ enum GNUNET_DB_QueryStatus - (*get_denomination_revocation)(void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *denom_pub_hash, - struct TALER_MasterSignatureP *master_sig, - uint64_t *rowid); + (*get_denomination_revocation)( + void *cls, + const struct TALER_DenominationHashP *denom_pub_hash, + struct TALER_MasterSignatureP *master_sig, + uint64_t *rowid); /** - * Select all of those deposits in the database for which we do - * not have a wire transfer (or a refund) and which should have - * been deposited between @a start_date and @a end_date. + * Select all (batch) deposits in the database + * above a given @a min_batch_deposit_serial_id. * * @param cls closure - * @param session a session - * @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 TALER_EXCHANGEDB_Session *session, - struct GNUNET_TIME_Absolute start_date, - struct GNUNET_TIME_Absolute end_date, - TALER_EXCHANGEDB_WireMissingCallback cb, - void *cb_cls); + (*select_batch_deposits_missing_wire)( + void *cls, + uint64_t min_batch_deposit_serial_id, + TALER_EXCHANGEDB_WireMissingCallback cb, + void *cb_cls); + + + /** + * Select all aggregation tracking IDs in the database + * above a given @a min_tracking_serial_id. + * + * @param cls closure + * @param min_tracking_serial_id only return entries strictly above this row (and in order) + * @param cb function to call on all such aggregations + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_aggregations_above_serial)( + void *cls, + uint64_t min_tracking_serial_id, + TALER_EXCHANGEDB_AggregationCallback cb, + void *cb_cls); + + + /** + * Return any applicable justification as to why + * a wire transfer might have been held. Used + * by the auditor to determine if a wire transfer + * is legitimately stalled. + * + * @param cls closure + * @param wire_target_h_payto effected target account + * @param[out] payto_uri target account URI, set to NULL if unknown + * @param[out] kyc_pending set to string describing missing KYC data + * @param[out] status set to AML status + * @param[out] aml_limit set to AML limit, or invalid amount for none + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_justification_for_missing_wire)( + void *cls, + const struct TALER_PaytoHashP *wire_target_h_payto, + char **payto_uri, + char **kyc_pending, + enum TALER_AmlDecisionState *status, + struct TALER_Amount *aml_limit); + + + /** + * Check the last date an auditor was modified. + * + * @param cls closure + * @param auditor_pub key to look up information for + * @param[out] last_date last modification date to auditor status + * @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 current state of an auditor. + * + * @param cls closure + * @param auditor_pub key to look up information for + * @param[out] auditor_url set to the base URL of the auditor's REST API; memory to be + * released by the caller! + * @param[out] enabled set if the auditor is currently in use + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_auditor_status)( + void *cls, + const struct TALER_AuditorPublicKeyP *auditor_pub, + char **auditor_url, + bool *enabled); + + + /** + * Insert information about an auditor that will audit this exchange. + * + * @param cls closure + * @param auditor_pub key of the auditor + * @param auditor_url base URL of the auditor's REST service + * @param auditor_name name of the auditor (for humans) + * @param start_date date when the auditor was added by the offline system + * (only to be used for replay detection) + * @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); + + + /** + * Update information about an auditor that will audit this exchange. + * + * @param cls closure + * @param auditor_pub key of the auditor (primary key for the existing record) + * @param auditor_url base URL of the auditor's REST service, to be updated + * @param auditor_name name of the auditor (for humans) + * @param change_date date when the auditor status was last changed + * (only to be used for replay detection) + * @param enabled true to enable, false to disable + * @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); + + + /** + * Check the last date an exchange wire account was modified. + * + * @param cls closure + * @param payto_uri key to look up information for + * @param[out] last_date last modification date to auditor status + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_wire_timestamp)(void *cls, + const char *payto_uri, + struct GNUNET_TIME_Timestamp *last_date); + + + /** + * Insert information about an wire account used by this exchange. + * + * @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 char *bank_label, + int64_t priority); + + + /** + * Update information about a wire account of the exchange. + * + * @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); + + + /** + * Obtain information about the enabled wire accounts of the exchange. + * + * @param cls closure + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_wire_accounts)(void *cls, + TALER_EXCHANGEDB_WireAccountCallback cb, + void *cb_cls); + + + /** + * Obtain information about the fee structure of the exchange for + * a given @a wire_method + * + * @param cls closure + * @param wire_method which wire method to obtain fees for + * @param cb function to call on each account + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_wire_fees)(void *cls, + const char *wire_method, + TALER_EXCHANGEDB_WireFeeCallback cb, + void *cb_cls); + + + /** + * Obtain information about the global fee structure of the exchange. + * + * @param cls closure + * @param cb function to call on each fee entry + * @param cb_cls closure for @a cb + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_global_fees)(void *cls, + TALER_EXCHANGEDB_GlobalFeeCallback cb, + void *cb_cls); + + + /** + * Store information about a revoked online signing key. + * + * @param cls closure + * @param exchange_pub exchange online signing key that was revoked + * @param master_sig signature affirming the revocation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_signkey_revocation)( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Obtain information about a revoked online signing key. + * + * @param cls closure + * @param exchange_pub exchange online signing key that was revoked + * @param[out] master_sig signature affirming the revocation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_signkey_revocation)( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_MasterSignatureP *master_sig); + + + /** + * Lookup information about current denomination key. + * + * @param cls closure + * @param h_denom_pub hash of the denomination public key + * @param[out] meta set to various meta data about the key + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_denomination_key)( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta); + + + /** + * Add denomination key. + * + * @param cls closure + * @param h_denom_pub hash of the denomination public key + * @param denom_pub the denomination public key + * @param meta meta data about the denomination + * @param master_sig master signature to add + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*add_denomination_key)( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_DenominationPublicKey *denom_pub, + const struct TALER_EXCHANGEDB_DenominationKeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Activate future signing key, turning it into a "current" or "valid" + * denomination key by adding the master signature. + * + * @param cls closure + * @param exchange_pub the exchange online signing public key + * @param meta meta data about @a exchange_pub + * @param master_sig master signature to add + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*activate_signing_key)( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + const struct TALER_EXCHANGEDB_SignkeyMetaData *meta, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Lookup signing key meta data. + * + * @param cls closure + * @param exchange_pub the exchange online signing public key + * @param[out] meta meta data about @a exchange_pub + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_signing_key)( + void *cls, + const struct TALER_ExchangePublicKeyP *exchange_pub, + struct TALER_EXCHANGEDB_SignkeyMetaData *meta); + + + /** + * Insert information about an auditor auditing a denomination key. + * + * @param cls closure + * @param h_denom_pub the audited denomination + * @param auditor_pub the auditor's key + * @param auditor_sig signature affirming the auditor's audit activity + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_auditor_denom_sig)( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + const struct TALER_AuditorSignatureP *auditor_sig); + + + /** + * Obtain information about an auditor auditing a denomination key. + * + * @param cls closure + * @param h_denom_pub the audited denomination + * @param auditor_pub the auditor's key + * @param[out] auditor_sig set to signature affirming the auditor's audit activity + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_auditor_denom_sig)( + void *cls, + const struct TALER_DenominationHashP *h_denom_pub, + const struct TALER_AuditorPublicKeyP *auditor_pub, + struct TALER_AuditorSignatureP *auditor_sig); + + + /** + * Lookup information about known wire fees. + * + * @param cls closure + * @param wire_method the wire method to lookup fees for + * @param start_time starting time of fee + * @param end_time end time of fee + * @param[out] fees set to wire fees for that time period; if + * different wire fee exists within this time + * period, an 'invalid' amount is returned. + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_wire_fee_by_time)( + void *cls, + const char *wire_method, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_WireFeeSet *fees); + + + /** + * Lookup information about known global fees. + * + * @param cls closure + * @param start_time starting time of fee + * @param end_time end time of fee + * @param[out] fees set to wire fees for that time period; if + * different global fee exists within this time + * period, an 'invalid' amount is returned. + * @param[out] purse_timeout set to when unmerged purses expire + * @param[out] history_expiration set to when we expire reserve histories + * @param[out] purse_account_limit set to number of free purses + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*lookup_global_fee_by_time)( + void *cls, + struct GNUNET_TIME_Timestamp start_time, + struct GNUNET_TIME_Timestamp end_time, + struct TALER_GlobalFeeSet *fees, + struct GNUNET_TIME_Relative *purse_timeout, + struct GNUNET_TIME_Relative *history_expiration, + uint32_t *purse_account_limit); + + + /** + * Lookup the latest serial number of @a table. Used in + * exchange-auditor database replication. + * + * @param cls closure + * @param table table for which we should return the serial + * @param[out] latest serial number in use + * @return transaction status code, #GNUNET_DB_STATUS_HARD_ERROR if + * @a table does not have a serial number + */ + enum GNUNET_DB_QueryStatus + (*lookup_serial_by_table)(void *cls, + enum TALER_EXCHANGEDB_ReplicatedTable table, + uint64_t *serial); + + /** + * Lookup records above @a serial number in @a table. Used in + * exchange-auditor database replication. + * + * @param cls closure + * @param table table for which we should return the serial + * @param serial largest serial number to exclude + * @param cb function to call on the records + * @param cb_cls closure for @a cb + * @return transaction status code, GNUNET_DB_STATUS_HARD_ERROR if + * @a table does not have a serial number + */ + enum GNUNET_DB_QueryStatus + (*lookup_records_by_table)(void *cls, + enum TALER_EXCHANGEDB_ReplicatedTable table, + uint64_t serial, + TALER_EXCHANGEDB_ReplicationCallback cb, + void *cb_cls); + + + /** + * 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 + * @a table does not have a serial number + */ + enum GNUNET_DB_QueryStatus + (*insert_records_by_table)(void *cls, + const struct TALER_EXCHANGEDB_TableData *td); + + + /** + * Function called to grab a work shard on an operation @a op. Runs in its + * own transaction. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param delay minimum age of a shard to grab + * @param size desired shard size + * @param[out] start_row inclusive start row of the shard (returned) + * @param[out] end_row exclusive end row of the shard (returned) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*begin_shard)(void *cls, + const char *job_name, + struct GNUNET_TIME_Relative delay, + uint64_t shard_size, + uint64_t *start_row, + uint64_t *end_row); + + /** + * Function called to abort work on a shard. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to abort a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*abort_shard)(void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row); + + /** + * Function called to persist that work on a shard was completed. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param start_row inclusive start row of the shard + * @param end_row exclusive end row of the shard + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*complete_shard)(void *cls, + const char *job_name, + uint64_t start_row, + uint64_t end_row); + + + /** + * Function called to grab a revolving work shard on an operation @a op. Runs + * in its own transaction. Returns the oldest inactive shard. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a revolving shard for + * @param shard_size desired shard size + * @param shard_limit exclusive end of the shard range + * @param[out] start_row inclusive start row of the shard (returned) + * @param[out] end_row inclusive end row of the shard (returned) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*begin_revolving_shard)(void *cls, + const char *job_name, + uint32_t shard_size, + uint32_t shard_limit, + uint32_t *start_row, + uint32_t *end_row); + + + /** + * Function called to release a revolving shard back into the work pool. + * Clears the "completed" flag. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param job_name name of the operation to grab a word shard for + * @param start_row inclusive start row of the shard + * @param end_row inclusive end row of the shard + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*release_revolving_shard)(void *cls, + const char *job_name, + uint32_t start_row, + uint32_t end_row); + + + /** + * Function called to delete all revolving shards. + * To be used after a crash or when the shard size is + * changed. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @return #GNUNET_OK on success + * #GNUNET_SYSERR on failure + */ + enum GNUNET_GenericReturnValue + (*delete_shard_locks)(void *cls); + + + /** + * Function called to save the manifest of an extension + * (age-restriction, policy-extension, ...) + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param extension_name the name of the extension + * @param manifest JSON object of the Manifest as string, maybe NULL (== disabled extension) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*set_extension_manifest)(void *cls, + const char *extension_name, + const char *manifest); + + + /** + * Function called to retrieve the manifest of an extension + * (age-restriction, policy-extension, ...) + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param extension_name the name of the extension + * @param[out] manifest Manifest of the extension in JSON encoding, maybe NULL (== disabled extension) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_extension_manifest)(void *cls, + const char *extension_name, + char **manifest); + + + /** + * Function called to store configuration data about a partner + * exchange that we are federated with. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param master_pub public offline signing key of the partner exchange + * @param start_date when does the following data start to be valid + * @param end_date when does the validity end (exclusive) + * @param wad_frequency how often do we do exchange-to-exchange settlements? + * @param wad_fee how much do we charge for transfers to the partner + * @param partner_base_url base URL of the partner exchange + * @param master_sig signature with our offline signing key affirming the above + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_partner)(void *cls, + const struct TALER_MasterPublicKeyP *master_pub, + struct GNUNET_TIME_Timestamp start_date, + struct GNUNET_TIME_Timestamp end_date, + struct GNUNET_TIME_Relative wad_frequency, + const struct TALER_Amount *wad_fee, + const char *partner_base_url, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Function called to persist an encrypted contract associated with a reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param econtract the encrypted contract + * @param[out] econtract_sig set to the signature over the encrypted contract + * @param[out] in_conflict set to true if @a econtract + * conflicts with an existing contract; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_contract)(void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_EncryptedContract *econtract, + bool *in_conflict); + + + /** + * Function called to retrieve an encrypted contract. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pub_ckey set to the ephemeral DH used to encrypt the contract, key used to lookup the contract by + * @param[out] purse_pub public key of the purse of the contract + * @param[out] econtract_sig set to the signature over the encrypted contract + * @param[out] econtract_size set to the number of bytes in @a econtract + * @param[out] econtract set to the encrypted contract on success, to be freed by the caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_contract)( + void *cls, + const struct TALER_ContractDiffiePublicP *pub_ckey, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseContractSignatureP *econtract_sig, + size_t *econtract_size, + void **econtract); + + + /** + * Function called to retrieve an encrypted contract. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub key to lookup the contract by + * @param[out] econtract set to the encrypted contract on success, to be freed by the caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_contract_by_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_EncryptedContract *econtract); + + + /** + * Function called to create a new purse with certain meta data. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the new purse + * @param merge_pub public key providing the merge capability + * @param purse_expiration time when the purse will expire + * @param h_contract_terms hash of the contract for the purse + * @param age_limit age limit to enforce for payments into the purse + * @param flags flags for the operation + * @param purse_fee fee we are allowed to charge to the reserve (depending on @a flags) + * @param amount target amount (with fees) to be put into the purse + * @param purse_sig signature with @a purse_pub's private key affirming the above + * @param[out] in_conflict set to true if the meta data + * conflicts with an existing purse; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_purse_request)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp purse_expiration, + const struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t age_limit, + enum TALER_WalletAccountMergeFlags flags, + const struct TALER_Amount *purse_fee, + const struct TALER_Amount *amount, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *in_conflict); + + + /** + * Function called to clean up one expired purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param start_time select purse expired after this time + * @param end_time select purse expired before this time + * @return transaction status code (#GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if no purse expired in the given time interval). + */ + enum GNUNET_DB_QueryStatus + (*expire_purse)( + void *cls, + struct GNUNET_TIME_Absolute start_time, + struct GNUNET_TIME_Absolute end_time); + + + /** + * Function called to obtain information about a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the new purse + * @param[out] purse_creation set to time when the purse was created + * @param[out] purse_expiration set to time when the purse will expire + * @param[out] amount set to target amount (with fees) to be put into the purse + * @param[out] deposited set to actual amount put into the purse so far + * @param[out] h_contract_terms set to hash of the contract for the purse + * @param[out] merge_timestamp set to time when the purse was merged, or NEVER if not + * @param[out] purse_deleted set to true if purse was deleted + * @param[out] purse_refunded set to true if purse was refunded (after expiration) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_creation, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_Amount *amount, + struct TALER_Amount *deposited, + struct TALER_PrivateContractHashP *h_contract_terms, + struct GNUNET_TIME_Timestamp *merge_timestamp, + bool *purse_deleted, + bool *purse_refunded); + + + /** + * Function called to return meta data about a purse by the + * purse public key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the purse + * @param[out] merge_pub public key representing the merge capability + * @param[out] purse_expiration when would an unmerged purse expire + * @param[out] h_contract_terms contract associated with the purse + * @param[out] age_limit the age limit for deposits into the purse + * @param[out] target_amount amount to be put into the purse + * @param[out] balance amount put so far into the purse + * @param[out] purse_sig signature of the purse over the initialization data + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_purse_request)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergePublicKeyP *merge_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig); + + + /** + * Function called to return meta data about a purse by the + * merge capability key. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param merge_pub public key representing the merge capability + * @param[out] purse_pub public key of the purse + * @param[out] purse_expiration when would an unmerged purse expire + * @param[out] h_contract_terms contract associated with the purse + * @param[out] age_limit the age limit for deposits into the purse + * @param[out] target_amount amount to be put into the purse + * @param[out] balance amount put so far into the purse + * @param[out] purse_sig signature of the purse over the initialization data + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_by_merge_pub)( + void *cls, + const struct TALER_PurseMergePublicKeyP *merge_pub, + struct TALER_PurseContractPublicKeyP *purse_pub, + struct GNUNET_TIME_Timestamp *purse_expiration, + struct TALER_PrivateContractHashP *h_contract_terms, + uint32_t *age_limit, + struct TALER_Amount *target_amount, + struct TALER_Amount *balance, + struct TALER_PurseContractSignatureP *purse_sig); + + + /** + * Function called to execute a transaction crediting + * a purse with @a amount from @a coin_pub. Reduces the + * value of @a coin_pub and increase the balance of + * the @a purse_pub purse. If the balance reaches the + * target amount and the purse has been merged, triggers + * the updates of the reserve/account balance. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to credit + * @param coin_pub coin to deposit (debit) + * @param amount fraction of the coin's value to deposit + * @param coin_sig signature affirming the operation + * @param amount_minus_fee amount to add to the purse + * @param[out] balance_ok set to false if the coin's + * remaining balance is below @a amount; + * in this case, the return value will be + * #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT despite the failure + * @param[out] too_late it is too late to deposit into this purse + * @param[out] conflict the same coin was deposited into + * this purse with a different amount already + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_deposit)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_Amount *amount, + const struct TALER_CoinSpendSignatureP *coin_sig, + const struct TALER_Amount *amount_minus_fee, + bool *balance_ok, + bool *too_late, + bool *conflict); + + + /** + * Function called to explicitly delete a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to delete + * @param purse_sig signature affirming the deletion + * @param[out] decided set to true if the purse was + * already decided and thus could not be deleted + * @param[out] found set to true if the purse was found + * (if false, purse could not be deleted) + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_delete)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseContractSignatureP *purse_sig, + bool *decided, + bool *found); + + + /** + * Set the current @a balance in the purse + * identified by @a purse_pub. Used by the auditor + * to update the balance as calculated by the auditor. + * + * @param cls closure + * @param purse_pub public key of a purse + * @param balance new balance to store under the purse + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*set_purse_balance)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_Amount *balance); + + + /** + * Function called to obtain a coin deposit data from + * depositing the coin into a purse. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to credit + * @param coin_pub coin to deposit (debit) + * @param[out] amount set fraction of the coin's value that was deposited (with fee) + * @param[out] h_denom_pub set to hash of denomination of the coin + * @param[out] phac set to hash of age restriction on the coin + * @param[out] coin_sig set to signature affirming the operation + * @param[out] partner_url set to the URL of the partner exchange, or NULL for ourselves, must be freed by caller + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_purse_deposit)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_Amount *amount, + struct TALER_DenominationHashP *h_denom_pub, + struct TALER_AgeCommitmentHash *phac, + struct TALER_CoinSpendSignatureP *coin_sig, + char **partner_url); + + + /** + * Function called to approve merging a purse into a + * reserve by the respective purse merge key. The purse + * must not have been merged into a different reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to merge + * @param merge_sig signature affirming the merge + * @param merge_timestamp time of the merge + * @param reserve_sig signature of the reserve affirming the merge + * @param partner_url URL of the partner exchange, can be NULL if the reserves lives with us + * @param reserve_pub public key of the reserve to credit + * @param[out] no_partner set to true if @a partner_url is unknown + * @param[out] no_balance set to true if the @a purse_pub is not paid up yet + * @param[out] no_reserve set to true if the @a reserve_pub is not known + * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_purse_merge)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const char *partner_url, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *no_partner, + bool *no_balance, + bool *in_conflict); + + + /** + * Function called insert request to merge a purse into a reserve by the + * respective purse merge key. The purse must not have been merged into a + * different reserve. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub purse to merge + * @param merge_sig signature affirming the merge + * @param merge_timestamp time of the merge + * @param reserve_sig signature of the reserve affirming the merge + * @param purse_fee amount to charge the reserve for the purse creation, NULL to use the quota + * @param reserve_pub public key of the reserve to credit + * @param[out] in_conflict set to true if @a purse_pub was merged into a different reserve already + * @param[out] no_reserve set to true if @a reserve_pub is not a known reserve + * @param[out] insufficient_funds set to true if @a reserve_pub has insufficient capacity to create another purse + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*do_reserve_purse)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + const struct TALER_PurseMergeSignatureP *merge_sig, + const struct GNUNET_TIME_Timestamp merge_timestamp, + const struct TALER_ReserveSignatureP *reserve_sig, + const struct TALER_Amount *purse_fee, + const struct TALER_ReservePublicKeyP *reserve_pub, + bool *in_conflict, + bool *no_reserve, + bool *insufficient_funds); + + + /** + * Function called to approve merging of a purse with + * an account, made by the receiving account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param purse_pub public key of the purse + * @param[out] merge_sig set to the signature confirming the merge + * @param[out] merge_timestamp set to the time of the merge + * @param[out] partner_url set to the URL of the target exchange, or NULL if the target exchange is us. To be freed by the caller. + * @param[out] reserve_pub set to the public key of the reserve/account being credited + * @param[out] refunded set to true if purse was refunded + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_purse_merge)( + void *cls, + const struct TALER_PurseContractPublicKeyP *purse_pub, + struct TALER_PurseMergeSignatureP *merge_sig, + struct GNUNET_TIME_Timestamp *merge_timestamp, + char **partner_url, + struct TALER_ReservePublicKeyP *reserve_pub, + bool *refunded); + + + /** + * Function called to initiate closure of an account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param reserve_pub public key of the account to close + * @param payto_uri where to wire the funds + * @param reserve_sig signature affiming that the account is to be closed + * @param request_timestamp timestamp of the close request + * @param balance balance at the time of closing + * @param closing_fee closing fee to charge + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_close_request)(void *cls, + const struct TALER_ReservePublicKeyP *reserve_pub, + const char *payto_uri, + const struct TALER_ReserveSignatureP *reserve_sig, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *balance, + const struct TALER_Amount *closing_fee); + + + /** + * Function called to persist a request to drain profits. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wtid wire transfer ID to use + * @param account_section account to drain + * @param payto_uri account to wire funds to + * @param request_timestamp time of the signature + * @param amount amount to wire + * @param master_sig signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*insert_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + const char *account_section, + const char *payto_uri, + struct GNUNET_TIME_Timestamp request_timestamp, + const struct TALER_Amount *amount, + const struct TALER_MasterSignatureP *master_sig); + + + /** + * Function called to get information about a profit drain event. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param wtid wire transfer ID to look up drain event for + * @param[out] serial set to serial ID of the entry + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*get_drain_profit)(void *cls, + const struct TALER_WireTransferIdentifierRawP *wtid, + uint64_t *serial, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); + + + /** + * Get profit drain operation ready to execute. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param[out] serial set to serial ID of the entry + * @param[out] wtid set set to wire transfer ID to use + * @param[out] account_section set to account to drain + * @param[out] payto_uri set to account to wire funds to + * @param[out] request_timestamp set to time of the signature + * @param[out] amount set to amount to wire + * @param[out] master_sig set to signature affirming the operation + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*profit_drains_get_pending)( + void *cls, + uint64_t *serial, + struct TALER_WireTransferIdentifierRawP *wtid, + char **account_section, + char **payto_uri, + struct GNUNET_TIME_Timestamp *request_timestamp, + struct TALER_Amount *amount, + struct TALER_MasterSignatureP *master_sig); + + + /** + * Set profit drain operation to finished. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param serial serial ID of the entry to mark finished + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*profit_drains_set_finished)( + void *cls, + uint64_t serial); + + + /** + * Insert KYC requirement for @a h_payto account into table. + * + * @param cls closure + * @param requirements requirements that must be checked + * @param h_payto account that must be KYC'ed + * @param reserve_pub if account is a reserve, its public key, NULL otherwise + * @param[out] requirement_row set to legitimization requirement row for this check + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_requirement_for_account)( + void *cls, + const char *requirements, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_ReservePublicKeyP *reserve_pub, + uint64_t *requirement_row); + + + /** + * Begin KYC requirement process. + * + * @param cls closure + * @param h_payto account that must be KYC'ed + * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param[out] process_row row the process is stored under + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id, + uint64_t *process_row); + + + /** + * Fetch information about pending KYC requirement process. + * + * @param cls closure + * @param h_payto account that must be KYC'ed + * @param provider_section provider that must be checked + * @param[out] redirect_url set to redirect URL for the process + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*get_pending_kyc_requirement_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + char **redirect_url); + + + /** + * Update KYC process with updated provider-linkage and/or + * expiration data. + * + * @param cls closure + * @param process_row row to select by + * @param provider_section provider that must be checked (technically redundant) + * @param h_payto account that must be KYC'ed (helps access by shard, otherwise also redundant) + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param redirect_url where the user should be redirected to start the KYC process + * @param expiration how long is this KYC check set to be valid (in the past if invalid) + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*update_kyc_process_by_row)( + void *cls, + uint64_t process_row, + const char *provider_section, + const struct TALER_PaytoHashP *h_payto, + const char *provider_account_id, + const char *provider_legitimization_id, + const char *redirect_url, + struct GNUNET_TIME_Absolute expiration); + + + /** + * Lookup KYC requirement. + * + * @param cls closure + * @param legi_row identifies requirement to look up + * @param[out] requirements space-separated list of requirements + * @param[out] aml_status set to the AML status of the account + * @param[out] h_payto account that must be KYC'ed + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_kyc_requirement_by_row)( + void *cls, + uint64_t requirement_row, + char **requirements, + enum TALER_AmlDecisionState *aml_status, + struct TALER_PaytoHashP *h_payto); + + + /** + * Lookup KYC process meta data. + * + * @param cls closure + * @param provider_section provider that must be checked + * @param h_payto account that must be KYC'ed + * @param[out] process_row set to row with the legitimization data + * @param[out] expiration how long is this KYC check set to be valid (in the past if invalid) + * @param[out] provider_account_id provider account ID + * @param[out] provider_legitimization_id provider legitimization ID + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_kyc_process_by_account)( + void *cls, + const char *provider_section, + const struct TALER_PaytoHashP *h_payto, + uint64_t *process_row, + struct GNUNET_TIME_Absolute *expiration, + char **provider_account_id, + char **provider_legitimization_id); + + + /** + * Lookup an + * @a h_payto by @a provider_legitimization_id. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @param[out] process_row identifies the legitimization process on our end + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*kyc_provider_account_lookup)( + void *cls, + const char *provider_section, + const char *provider_legitimization_id, + struct TALER_PaytoHashP *h_payto, + uint64_t *process_row); + + + /** + * Call us on KYC processes satisfied for the given + * account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*select_satisfied_kyc_processes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_SatisfiedProviderCallback spc, + void *spc_cls); + + + /** + * Call us on KYC legitimization processes satisfied and not expired for the + * given account. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param lpc function to call for each satisfied KYC legitimization process + * @param lpc_cls closure for @a lpc + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*iterate_kyc_reference)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_LegitimizationProcessCallback lpc, + void *lpc_cls); + + + /** + * Call @a kac on withdrawn amounts after @a time_limit which are relevant + * for a KYC trigger for a the (debited) account identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_withdraw_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on aggregated amounts after @a time_limit which are relevant for a + * KYC trigger for a the (credited) account identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_aggregation_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Call @a kac on merged reserve amounts after @a time_limit which are relevant for a + * KYC trigger for a the wallet identified by @a h_payto. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param time_limit oldest transaction that could be relevant + * @param kac function to call for each applicable amount, in reverse chronological order (or until @a kac aborts by returning anything except #GNUNET_OK). + * @param kac_cls closure for @a kac + * @return transaction status code, @a kac aborting with #GNUNET_NO is not an error + */ + enum GNUNET_DB_QueryStatus + (*select_merge_amounts_for_kyc_check)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + struct GNUNET_TIME_Absolute time_limit, + TALER_EXCHANGEDB_KycAmountCallback kac, + void *kac_cls); + + + /** + * Store KYC attribute data, update KYC process status and + * AML status for the given account. + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param kyc_prox key for similarity search + * @param provider_section provider that must be checked + * @param num_checks how many checks do these attributes satisfy + * @param satisfied_checks array of checks satisfied by these attributes + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @param birthday birthdate of user, in days after 1990, or 0 if unknown or definitively adult + * @param collection_time when was the data collected + * @param expiration_time when does the data expire + * @param enc_attributes_size number of bytes in @a enc_attributes + * @param enc_attributes encrypted attribute data + * @param require_aml true to trigger AML + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_attributes)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const struct GNUNET_ShortHashCode *kyc_prox, + const char *provider_section, + unsigned int num_checks, + const char *satisfied_checks[static num_checks], + uint32_t birthday, + struct GNUNET_TIME_Timestamp collection_time, + const char *provider_account_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration_time, + size_t enc_attributes_size, + const void *enc_attributes, + bool require_aml); + + + /** + * Lookup similar KYC attribute data. + * + * @param cls closure + * @param kyc_prox key for similarity search + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_similar_kyc_attributes)( + void *cls, + const struct GNUNET_ShortHashCode *kyc_prox, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Lookup KYC attribute data for a specific account. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_kyc_attributes)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AttributeCallback cb, + void *cb_cls); + + + /** + * Insert AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param master_sig offline signature affirming the AML officer + * @param decider_name full name of the staff member + * @param is_active true to enable, false to set as inactive + * @param read_only true to set read-only access + * @param last_change when was the change made effective + * @param[out] previous_change when was the previous change made + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_MasterSignatureP *master_sig, + const char *decider_name, + bool is_active, + bool read_only, + struct GNUNET_TIME_Timestamp last_change, + struct GNUNET_TIME_Timestamp *previous_change); + + + /** + * Test if the given AML staff member is active + * (at least read-only). + * + * @param cls closure + * @param decider_pub public key of the staff member + * @return database transaction status, if member is unknown or not active, 1 if member is active + */ + enum GNUNET_DB_QueryStatus + (*test_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub); + + + /** + * Fetch AML staff record. + * + * @param cls closure + * @param decider_pub public key of the staff member + * @param[out] master_sig offline signature affirming the AML officer + * @param[out] decider_name full name of the staff member + * @param[out] is_active true to enable, false to set as inactive + * @param[out] read_only true to set read-only access + * @param[out] last_change when was the change made effective + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*lookup_aml_officer)( + void *cls, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + struct TALER_MasterSignatureP *master_sig, + char **decider_name, + bool *is_active, + bool *read_only, + struct GNUNET_TIME_Absolute *last_change); + + + /** + * Obtain the current AML threshold set for an account. + * + * @param cls closure + * @param h_payto account for which the AML threshold is stored + * @param[out] decision set to current AML decision + * @param[out] threshold set to the existing threshold + * @return database transaction status, 0 if no threshold was set + */ + enum GNUNET_DB_QueryStatus + (*select_aml_threshold)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + enum TALER_AmlDecisionState *decision, + struct TALER_EXCHANGEDB_KycStatus *kyc, + struct TALER_Amount *threshold); + + + /** + * Trigger AML process, an account has crossed the threshold. Inserts or + * updates the AML status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param threshold_crossed existing threshold that was crossed + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*trigger_aml_process)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *threshold_crossed); + + + /** + * Lookup AML decisions that have a particular state. + * + * @param cls closure + * @param decision which decision states to filter by + * @param row_off offset to start from + * @param forward true to go forward in time, false to go backwards + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_process)( + void *cls, + enum TALER_AmlDecisionState decision, + uint64_t row_off, + uint64_t limit, + bool forward, + TALER_EXCHANGEDB_AmlStatusCallback cb, + void *cb_cls); + + + /** + * Lookup AML decision history for a particular account. + * + * @param cls closure + * @param h_payto which account should we return the AML decision history for + * @param cb callback to invoke on each match + * @param cb_cls closure for @a cb + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*select_aml_history)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_AmlHistoryCallback cb, + void *cb_cls); + + + /** + * Insert an AML decision. Inserts into AML history and insert or updates AML + * status. + * + * @param cls closure + * @param h_payto account for which the attribute data is stored + * @param new_threshold new monthly threshold that would trigger an AML check + * @param new_status AML decision status + * @param decision_time when was the decision made + * @param justification human-readable text justifying the decision + * @param kyc_requirements specific KYC requirements being imposed + * @param requirements_row row in the KYC table for this process, 0 for none + * @param decider_pub public key of the staff member + * @param decider_sig signature of the staff member + * @param[out] invalid_officer set to TRUE if @a decider_pub is not allowed to make decisions right now + * @param[out] last_date set to the previous decision time; + * the INSERT is not performed if @a last_date is not before @a decision_time + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_aml_decision)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + const struct TALER_Amount *new_threshold, + enum TALER_AmlDecisionState new_status, + struct GNUNET_TIME_Timestamp decision_time, + const char *justification, + const json_t *kyc_requirements, + uint64_t requirements_row, + const struct TALER_AmlOfficerPublicKeyP *decider_pub, + const struct TALER_AmlOfficerSignatureP *decider_sig, + bool *invalid_officer, + struct GNUNET_TIME_Timestamp *last_date); + + + /** + * Update KYC process status to finished (and failed). + * + * @param cls closure + * @param process_row KYC process row to update + * @param h_payto account for which the attribute data is stored + * @param provider_section provider that must be checked + * @param provider_account_id provider account ID + * @param provider_legitimization_id provider legitimization ID + * @return database transaction status + */ + enum GNUNET_DB_QueryStatus + (*insert_kyc_failure)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *h_payto, + const char *provider_section, + const char *provider_account_id, + const char *provider_legitimization_id); + + /** + * Function called to inject auditor triggers into the + * database, triggering the real-time auditor upon + * relevant INSERTs. + * + * @param cls closure + * @return #GNUNET_OK on success, + * #GNUNET_SYSERR on DB errors + */ + enum GNUNET_GenericReturnValue + (*inject_auditor_triggers)(void *cls); }; diff --git a/src/include/taler_extensions.h b/src/include/taler_extensions.h new file mode 100644 index 000000000..1eb567f72 --- /dev/null +++ b/src/include/taler_extensions.h @@ -0,0 +1,386 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file include/taler_extensions.h + * @brief Interface for extensions + * @author Özgür Kesim + */ +#ifndef TALER_EXTENSIONS_H +#define TALER_EXTENSIONS_H + +#include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" +#include "taler_extensions_policy.h" + + +#define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-" + +enum TALER_Extension_Type +{ + TALER_Extension_PolicyNull = 0, + + TALER_Extension_AgeRestriction = 1, + TALER_Extension_PolicyMerchantRefund = 2, + TALER_Extension_PolicyBrandtVickeryAuction = 3, + TALER_Extension_PolicyEscrowedPayment = 4, + + TALER_Extension_MaxPredefined = 5 // Must be last of the predefined +}; + + +/* Forward declarations */ +enum TALER_PolicyFulfillmentState; +struct TALER_PolicyFulfillmentOutcome; + +/* + * @brief Represents the implementation of an extension. + * + * An "Extension" is an optional feature for the Exchange. + * There are only two types of extensions: + * + * a) Age restriction: This is a special feature that directly interacts with + * denominations and coins, but is not define policies during deposits, see b). + * The implementation of this extension doesn't have to implement any of the + * http- or depost-handlers in the struct. + * + * b) Policies for deposits: These are extensions that define policies (such + * as refund, escrow or auctions) for deposit requests. These extensions have + * to implement at least the deposit- and post-http-handler in the struct to be + * functional. + * + * In addition to the handlers defined in this struct, an extension must also + * be a plugin in the GNUNET_Plugin sense. That is, it must implement the + * functions + * 1: (void *ext)libtaler_extension_<name>_init(void *cfg) + * and + * 2: (void *)libtaler_extension_<name>_done(void *) + * + * In 1:, the input will be the GNUNET_CONFIGURATION_Handle to the TALER + * configuration and the output must be the struct TALER_Extension * on + * success, NULL otherwise. + * + * In 2:, no arguments are passed and NULL is expected to be returned. + */ +struct TALER_Extension +{ + /** + * Type of the extension. Only one extension of a type can be loaded + * at any time. + */ + enum TALER_Extension_Type type; + + /** + * The name of the extension, must be unique among all loaded extensions. It + * is used in URLs for /extension/$NAME as well. + */ + char *name; + + /** + * Criticality of the extension. It has the same semantics as "critical" has + * for extensions in X.509: + * - if "true", the client must "understand" the extension before proceeding, + * - if "false", clients can safely skip extensions they do not understand. + * (see https://datatracker.ietf.org/doc/html/rfc5280#section-4.2) + */ + bool critical; + + /** + * Version of the extension must be provided in Taler's protocol version ranges notation, see + * https://docs.taler.net/core/api-common.html#protocol-version-ranges + */ + char *version; + + /** + * If the extension is marked as enabled, it will be listed in the + * "extensions" field in the "/keys" response. + */ + bool enabled; + + /** + * Opaque (public) configuration object, set by the extension. + */ + void *config; + + + /** + * @brief Handler to to disable the extension. + * + * @param ext The current extension object + */ + void (*disable)(struct TALER_Extension *ext); + + /** + * @brief Handler to read an extension-specific configuration in JSON + * encoding and enable the extension. Must be implemented by the extension. + * + * @param[in] ext The extension object. If NULL, the configuration will only be checked. + * @param[in,out] config A JSON blob + * @return GNUNET_OK if the json was a valid configuration for the extension. + */ + enum GNUNET_GenericReturnValue (*load_config)( + const json_t *config, + struct TALER_Extension *ext); + + /** + * @brief Handler to return the manifest of the extension in JSON encoding. + * + * See + * https://docs.taler.net/design-documents/006-extensions.html#tsref-type-Extension + * for the definition. + * + * @param ext The extension object + * @return The JSON encoding of the extension, if enabled, NULL otherwise. + */ + json_t *(*manifest)( + const struct TALER_Extension *ext); + + /* ========================= + * Policy related handlers + * ========================= + */ + + /** + * @brief Handler to check an incoming policy and create a + * TALER_PolicyDetails. Can be NULL; + * + * When a deposit request refers to this extension in its policy + * (see https://docs.taler.net/core/api-exchange.html#deposit), this handler + * will be called before the deposit transaction. + * + * @param[in] currency Currency used in the exchange + * @param[in] policy_json Details about the policy, provided by the client + * during a deposit request. + * @param[out] details On success, will contain the details to the policy, + * evaluated by the corresponding policy handler. + * @param[out] error_hint On error, will contain a hint + * @return GNUNET_OK if the data was accepted by the extension. + */ + enum GNUNET_GenericReturnValue (*create_policy_details)( + const char *currency, + const json_t *policy_json, + struct TALER_PolicyDetails *details, + const char **error_hint); + + /** + * @brief Handler for POST-requests to the /extensions/$name endpoint. Can be NULL. + * + * @param[in] root The JSON body from the request + * @param[in] args Additional query parameters of the request. + * @param[in,out] details List of policy details related to the incoming fulfillment proof + * @param[in] details_len Size of the list @e details + * @param[out] output JSON output to return to the client + * @return GNUNET_OK on success. + */ + enum GNUNET_GenericReturnValue (*policy_post_handler)( + const json_t *root, + const char *const args[], + struct TALER_PolicyDetails *details, + size_t details_len, + json_t **output); + + /** + * @brief Handler for GET-requests to the /extensions/$name endpoint. Can be NULL. + * + * @param connection The current connection + * @param root The JSON body from the request + * @param args Additional query parameters of the request. + * @return MDH result + */ + MHD_RESULT (*policy_get_handler)( + struct MHD_Connection *connection, + const char *const args[]); +}; + + +/* + * @brief simply linked list of extensions + */ + +struct TALER_Extensions +{ + struct TALER_Extensions *next; + const struct TALER_Extension *extension; +}; + +/** + * Generic functions for extensions + */ + +/** + * @brief Loads the extensions as shared libraries, as specified in the given + * TALER configuration. + * + * @param cfg Handle to the TALER configuration + * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were found + * or any particular configuration couldn't be parsed. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_init ( + const struct GNUNET_CONFIGURATION_Handle *cfg); + +/* + * @brief Parses a given JSON object as an extension manifest. + * + * @param[in] obj JSON object to parse as an extension manifest + * @param{out] critical will be set to 1 if the extension is critical according to obj + * @param[out] version will be set to the version of the extension according to obj + * @param[out] config will be set to the configuration of the extension according to obj + * @return OK on success, Error otherwise + */ +enum GNUNET_GenericReturnValue +TALER_extensions_parse_manifest ( + json_t *obj, + int *critical, + const char **version, + json_t **config); + +/* + * @brief Loads extensions according to the manifests. + * + * The JSON object must be of type ExtensionsManifestsResponse as described + * in https://docs.taler.net/design-documents/006-extensions.html#exchange + * + * @param cfg JSON object containing the manifests for all extensions + * @return #GNUNET_OK on success, #GNUNET_SYSERR if unknown extensions were + * found or any particular configuration couldn't be parsed. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_load_manifests ( + const json_t *manifests); + +/* + * @brief Returns the head of the linked list of extensions. + */ +const struct TALER_Extensions * +TALER_extensions_get_head (void); + +/** + * @brief Finds and returns a supported extension by a given type. + * + * @param type of the extension to lookup + * @return extension found, or NULL (should not happen!) + */ +const struct TALER_Extension * +TALER_extensions_get_by_type ( + enum TALER_Extension_Type type); + + +/** + * @brief Finds and returns a supported extension by a given name. + * + * @param name name of the extension to lookup + * @return the extension, if found, NULL otherwise + */ +const struct TALER_Extension * +TALER_extensions_get_by_name ( + const char *name); + +/** + * @brief Check if a given type of an extension is enabled + * + * @param type type of to check + * @return true enabled, false if not enabled, will assert if type is not found. + */ +bool +TALER_extensions_is_enabled_type ( + enum TALER_Extension_Type type); + +/** + * @brief Check if an extension is enabled + * + * @param extension The extension handler. + * @return true enabled, false if not enabled, will assert if type is not found. + */ +bool +TALER_extensions_is_enabled ( + const struct TALER_Extension *extension); + +/* + * Verify the signature of a given JSON object for extensions with the master + * key of the exchange. + * + * The JSON object must be of type ExtensionsManifestsResponse as described in + * https://docs.taler.net/design-documents/006-extensions.html#exchange + * + * @param extensions JSON object with the extension configuration + * @param extensions_sig signature of the hash of the JSON object + * @param master_pub public key to verify the signature + * @return GNUNET_OK on success, GNUNET_SYSERR when hashing of the JSON fails + * and GNUNET_NO if the signature couldn't be verified. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_verify_manifests_signature ( + const json_t *manifests, + struct TALER_MasterSignatureP *extensions_sig, + struct TALER_MasterPublicKeyP *master_pub); + + +/* + * TALER Age Restriction Extension + * + * This extension is special insofar as it directly interacts with coins and + * denominations. + * + * At the same time, it doesn't implement and http- or deposit-handlers. + */ + +#define TALER_EXTENSION_SECTION_AGE_RESTRICTION (TALER_EXTENSION_SECTION_PREFIX \ + "age_restriction") + +/** + * The default age mask represents the age groups + * 0-7, 8-9, 10-11, 12-13, 14-15, 16-17, 18-20, 21-... + */ +#define TALER_EXTENSION_AGE_RESTRICTION_DEFAULT_AGE_GROUPS "8:10:12:14:16:18:21" + + +/* + * @brief Configuration for Age Restriction + */ +struct TALER_AgeRestrictionConfig +{ + struct TALER_AgeMask mask; + uint8_t num_groups; +}; + + +/** + * @brief Retrieve the age restriction configuration + * + * @return age restriction configuration if present, otherwise NULL. + */ +const struct TALER_AgeRestrictionConfig * +TALER_extensions_get_age_restriction_config (void); + +/** + * @brief Check if age restriction is enabled + * + * @return true, if age restriction is loaded, configured and enabled; otherwise false. + */ +bool +TALER_extensions_is_age_restriction_enabled (void); + +/** + * @brief Return the age mask for age restriction + * + * @return configured age mask, if age restriction is loaded, configured and enabled; otherwise zero mask. + */ +struct TALER_AgeMask +TALER_extensions_get_age_restriction_mask (void); + +#endif diff --git a/src/include/taler_extensions_policy.h b/src/include/taler_extensions_policy.h new file mode 100644 index 000000000..b10c0d8a2 --- /dev/null +++ b/src/include/taler_extensions_policy.h @@ -0,0 +1,205 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file include/taler_extensions_policy.h + * @brief Interface for policy extensions + * @author Özgür Kesim + */ +#ifndef TALER_EXTENSIONS_POLICY_H +#define TALER_EXTENSIONS_POLICY_H + +#include <gnunet/gnunet_util_lib.h> +#include "taler_util.h" +#include "taler_json_lib.h" +#include "taler_mhd_lib.h" + +/* + * @brief Describes the states of fulfillment of a policy bound to a deposit + * NOTE: These values must be in sync with their use in stored procedures, f.e. + * exchange_do_insert_or_update_policy_details. + */ +enum TALER_PolicyFulfillmentState +{ + /* Initial state of an fulfillment, before any other state. */ + TALER_PolicyFulfillmentInitial = 0, + + /* General error state of an fulfillment. */ + TALER_PolicyFulfillmentFailure = 1, + + /* The policy is not yet ready due to insufficient funding. More deposits are + * necessary for it to become ready . */ + TALER_PolicyFulfillmentInsufficient = 2, + + /* The policy is funded and ready, pending */ + TALER_PolicyFulfillmentReady = 3, + + /* Policy is provably fulfilled. */ + TALER_PolicyFulfillmentSuccess = 4, + + /* Policy fulfillment has timed out */ + TALER_PolicyFulfillmentTimeout = 5, + + TALER_PolicyFulfillmentStateCount = TALER_PolicyFulfillmentTimeout + 1 +}; + + +/* + * @brief Returns a string representation of the state of a policy fulfillment + */ +const char * +TALER_policy_fulfillment_state_str (enum TALER_PolicyFulfillmentState state); + + +/* @brief Details of a policy for a deposit request */ +struct TALER_PolicyDetails +{ + /* Hash code that should be used for the .policy_hash_code field when + * this policy is saved in the policy_details table. */ + struct GNUNET_HashCode hash_code; + + /* Content of the policy in its original JSON form */ + json_t *policy_json; + + /* When the deadline is met and the policy is still in "Ready" state, + * a timeout-handler will transfer the amount + * (total_amount - policy_fee - refreshable_amount) + * to the payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins */ + struct GNUNET_TIME_Timestamp deadline; + + /* The amount to which this policy commits to. It must be at least as + * large as @e policy_fee. */ + struct TALER_Amount commitment; + + /* The total sum of contributions from coins so far to fund this + * policy. It must be at least as large as @commitment in order to be + * sufficiently funded. */ + struct TALER_Amount accumulated_total; + + /* The fee from the exchange for handling the policy. It is due when + * the state changes to Timeout or Success. */ + struct TALER_Amount policy_fee; + + /* The amount that will be transferred to the payto-URIs from the + * corresponding deposits when the fulfillment state changes to Timeout + * or Success. Note that a fulfillment handler can alter this upon + * arrival of a proof of fulfillment. The remaining amount + * (accumulated_amount - policy_amount - transferable_amount) */ + struct TALER_Amount transferable_amount; + + /* The state of fulfillment of a policy. + * - If the state is Insufficient, the client is required to call + * /deposit -maybe multiple times- with enough coins and the same + * policy details in order to reach the required amount. The state is + * then changed to Ready. + * - If the state changes to Timeout or Success, a handler will transfer + * the amount (total_amount - policy_fee - refreshable_amount) to the + * payto-URI from the corresponding deposit. The value + * amount_refreshable will be refreshable by the owner of the + * associated deposits's coins. */ + enum TALER_PolicyFulfillmentState fulfillment_state; + + /* If there is a proof of fulfillment, the row ID from the + * policy_fulfillment table */ + uint64_t policy_fulfillment_id; + bool no_policy_fulfillment_id; +}; + +/* + * @brief All information required for the database transaction when handling a + * proof of fulfillment request. + */ +struct TALER_PolicyFulfillmentTransactionData +{ + /* The incoming proof, provided by a client */ + const json_t *proof; + + /* The Hash of the proof */ + struct GNUNET_HashCode h_proof; + + /* The timestamp of retrieval of the proof */ + struct GNUNET_TIME_Timestamp timestamp; + + /* The ID of the proof in the policy_fulfillment table. Will be set + * during the transaction. Needed to fill the table + * policy_details_fulfillments. */ + uint64_t fulfillment_id; + + /* The list of policy details. Will be updated by the policy handler */ + struct TALER_PolicyDetails *details; + size_t details_count; +}; + + +/* + * @brief Extracts policy details from the deposit's policy options and the policy extensions + * + * @param[in] currency Currency used in the exchange + * @param[in] policy_options JSON of the policy options from a deposit request + * @param[out] details On GNUNET_OK, the parsed details + * @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed + * @return GNUNET_OK on success, GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was + * invalid, with *error_hint maybe non-NULL. + */ +enum GNUNET_GenericReturnValue +TALER_extensions_create_policy_details ( + const char *currency, + const json_t *policy_options, + struct TALER_PolicyDetails *details, + const char **error_hint); + + +/* + * ================================ + * Merchant refund policy + * ================================ + */ +struct TALER_ExtensionPolicyMerchantRefundPolicyConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +/* + * ================================ + * Brandt-Vickrey Auctions policy + * ================================ + */ +/* + * @brief Configuration for Brandt-Vickrey auctions policy + */ +struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig +{ + uint16_t max_bidders; + uint16_t max_prices; + struct TALER_Amount auction_fee; +}; + + +/* + * ================================ + * Escrowed Payments policy + * ================================ + */ +/* + * @brief Configuration for escrowed payments policy + */ +struct TALER_ExtensionPolicyEscrowedPaymentsConfig +{ + struct GNUNET_TIME_Relative max_timeout; +}; + +#endif diff --git a/src/include/taler_fakebank_lib.h b/src/include/taler_fakebank_lib.h index bd4376695..6b34f4730 100644 --- a/src/include/taler_fakebank_lib.h +++ b/src/include/taler_fakebank_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2016-2020 Taler Systems SA + (C) 2016-2021 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -53,61 +53,71 @@ TALER_FAKEBANK_start (uint16_t port, /** - * Check that no wire transfers were ordered (or at least none - * that have not been taken care of via #TALER_FAKEBANK_check_debit() - * or #TALER_FAKEBANK_check_credit()). - * If any transactions are onrecord, return #GNUNET_SYSERR. + * Start the fake bank. The fake bank will, like the normal bank, listen for + * requests for /admin/add/incoming and /transfer. However, instead of + * executing or storing those requests, it will simply allow querying whether + * such a request has been made via #TALER_FAKEBANK_check_debit() and + * #TALER_FAKEBANK_check_credit() as well as the history API. * - * @param h bank instance - * @return #GNUNET_OK on success + * This is useful for writing testcases to check whether the exchange + * would have issued the correct wire transfer orders. + * + * @param port port to listen to + * @param currency which currency should the bank offer + * @param ram_limit how much memory do we use at most + * @param num_threads size of the thread pool, 0 to use the GNUnet scheduler + * @return NULL on error */ -int -TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h); +struct TALER_FAKEBANK_Handle * +TALER_FAKEBANK_start2 (uint16_t port, + const char *currency, + uint64_t ram_limit, + unsigned int num_threads); /** - * Tell the fakebank to create another wire transfer *from* an exchange. + * Start the fake bank. The fake bank will, like the normal bank, listen for + * requests for /admin/add/incoming and /transfer. However, instead of + * executing or storing those requests, it will simply allow querying whether + * such a request has been made via #TALER_FAKEBANK_check_debit() and + * #TALER_FAKEBANK_check_credit() as well as the history API. + * + * This is useful for writing testcases to check whether the exchange + * would have issued the correct wire transfer orders. * - * @param h fake bank handle - * @param debit_account account to debit - * @param credit_account account to credit - * @param amount amount to transfer - * @param subject wire transfer subject to use - * @param exchange_base_url exchange URL - * @param request_uid unique number to make the request unique, or NULL to create one - * @param[out] ret_row_id pointer to store the row ID of this transaction - * @return #GNUNET_YES if the transfer was successful, - * #GNUNET_SYSERR if the request_uid was reused for a different transfer + * @param hostname hostname to use in URLs and URIs. + * @param port port to listen to + * @param exchange_url suggested exchange base URL + * @param currency which currency should the bank offer + * @param ram_limit how much memory do we use at most + * @param num_threads size of the thread pool, 0 to use the GNUnet scheduler + * @param signup_bonus how much to credit new users + * @return NULL on error */ -int -TALER_FAKEBANK_make_transfer ( - struct TALER_FAKEBANK_Handle *h, - const char *debit_account, - const char *credit_account, - const struct TALER_Amount *amount, - const struct TALER_WireTransferIdentifierRawP *subject, - const char *exchange_base_url, - const struct GNUNET_HashCode *request_uid, - uint64_t *ret_row_id); +struct TALER_FAKEBANK_Handle * +TALER_FAKEBANK_start3 (const char *hostname, + uint16_t port, + const char *exchange_url, + const char *currency, + uint64_t ram_limit, + unsigned int num_threads, + const struct TALER_Amount *signup_bonus); /** - * Tell the fakebank to create another wire transfer *to* an exchange. + * Check that no wire transfers were ordered (or at least none + * that have not been taken care of via #TALER_FAKEBANK_check_debit() + * or #TALER_FAKEBANK_check_credit()). + * If any transactions are onrecord, return #GNUNET_SYSERR. + * + * Note that this function only works in + * single-threaded mode while nothing else is happening. * - * @param h fake bank handle - * @param debit_account account to debit - * @param credit_account account to credit - * @param amount amount to transfer - * @param reserve_pub reserve public key to use in subject - * @return serial_id of the transfer + * @param h bank instance + * @return #GNUNET_OK on success */ -uint64_t -TALER_FAKEBANK_make_admin_transfer ( - struct TALER_FAKEBANK_Handle *h, - const char *debit_account, - const char *credit_account, - const struct TALER_Amount *amount, - const struct TALER_ReservePublicKeyP *reserve_pub); +enum GNUNET_GenericReturnValue +TALER_FAKEBANK_check_empty (struct TALER_FAKEBANK_Handle *h); /** @@ -116,16 +126,19 @@ TALER_FAKEBANK_make_admin_transfer ( * to the transfer identifier and remove the transaction from the * list. If the transaction was not recorded, return #GNUNET_SYSERR. * + * Note that this function only works in + * single-threaded mode while nothing else is happening. + * * @param h bank instance * @param want_amount transfer amount desired * @param want_debit account that should have been debited - * @param want_debit account that should have been credited + * @param want_credit account that should have been credited * @param exchange_base_url expected base URL of the exchange, * i.e. "https://example.com/"; may include a port * @param[out] wtid set to the wire transfer identifier * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_FAKEBANK_check_debit (struct TALER_FAKEBANK_Handle *h, const struct TALER_Amount *want_amount, const char *want_debit, @@ -139,14 +152,17 @@ TALER_FAKEBANK_check_debit (struct TALER_FAKEBANK_Handle *h, * @a want_credit account with the @a subject. If so, remove the transaction * from the list. If the transaction was not recorded, return #GNUNET_SYSERR. * + * Note that this function only works in + * single-threaded mode while nothing else is happening. + * * @param h bank instance * @param want_amount transfer amount desired * @param want_debit account that should have been debited - * @param want_debit account that should have been credited + * @param want_credit account that should have been credited * @param reserve_pub reserve public key expected in wire subject * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_FAKEBANK_check_credit (struct TALER_FAKEBANK_Handle *h, const struct TALER_Amount *want_amount, const char *want_debit, diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h index 094cbe2eb..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 Taler Systems SA + Copyright (C) 2014-2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -29,6 +29,40 @@ #include "taler_error_codes.h" /** + * Version of this API, for compatibility tests. + */ +#define TALER_JSON_LIB_VERSION 0x00020000 + +/** + * Details about an encrypted contract. + */ +struct TALER_EncryptedContract +{ + + /** + * Signature of the client affiming this encrypted contract. + */ + struct TALER_PurseContractSignatureP econtract_sig; + + /** + * Contract decryption key for the purse. + */ + struct TALER_ContractDiffiePublicP contract_pub; + + /** + * Encrypted contract, can be NULL. + */ + void *econtract; + + /** + * Number of bytes in @e econtract. + */ + size_t econtract_size; + +}; + + +/** * Print JSON parsing related error information * @deprecated */ @@ -37,14 +71,139 @@ "JSON parsing failed at %s:%u: %s (%s)\n", \ __FILE__, __LINE__, error.text, error.source) + /** - * Convert a TALER amount to a JSON object. + * Generate packer instruction for a JSON field of type + * absolute time creating a human-readable timestamp. * - * @param amount the amount - * @return a json object describing the amount + * @param name name of the field to add to the object + * @param at absolute time to pack + * @return json pack specification */ -json_t * -TALER_JSON_from_amount (const struct TALER_Amount *amount); +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_time_abs_human (const char *name, + struct GNUNET_TIME_Absolute at); + + +/** + * Put an error code into a JSON reply, including + * both the numeric value and the hint. + * + * @param ec error code to encode using canonical field names + */ +#define TALER_JSON_pack_ec(ec) \ + 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 + * denomination public key. + * + * @param name name of the field to add to the object + * @param pk public key + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_denom_pub ( + const char *name, + const struct TALER_DenominationPublicKey *pk); + + +/** + * Generate packer instruction for a JSON field of type + * denomination signature. + * + * @param name name of the field to add to the object + * @param sig signature + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_denom_sig ( + const char *name, + const struct TALER_DenominationSignature *sig); + + +/** + * Generate packer instruction for a JSON field of type + * blinded denomination signature (that needs to be + * unblinded before it becomes valid). + * + * @param name name of the field to add to the object + * @param sig signature + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_blinded_denom_sig ( + const char *name, + const struct TALER_BlindedDenominationSignature *sig); + + +/** + * Generate packer instruction for a JSON field of type + * blinded planchet. + * + * @param name name of the field to add to the object + * @param blinded_planchet blinded planchet + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_blinded_planchet ( + const char *name, + const struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * Generate packer instruction for a JSON field of type + * exchange withdraw values (/csr). + * + * @param name name of the field to add to the object + * @param ewv values to transmit + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_exchange_withdraw_values ( + const char *name, + const struct TALER_ExchangeWithdrawValues *ewv); + + +/** + * 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 (const char *name, + const struct TALER_Amount *amount); + + +/** + * Generate packer instruction for a JSON field of type + * encrypted contract. + * + * @param name name of the field to add to the object + * @param econtract the encrypted contract + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_econtract ( + const char *name, + const struct TALER_EncryptedContract *econtract); + +/** + * Generate packer instruction for a JSON field of type age_commitment + * + * @param name name of the field to add to the object + * @param age_commitment age commitment to add + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +TALER_JSON_pack_age_commitment ( + const char *name, + const struct TALER_AgeCommitment *age_commitment); /** @@ -54,31 +213,169 @@ TALER_JSON_from_amount (const struct TALER_Amount *amount); * @return a json object describing the amount */ json_t * -TALER_JSON_from_amount_nbo (const struct TALER_AmountNBO *amount); +TALER_JSON_from_amount (const struct TALER_Amount *amount); /** * 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. * * @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 + * @return spec for parsing an amount */ struct GNUNET_JSON_Specification TALER_JSON_spec_amount (const char *name, + const char *currency, struct TALER_Amount *r_amount); /** + * Provide specification to parse given JSON object to + * a currency specification. + * + * @param name name of the amount field in the JSON + * @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_currency_specification ( + const char *name, + const char *currency_code, + struct TALER_CurrencySpecification *r_cspec); + + +/** * Provide specification to parse given JSON object to an amount - * in network byte order. + * in any currency. * * @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 + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_amount_any (const char *name, + struct TALER_Amount *r_amount); + + +/** + * Provide specification to parse given JSON object to an encrypted contract. + * + * @param name name of the amount field in the JSON + * @param[out] econtract where to store the encrypted contract + * @return spec for parsing an amount + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_econtract (const char *name, + struct TALER_EncryptedContract *econtract); + + +/** + * Provide specification to parse a given JSON object to an age commitment. + * + * @param name name of the age commitment field in the JSON + * @param[out] age_commitment where to store the age commitment + * @return spec for parsing an age commitment + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_age_commitment (const char *name, + struct TALER_AgeCommitment *age_commitment); + + +/** + * 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 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_nbo (const char *name, - struct TALER_AmountNBO *r_amount); +TALER_JSON_spec_otp_type (const char *name, + enum TALER_MerchantConfirmationAlgorithm *mca); + + +/** + * Generate specification to parse all fees for + * a denomination under a prefix @a pfx. + * + * @param pfx string prefix to use + * @param currency which currency to expect + * @param[out] dfs a `struct TALER_DenomFeeSet` to initialize + */ +#define TALER_JSON_SPEC_DENOM_FEES(pfx,currency,dfs) \ + TALER_JSON_spec_amount (pfx "_withdraw", (currency), &(dfs)->withdraw), \ + TALER_JSON_spec_amount (pfx "_deposit", (currency), &(dfs)->deposit), \ + TALER_JSON_spec_amount (pfx "_refresh", (currency), &(dfs)->refresh), \ + TALER_JSON_spec_amount (pfx "_refund", (currency), &(dfs)->refund) + + +/** + * Macro to pack all of a denominations' fees under + * a given @a pfx. + * + * @param pfx string prefix to use + * @param dfs a `struct TALER_DenomFeeSet` to pack + */ +#define TALER_JSON_PACK_DENOM_FEES(pfx, dfs) \ + TALER_JSON_pack_amount (pfx "_withdraw", &(dfs)->withdraw), \ + TALER_JSON_pack_amount (pfx "_deposit", &(dfs)->deposit), \ + TALER_JSON_pack_amount (pfx "_refresh", &(dfs)->refresh), \ + TALER_JSON_pack_amount (pfx "_refund", &(dfs)->refund) + +/** + * Generate specification to parse all global fees. + * + * @param currency which currency to expect + * @param[out] gfs a `struct TALER_GlobalFeeSet` to initialize + */ +#define TALER_JSON_SPEC_GLOBAL_FEES(currency,gfs) \ + TALER_JSON_spec_amount ("history_fee", (currency), &(gfs)->history), \ + TALER_JSON_spec_amount ("account_fee", (currency), &(gfs)->account), \ + TALER_JSON_spec_amount ("purse_fee", (currency), &(gfs)->purse) + +/** + * Macro to pack all of the global fees. + * + * @param gfs a `struct TALER_GlobalFeeSet` to pack + */ +#define TALER_JSON_PACK_GLOBAL_FEES(gfs) \ + TALER_JSON_pack_amount ("history_fee", &(gfs)->history), \ + TALER_JSON_pack_amount ("account_fee", &(gfs)->account), \ + TALER_JSON_pack_amount ("purse_fee", &(gfs)->purse) + + +/** + * Generate a parser for a group of denominations. + * + * @param[in] field name of the field, maybe NULL + * @param[in] currency name of the currency + * @param[out] group denomination group information + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denomination_group (const char *field, + const char *currency, + struct TALER_DenominationGroup *group); /** * Generate line in parser specification for denomination public key. @@ -88,20 +385,206 @@ TALER_JSON_spec_amount_nbo (const char *name, * @return corresponding field spec */ struct GNUNET_JSON_Specification -TALER_JSON_spec_denomination_public_key (const char *field, - struct TALER_DenominationPublicKey *pk); +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. + * + * @param field name of the field + * @param cipher which cipher type to parse for + * @param[out] pk key to fill + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_denom_pub_cipher ( + const char *field, + enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, + struct TALER_DenominationPublicKey *pk); /** * Generate line in parser specification for denomination signature. * * @param field name of the field - * @param sig the signature to initialize + * @param[out] sig the signature to initialize * @return corresponding field spec */ struct GNUNET_JSON_Specification -TALER_JSON_spec_denomination_signature (const char *field, - struct TALER_DenominationSignature *sig); +TALER_JSON_spec_denom_sig (const char *field, + struct TALER_DenominationSignature *sig); + + +/** + * Generate line in parser specification for a + * blinded denomination signature. + * + * @param field name of the field + * @param[out] sig the blinded signature to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_denom_sig ( + const char *field, + struct TALER_BlindedDenominationSignature *sig); + + +/** + * Generate line in parser specification for + * exchange withdraw values (/csr). + * + * @param field name of the field + * @param[out] ewv the exchange withdraw values to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_exchange_withdraw_values ( + const char *field, + struct TALER_ExchangeWithdrawValues *ewv); + + +/** + * Generate line in parser specification for a + * blinded planchet. + * + * @param field name of the field + * @param[out] blinded_planchet the blinded planchet to initialize + * @return corresponding field spec + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_blinded_planchet (const char *field, + struct TALER_BlindedPlanchet *blinded_planchet); + + +/** + * The expected field stores a possibly internationalized string. + * Internationalization means that there is another field "$name_i18n" + * which is an object where the keys are languages. If this is + * present, and if @a language_pattern is non-NULL, this function + * should return the best match from @a language pattern from the + * "_i18n" field. If no language matches, the normal field under + * @a name is to be returned. + * + * The @a language_pattern is given using the format from + * https://tools.ietf.org/html/rfc7231#section-5.3.1 + * so that #TALER_language_matches() can be used. + * + * @param name name of the JSON field + * @param language_pattern language pattern to use to find best match, possibly NULL + * @param[out] strptr where to store a pointer to the field with the best variant + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_i18n_string (const char *name, + const char *language_pattern, + const char **strptr); + + +/** + * The expected field stores a possibly internationalized string. + * Internationalization means that there is another field "$name_i18n" which + * is an object where the keys are languages. If this is present, this + * function should return the best match based on the locale from the "_i18n" + * field. If no language matches, the normal field under @a name is to be + * returned. + * + * @param name name of the JSON field + * @param[out] strptr where to store a pointer to the field with the best variant + */ +struct GNUNET_JSON_Specification +TALER_JSON_spec_i18n_str (const char *name, + const char **strptr); /** @@ -115,11 +598,87 @@ TALER_JSON_spec_denomination_signature (const char *field, * * @param[in] json some JSON value to hash * @param[out] hc resulting hash code + * @return #GNUNET_OK on success, + * #GNUNET_NO if @a json was malformed + * #GNUNET_SYSERR on internal error + */ +enum GNUNET_GenericReturnValue +TALER_JSON_contract_hash (const json_t *json, + struct TALER_PrivateContractHashP *hc); + + +/** + * 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 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 (const json_t *spec, + json_t *contract); + + +/** + * Mark part of a contract object as 'forgettable'. + * + * @param[in,out] json some JSON object to modify + * @param field name of the field to mark as forgettable * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ -int -TALER_JSON_hash (const json_t *json, - struct GNUNET_HashCode *hc); +enum GNUNET_GenericReturnValue +TALER_JSON_contract_mark_forgettable (json_t *json, + const char *field); + + +/** + * Forget part of a contract object. + * + * @param[in,out] json some JSON object to modify + * @param field name of the field to forget + * @return #GNUNET_OK on success, + * #GNUNET_NO if the field was already forgotten before + * #GNUNET_SYSERR on error + */ +enum GNUNET_GenericReturnValue +TALER_JSON_contract_part_forget (json_t *json, + const char *field); + + +/** + * Called for each path found after expanding a path. + * + * @param cls the closure. + * @param object_id the name of the object that is pointed to. + * @param parent the parent of the object at @e object_id. + */ +typedef void +(*TALER_JSON_ExpandPathCallback) ( + void *cls, + const char *object_id, + json_t *parent); + + +/** + * Expands a path for a json object. May call the callback several times + * if the path contains a wildcard. + * + * @param json the json object the path references. + * @param path the path to expand. Must begin with "$." and follow dot notation, + * and may include array indices and wildcards. + * @param cb the callback. + * @param cb_cls closure for the callback. + * @return #GNUNET_OK on success, #GNUNET_SYSERR if @e path is invalid. + */ +enum GNUNET_GenericReturnValue +TALER_JSON_expand_path (json_t *json, + const char *path, + TALER_JSON_ExpandPathCallback cb, + void *cb_cls); + /** * Extract the Taler error code from the given @a json object. @@ -167,36 +726,50 @@ TALER_JSON_get_error_code2 (const void *data, * @param[out] hc set to the hash * @return #GNUNET_OK on success, #GNUNET_SYSERR if @a wire_s is malformed */ -int +enum GNUNET_GenericReturnValue TALER_JSON_merchant_wire_signature_hash (const json_t *wire_s, - struct GNUNET_HashCode *hc); + struct TALER_MerchantWireHashP *hc); /** - * Check the signature in @a wire_s. Also performs rudimentary - * checks on the account data *if* supported. + * 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. * - * @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 + * Basically, the @a object may optionally contain a sub-object + * "${field}_i18n" with a map from IETF BCP 47 language tags to a localized + * version of the string. If this map exists and contains an entry that + * matches the @a language pattern, that object (usually a string) is + * returned. If the @a language_pattern does not match any entry, or if the + * i18n sub-object does not exist, we simply return @a field of @a object + * (also usually a string). + * + * If @a object does not have a member @a field we return NULL (error). + * + * @param object the object to extract internationalized + * content from + * @param language_pattern a language preferences string + * like "fr-CH, fr;q=0.9, en;q=0.8, *;q=0.1", following + * https://tools.ietf.org/html/rfc7231#section-5.3.1 + * @param field name of the field to extract + * @return NULL on error, otherwise the member from + * @a object. Note that the reference counter is + * NOT incremented. */ -int -TALER_JSON_exchange_wire_signature_check ( - const json_t *wire_s, - const struct TALER_MasterPublicKeyP *master_pub); +const json_t * +TALER_JSON_extract_i18n (const json_t *object, + const char *language_pattern, + const char *field); /** - * Create a signed wire statement for the given account. + * Check whether a given @a i18n object is wellformed. * - * @param payto_uri account specification - * @param master_priv private key to sign with - * @return NULL if @a payto_uri is malformed + * @param i18n object with internationalized content + * @return true if @a i18n is well-formed */ -json_t * -TALER_JSON_exchange_wire_signature_make ( - const char *payto_uri, - const struct TALER_MasterPrivateKeyP *master_priv); +bool +TALER_JSON_check_i18n (const json_t *i18n); /** @@ -221,6 +794,33 @@ char * TALER_JSON_wire_to_payto (const json_t *wire_s); +/** + * Hash @a policy extensions in deposits. + * + * @param policy contract policy extension to hash + * @param[out] ech where to write the policy hash + */ +void +TALER_deposit_policy_hash (const json_t *policy, + struct TALER_ExtensionPolicyHashP *ech); + +/** + * Hash the @a manifests of extensions, given as JSON + * + * @param manifests Manifests of the extensions + * @param[out] eh where to write the hash + * @return GNUNET_OK on success, GNUNET_SYSERR on failure + */ +enum GNUNET_GenericReturnValue +TALER_JSON_extensions_manifests_hash (const json_t *manifests, + struct TALER_ExtensionManifestsHashP *eh); + +/** + * Canonicalize a JSON input to a string according to RFC 8785. + */ +char * +TALER_JSON_canonicalize (const json_t *input); + #endif /* TALER_JSON_LIB_H_ */ /* End of taler_json_lib.h */ diff --git a/src/include/taler_kyclogic_lib.h b/src/include/taler_kyclogic_lib.h new file mode 100644 index 000000000..4d0c18fa4 --- /dev/null +++ b/src/include/taler_kyclogic_lib.h @@ -0,0 +1,374 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU Affero General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler_kyclogic_lib.h + * @brief server-side KYC API + * @author Christian Grothoff + */ +#ifndef TALER_KYCLOGIC_LIB_H +#define TALER_KYCLOGIC_LIB_H + +#include <microhttpd.h> +#include "taler_exchangedb_plugin.h" +#include "taler_kyclogic_plugin.h" + + +/** + * Enumeration for our KYC user types. + */ +enum TALER_KYCLOGIC_KycUserType +{ + /** + * KYC rule is for an individual. + */ + TALER_KYCLOGIC_KYC_UT_INDIVIDUAL = 0, + + /** + * KYC rule is for a business. + */ + TALER_KYCLOGIC_KYC_UT_BUSINESS = 1 +}; + + +/** + * Enumeration of possible events that may trigger + * KYC requirements. + */ +enum TALER_KYCLOGIC_KycTriggerEvent +{ + + /** + * Customer withdraws coins. + */ + TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW = 0, + + /** + * Merchant deposits coins. + */ + TALER_KYCLOGIC_KYC_TRIGGER_DEPOSIT = 1, + + /** + * Wallet receives P2P payment. + */ + TALER_KYCLOGIC_KYC_TRIGGER_P2P_RECEIVE = 2, + + /** + * Wallet balance exceeds threshold. + */ + TALER_KYCLOGIC_KYC_TRIGGER_WALLET_BALANCE = 3, + + /** + * Reserve is being closed by force. + */ + TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE = 4, + + /** + * Customer withdraws coins via age-withdraw. + */ + TALER_KYCLOGIC_KYC_TRIGGER_AGE_WITHDRAW = 5, +}; + + +/** + * Parse KYC trigger string value from a string + * into enumeration value. + * + * @param trigger_s string to parse + * @param[out] trigger set to the value found + * @return #GNUNET_OK on success, #GNUNET_NO if option + * does not exist, #GNUNET_SYSERR if option is + * malformed + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_trigger_from_string ( + const char *trigger_s, + enum TALER_KYCLOGIC_KycTriggerEvent *trigger); + + +/** + * Convert KYC trigger value to human-readable string. + * + * @param trigger value to convert + * @return human-readable representation of the @a trigger + */ +const char * +TALER_KYCLOGIC_kyc_trigger2s (enum TALER_KYCLOGIC_KycTriggerEvent trigger); + + +/** + * Parse user type string into enumeration value. + * + * @param ut_s string to parse + * @param[out] ut set to the value found + * @return #GNUNET_OK on success, #GNUNET_NO if option + * does not exist, #GNUNET_SYSERR if option is + * malformed + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_user_type_from_string (const char *ut_s, + enum TALER_KYCLOGIC_KycUserType *ut); + + +/** + * Convert KYC user type to human-readable string. + * + * @param ut value to convert + * @return human-readable representation of the @a ut + */ +const char * +TALER_KYCLOGIC_kyc_user_type2s (enum TALER_KYCLOGIC_KycUserType ut); + + +/** + * Initialize KYC subsystem. Loads the KYC configuration. + * + * @param cfg configuration to parse + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_kyc_init (const struct GNUNET_CONFIGURATION_Handle *cfg); + + +/** + * Shut down the KYC subsystem. + */ +void +TALER_KYCLOGIC_kyc_done (void); + + +/** + * Function called to iterate over KYC-relevant + * transaction amounts for a particular time range. + * Called within a database transaction, so must + * not start a new one. + * + * @param cls closure, identifies the event type and + * account to iterate over events for + * @param limit maximum time-range for which events + * should be fetched (timestamp in the past) + * @param cb function to call on each event found, + * events must be returned in reverse chronological + * order + * @param cb_cls closure for @a cb + */ +typedef void +(*TALER_KYCLOGIC_KycAmountIterator)(void *cls, + struct GNUNET_TIME_Absolute limit, + TALER_EXCHANGEDB_KycAmountCallback cb, + void *cb_cls); + + +/** + * Function called to iterate over KYC-relevant + * transaction thresholds amounts. + * + * @param cls closure, identifies the event type and + * account to iterate over events for + * @param threshold a relevant threshold amount + */ +typedef void +(*TALER_KYCLOGIC_KycThresholdIterator)(void *cls, + const struct TALER_Amount *threshold); + + +/** + * Call us on KYC processes satisfied for the given + * account. Must match the ``select_satisfied_kyc_processes`` of the exchange database plugin. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param h_payto account identifier + * @param spc function to call for each satisfied KYC process + * @param spc_cls closure for @a spc + * @return transaction status code + */ +typedef enum GNUNET_DB_QueryStatus +(*TALER_KYCLOGIC_KycSatisfiedIterator)( + void *cls, + const struct TALER_PaytoHashP *h_payto, + TALER_EXCHANGEDB_SatisfiedProviderCallback spc, + void *spc_cls); + + +/** + * Check if KYC is provided for a particular operation. Returns the set of checks that still need to be satisfied. + * + * Called within a database transaction, so must + * not start a new one. + * + * @param event what type of operation is triggering the + * test if KYC is required + * @param h_payto account the event is about + * @param ki callback that returns list of already + * satisfied KYC checks, implemented by ``select_satisfied_kyc_processes`` of the exchangedb + * @param ki_cls closure for @a ki + * @param ai callback offered to inquire about historic + * amounts involved in this type of operation + * at the given account + * @param ai_cls closure for @a ai + * @param[out] required set to NULL if no check is needed, + * otherwise space-separated list of required checks + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +TALER_KYCLOGIC_kyc_test_required (enum TALER_KYCLOGIC_KycTriggerEvent event, + const struct TALER_PaytoHashP *h_payto, + TALER_KYCLOGIC_KycSatisfiedIterator ki, + void *ki_cls, + TALER_KYCLOGIC_KycAmountIterator ai, + void *ai_cls, + char **required); + + +/** + * Check if the @a requirements are now satsified for + * @a h_payto account. + * + * @param[in,out] requirements space-spearated list of requirements, + * already satisfied requirements are removed from the list + * @param h_payto hash over the account + * @param[out] kyc_details if satisfied, set to what kind of + * KYC information was collected + * @param ki iterator over satisfied providers + * @param ki_cls closure for @a ki + * @param[out] satisfied set to true if the KYC check was satisfied + * @return transaction status (from @a ki) + */ +enum GNUNET_DB_QueryStatus +TALER_KYCLOGIC_check_satisfied (char **requirements, + const struct TALER_PaytoHashP *h_payto, + json_t **kyc_details, + TALER_KYCLOGIC_KycSatisfiedIterator ki, + void *ki_cls, + bool *satisfied); + + +/** + * Iterate over all thresholds that are applicable + * to a particular type of @a event + * + * @param event thresholds to look up + * @param it function to call on each + * @param it_cls closure for @a it + */ +void +TALER_KYCLOGIC_kyc_iterate_thresholds ( + enum TALER_KYCLOGIC_KycTriggerEvent event, + TALER_KYCLOGIC_KycThresholdIterator it, + void *it_cls); + + +/** + * Function called with the provider details and + * associated plugin closures for matching logics. + * + * @param cls closure + * @param pd provider details of a matching logic + * @param plugin_cls closure of the plugin + * @return #GNUNET_OK to continue to iterate + */ +typedef enum GNUNET_GenericReturnValue +(*TALER_KYCLOGIC_DetailsCallback)( + void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + void *plugin_cls); + + +/** + * Call @a cb for all logics with name @a logic_name, + * providing the plugin closure and the @a pd configurations. + * + * @param logic_name name of the logic to match + * @param cb function to call on matching results + * @param cb_cls closure for @a cb + */ +void +TALER_KYCLOGIC_kyc_get_details ( + const char *logic_name, + TALER_KYCLOGIC_DetailsCallback cb, + void *cb_cls); + + +/** + * Check if a given @a check_name is a legal name (properly + * configured) and can be satisfied in principle. + * + * @param check_name name of the check to see if it is configured + * @return #GNUNET_OK if the check can be satisfied, + * #GNUNET_NO if the check can never be satisfied, + * #GNUNET_SYSERR if the type of the check is unknown + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_check_satisfiable ( + const char *check_name); + + +/** + * Return list of all KYC checks that are possible. + * + * @return JSON array of strings with the allowed KYC checks + */ +json_t * +TALER_KYCLOGIC_get_satisfiable (void); + + +/** + * Obtain the provider logic for a given set of @a requirements. + * + * @param requirements space-separated list of required checks + * @param ut type of the entity performing the check + * @param[out] plugin set to the KYC logic API + * @param[out] pd set to the specific operation context + * @param[out] configuration_section set to the name of the KYC logic configuration section * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_requirements_to_logic (const char *requirements, + enum TALER_KYCLOGIC_KycUserType ut, + struct TALER_KYCLOGIC_Plugin **plugin, + struct TALER_KYCLOGIC_ProviderDetails **pd, + const char **configuration_section); + + +/** + * Obtain the provider logic for a given @a name. + * + * @param name name of the logic or provider section + * @param[out] plugin set to the KYC logic API + * @param[out] pd set to the specific operation context + * @param[out] configuration_section set to the name of the KYC logic configuration section + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_KYCLOGIC_lookup_logic (const char *name, + struct TALER_KYCLOGIC_Plugin **plugin, + struct TALER_KYCLOGIC_ProviderDetails **pd, + const char **configuration_section); + + +/** + * Obtain array of KYC checks provided by the provider + * configured in @a section_name. + * + * @param section_name configuration section name + * @param[out] num_checks set to the length of the array + * @param[out] provided_checks set to an array with the + * names of the checks provided by this KYC provider + */ +void +TALER_KYCLOGIC_lookup_checks (const char *section_name, + unsigned int *num_checks, + char ***provided_checks); + +#endif diff --git a/src/include/taler_kyclogic_plugin.h b/src/include/taler_kyclogic_plugin.h new file mode 100644 index 000000000..a9a4dd97a --- /dev/null +++ b/src/include/taler_kyclogic_plugin.h @@ -0,0 +1,384 @@ +/* + This file is part of TALER + Copyright (C) 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file include/taler_kyclogic_plugin.h + * @brief KYC API specific logic C interface + * @author Christian Grothoff + */ +#ifndef TALER_KYCLOGIC_PLUGIN_H +#define TALER_KYCLOGIC_PLUGIN_H + +#include <jansson.h> +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_db_lib.h> +#include "taler_util.h" + + +/** + * Possible states of a KYC check. + */ +enum TALER_KYCLOGIC_KycStatus +{ + + /** + * The provider has passed the customer. + */ + TALER_KYCLOGIC_STATUS_SUCCESS = 0, + + /** + * Something to do with the user (bit!). + */ + TALER_KYCLOGIC_STATUS_USER = 1, + + /** + * Something to do with the provider (bit!). + */ + TALER_KYCLOGIC_STATUS_PROVIDER = 2, + + /** + * The interaction ended in definitive failure. + * (kind of with both parties). + */ + TALER_KYCLOGIC_STATUS_FAILED + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_PROVIDER, + + /** + * The interaction is still ongoing. + */ + TALER_KYCLOGIC_STATUS_PENDING = 4, + + /** + * One of the parties hat a temporary failure. + */ + TALER_KYCLOGIC_STATUS_ABORTED = 8, + + /** + * The interaction with the user is ongoing. + */ + TALER_KYCLOGIC_STATUS_USER_PENDING + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_PENDING, + + /** + * The provider is still checking. + */ + TALER_KYCLOGIC_STATUS_PROVIDER_PENDING + = TALER_KYCLOGIC_STATUS_PROVIDER + | TALER_KYCLOGIC_STATUS_PENDING, + + /** + * The user aborted the check (possibly recoverable) + * or made some other type of (recoverable) mistake. + */ + TALER_KYCLOGIC_STATUS_USER_ABORTED + = TALER_KYCLOGIC_STATUS_USER + | TALER_KYCLOGIC_STATUS_ABORTED, + + /** + * The provider had an (internal) failure. + */ + TALER_KYCLOGIC_STATUS_PROVIDER_FAILED + = TALER_KYCLOGIC_STATUS_PROVIDER + | TALER_KYCLOGIC_STATUS_ABORTED, + + /** + * Return code set to not update the KYC status + * at all. + */ + TALER_KYCLOGIC_STATUS_KEEP = 16, + + /** + * We had an internal logic failure. + */ + TALER_KYCLOGIC_STATUS_INTERNAL_ERROR = 32 + +}; + + +/** + * Plugin-internal specification of the configuration + * of the plugin for a given KYC provider. + */ +struct TALER_KYCLOGIC_ProviderDetails; + +/** + * Handle for an initiation operation. + */ +struct TALER_KYCLOGIC_InitiateHandle; + +/** + * Handle for an KYC proof operation. + */ +struct TALER_KYCLOGIC_ProofHandle; + +/** + * Handle for an KYC Web hook operation. + */ +struct TALER_KYCLOGIC_WebhookHandle; + + +/** + * Function called with the result of a KYC initiation + * operation. + * + * @param cls closure + * @param ec #TALER_EC_NONE on success + * @param redirect_url set to where to redirect the user on success, NULL on failure + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param error_msg_hint set to additional details to return to user, NULL on success + */ +typedef void +(*TALER_KYCLOGIC_InitiateCallback)( + void *cls, + enum TALER_ErrorCode ec, + const char *redirect_url, + const char *provider_user_id, + const char *provider_legitimization_id, + const char *error_msg_hint); + + +/** + * Function called with the result of a proof check operation. + * + * Note that the "decref" for the @a response + * will be done by the callee and MUST NOT be done by the plugin. + * + * @param cls closure + * @param status KYC status + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param attributes user attributes returned by the provider + * @param expiration until when is the KYC check valid + * @param http_status HTTP status code of @a response + * @param[in] response to return to the HTTP client + */ +typedef void +(*TALER_KYCLOGIC_ProofCallback)( + void *cls, + enum TALER_KYCLOGIC_KycStatus status, + const char *provider_user_id, + const char *provider_legitimization_id, + struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, + unsigned int http_status, + struct MHD_Response *response); + + +/** + * Function called with the result of a webhook operation. + * + * Note that the "decref" for the @a response will be done by the callee and + * MUST NOT be done by the plugin! + * + * @param cls closure + * @param process_row legitimization process the webhook was about + * @param account_id account the webhook was about + * @param provider_section name of the configuration section of the logic that was run + * @param provider_user_id set to user ID at the provider, or NULL if not supported or unknown + * @param provider_legitimization_id set to legitimization process ID at the provider, or NULL if not supported or unknown + * @param status KYC status + * @param expiration until when is the KYC check valid + * @param attributes user attributes returned by the provider + * @param http_status HTTP status code of @a response + * @param[in] response to return to the HTTP client + */ +typedef void +(*TALER_KYCLOGIC_WebhookCallback)( + void *cls, + uint64_t process_row, + const struct TALER_PaytoHashP *account_id, + const char *provider_section, + const char *provider_user_id, + const char *provider_legitimization_id, + enum TALER_KYCLOGIC_KycStatus status, + struct GNUNET_TIME_Absolute expiration, + const json_t *attributes, + unsigned int http_status, + struct MHD_Response *response); + + +/** + * Function the plugin can use to lookup an @a h_payto by @a + * provider_legitimization_id. Must match the `kyc_provider_account_lookup` + * of the exchange's database plugin. + * + * @param cls closure + * @param provider_section + * @param provider_legitimization_id legi to look up + * @param[out] h_payto where to write the result + * @param[out] process_row where to write the row of the entry + * @return database transaction status + */ +typedef enum GNUNET_DB_QueryStatus +(*TALER_KYCLOGIC_ProviderLookupCallback)( + void *cls, + const char *provider_section, + const char *provider_legitimization_id, + struct TALER_PaytoHashP *h_payto, + uint64_t *process_row); + + +/** + * @brief The plugin API, returned from the plugin's "init" function. + * The argument given to "init" is simply a configuration handle. + */ +struct TALER_KYCLOGIC_Plugin +{ + + /** + * Closure for all callbacks. + */ + void *cls; + + /** + * Name of the library which generated this plugin. Set by the + * plugin loader. + */ + char *library_name; + + /** + * Name of the logic, for webhook matching. Set by the + * plugin loader. + */ + char *name; + + /** + * Load the configuration of the KYC provider. + * + * @param cls closure + * @param provider_section_name configuration section to parse + * @return NULL if configuration is invalid + */ + struct TALER_KYCLOGIC_ProviderDetails * + (*load_configuration)(void *cls, + const char *provider_section_name); + + /** + * Release configuration resources previously loaded + * + * @param[in] pd configuration to release + */ + void + (*unload_configuration)(struct TALER_KYCLOGIC_ProviderDetails *pd); + + + /** + * Initiate KYC check. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param account_id which account to trigger process for + * @param process_row unique ID for the legitimization process + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_InitiateHandle * + (*initiate)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + const struct TALER_PaytoHashP *account_id, + uint64_t process_row, + TALER_KYCLOGIC_InitiateCallback cb, + void *cb_cls); + + + /** + * Cancel KYC check initiation. + * + * @param[in] ih handle of operation to cancel + */ + void + (*initiate_cancel) (struct TALER_KYCLOGIC_InitiateHandle *ih); + + + /** + * Check KYC status and return status to human. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param connection MHD connection object (for HTTP headers) + * @param account_id which account to trigger process for + * @param process_row row in the legitimization processes table the legitimization is for + * @param provider_user_id user ID (or NULL) the proof is for + * @param provider_legitimization_id legitimization ID the proof is for + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_ProofHandle * + (*proof)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + struct MHD_Connection *connection, + const struct TALER_PaytoHashP *account_id, + uint64_t process_row, + const char *provider_user_id, + const char *provider_legitimization_id, + TALER_KYCLOGIC_ProofCallback cb, + void *cb_cls); + + + /** + * Cancel KYC proof. + * + * @param[in] ph handle of operation to cancel + */ + void + (*proof_cancel) (struct TALER_KYCLOGIC_ProofHandle *ph); + + + /** + * Check KYC status and return result for Webhook. + * + * @param cls the @e cls of this struct with the plugin-specific state + * @param pd provider configuration details + * @param plc callback to lookup accounts with + * @param plc_cls closure for @a plc + * @param http_method HTTP method used for the webhook + * @param url_path rest of the URL after `/kyc-webhook/$LOGIC/` + * @param connection MHD connection object (for HTTP headers) + * @param body_size number of bytes in @a body + * @param body HTTP request body + * @param cb function to call with the result + * @param cb_cls closure for @a cb + * @return handle to cancel operation early + */ + struct TALER_KYCLOGIC_WebhookHandle * + (*webhook)(void *cls, + const struct TALER_KYCLOGIC_ProviderDetails *pd, + TALER_KYCLOGIC_ProviderLookupCallback plc, + void *plc_cls, + const char *http_method, + const char *const url_path[], + struct MHD_Connection *connection, + const json_t *upload, + TALER_KYCLOGIC_WebhookCallback cb, + void *cb_cls); + + + /** + * Cancel KYC webhook execution. + * + * @param[in] wh handle of operation to cancel + */ + void + (*webhook_cancel) (struct TALER_KYCLOGIC_WebhookHandle *wh); + +}; + + +#endif /* _TALER_KYCLOGIC_PLUGIN_H */ diff --git a/src/include/taler_mhd_lib.h b/src/include/taler_mhd_lib.h index 71006e8bc..57d041758 100644 --- a/src/include/taler_mhd_lib.h +++ b/src/include/taler_mhd_lib.h @@ -27,10 +27,17 @@ #include <jansson.h> #include <microhttpd.h> #include "taler_error_codes.h" +#include "taler_util.h" #include <gnunet/gnunet_mhd_compat.h> /** + * Maximum POST request size. + */ +#define TALER_MHD_REQUEST_BUFFER_MAX (1024 * 1024 * 16) + + +/** * Global options for response generation. */ enum TALER_MHD_GlobalOptions @@ -97,6 +104,20 @@ TALER_MHD_can_compress (struct MHD_Connection *connection); /** + * Check if @a mime matches the @a accept_pattern. For this function, the @a + * accept_pattern may include multiple values separated by ";". + * + * @param accept_pattern a mime pattern like "text/plain" + * or "image/STAR" or "text/plain; text/xml" + * @param mime the mime type to match + * @return true if @a mime matches the @a accept_pattern + */ +bool +TALER_MHD_xmime_matches (const char *accept_pattern, + const char *mime); + + +/** * Send JSON object as response. * * @param connection the MHD connection @@ -111,6 +132,21 @@ TALER_MHD_reply_json (struct MHD_Connection *connection, /** + * Send JSON object as response, and free the @a json + * object. + * + * @param connection the MHD connection + * @param json the json object (freed!) + * @param response_code the http response code + * @return MHD result code + */ +MHD_RESULT +TALER_MHD_reply_json_steal (struct MHD_Connection *connection, + json_t *json, + unsigned int response_code); + + +/** * Function to call to handle the request by building a JSON * reply from a format string and varargs. * @@ -128,19 +164,60 @@ TALER_MHD_reply_json_pack (struct MHD_Connection *connection, /** + * Function to call to handle the request by building a JSON + * reply from varargs. + * + * @param connection the MHD connection to handle + * @param response_code HTTP response code to use + * @param ... varargs of JSON pack specification + * @return MHD result code + */ +#define TALER_MHD_REPLY_JSON_PACK(connection,response_code,...) \ + TALER_MHD_reply_json_steal (connection, GNUNET_JSON_PACK (__VA_ARGS__), \ + response_code) + + +/** * Send a response indicating an error. * * @param connection the MHD connection to use * @param ec error code uniquely identifying the error * @param http_status HTTP status code to use - * @param hint human readable hint about the error + * @param detail additional optional detail about the error * @return a MHD result code */ MHD_RESULT TALER_MHD_reply_with_error (struct MHD_Connection *connection, unsigned int http_status, enum TALER_ErrorCode ec, - const char *hint); + const char *detail); + + +/** + * Send a response indicating an error. The HTTP status code is + * to be derived from the @a ec. + * + * @param connection the MHD connection to use + * @param ec error code uniquely identifying the error + * @param detail additional optional detail about the error + * @return a MHD result code + */ +MHD_RESULT +TALER_MHD_reply_with_ec (struct MHD_Connection *connection, + enum TALER_ErrorCode ec, + const char *detail); + + +/** + * Produce HTTP "Date:" header. + * + * @param at time to write to @a date + * @param[out] date where to write the header, with + * at least 128 bytes available space. + */ +void +TALER_MHD_get_date_string (struct GNUNET_TIME_Absolute at, + char date[128]); /** @@ -154,6 +231,16 @@ TALER_MHD_make_json (const json_t *json); /** + * Make JSON response object and free @a json. + * + * @param json the json object, freed. + * @return MHD response object + */ +struct MHD_Response * +TALER_MHD_make_json_steal (json_t *json); + + +/** * Make JSON response object. * * @param fmt format string for pack @@ -166,15 +253,36 @@ TALER_MHD_make_json_pack (const char *fmt, /** + * Make JSON response object. + * + * @param ... varargs + * @return MHD response object + */ +#define TALER_MHD_MAKE_JSON_PACK(...) \ + TALER_MHD_make_json_steal (GNUNET_JSON_PACK (__VA_ARGS__)) + + +/** + * Pack Taler error code @a ec and associated hint into a + * JSON object. + * + * @param ec error code to pack + * @return packer array entries (two!) + */ +#define TALER_MHD_PACK_EC(ec) \ + GNUNET_JSON_pack_uint64 ("code", ec), \ + GNUNET_JSON_pack_string ("hint", TALER_ErrorCode_get_hint (ec)) + +/** * Create a response indicating an internal error. * * @param ec error code to return - * @param hint hint about the internal error's nature + * @param detail additional optional detail about the error, can be NULL * @return a MHD response object */ struct MHD_Response * TALER_MHD_make_error (enum TALER_ErrorCode ec, - const char *hint); + const char *detail); /** @@ -264,7 +372,8 @@ TALER_MHD_parse_post_cleanup_callback (void *con_cls); /** * Parse JSON object into components based on the given field - * specification. + * specification. If parsing fails, we return an HTTP + * status code of 400 (#MHD_HTTP_BAD_REQUEST). * * @param connection the connection to send an error response to * @param root the JSON node to start the navigation at. @@ -283,6 +392,30 @@ TALER_MHD_parse_json_data (struct MHD_Connection *connection, /** + * Parse JSON object that we (the server!) generated into components based on + * the given field specification. The difference to + * #TALER_MHD_parse_json_data() is that this function will fail + * with an HTTP failure of 500 (internal server error) in case + * parsing fails, instead of blaming it on the client with a + * 400 (#MHD_HTTP_BAD_REQUEST). + * + * @param connection the connection to send an error response to + * @param root the JSON node to start the navigation at. + * @param spec field specification for the parser + * @return + * #GNUNET_YES if navigation was successful (caller is responsible + * for freeing allocated variable-size data using + * GNUNET_JSON_parse_free() when done) + * #GNUNET_NO if json is malformed, error response was generated + * #GNUNET_SYSERR on internal error + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_internal_json_data (struct MHD_Connection *connection, + const json_t *root, + struct GNUNET_JSON_Specification *spec); + + +/** * Parse JSON array into components based on the given field * specification. Generates error response on parse errors. * @@ -305,7 +438,201 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection, /** - * Extraxt fixed-size base32crockford encoded data from request. + * Extract optional "timeout_ms" argument from request. + * + * @param connection the MHD connection + * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout, + * the current time plus the value given under "timeout_ms" otherwise + * @return #GNUNET_OK on success, #GNUNET_NO if an + * error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_timeout (struct MHD_Connection *connection, + struct GNUNET_TIME_Absolute *expiration); + + +/** + * Extract optional "timeout_ms" argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the "timeout_ms" + * argument existed but failed to parse. + * + * @param connection the MHD connection + * @param[out] expiration set to #GNUNET_TIME_UNIT_ZERO_ABS if there was no timeout, + * the current time plus the value given under "timeout_ms" otherwise + */ +#define TALER_MHD_parse_request_timeout(connection,expiration) \ + do { \ + switch (TALER_MHD_parse_request_arg_timeout (connection, \ + expiration)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional numeric limit argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] off set to the offset, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_number (struct MHD_Connection *connection, + const char *name, + uint64_t *off); + + +/** + * Extract optional numeric argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] off set to the given numeric value, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_number(connection,name,off) \ + do { \ + switch (TALER_MHD_parse_request_arg_number (connection, \ + name, \ + off)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional signed numeric limit argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] val set to the signed value, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_snumber (struct MHD_Connection *connection, + const char *name, + int64_t *val); + + +/** + * Extract optional numeric argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] val set to the given numeric value, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_snumber(connection,name,val) \ + do { \ + switch (TALER_MHD_parse_request_arg_snumber (connection, \ + name, \ + val)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Extract optional amount argument from request. + * + * @param connection the MHD connection + * @param name name of the query parameter + * @param[out] val set to the amount, unchanged if the + * option was not given + * @return #GNUNET_OK on success, + * #GNUNET_NO if an error was returned on @a connection (caller should return #MHD_YES) and + * #GNUNET_SYSERR if we failed to return an error (caller should return #MHD_NO) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_arg_amount (struct MHD_Connection *connection, + const char *name, + struct TALER_Amount *val); + + +/** + * Extract optional amount argument from request. + * Macro that *returns* #MHD_YES/#MHD_NO if the + * requested argument existed but failed to parse. + * + * @param connection the MHD connection + * @param name name of the argument to parse + * @param[out] val set to the given amount, + * unchanged if value was not specified + */ +#define TALER_MHD_parse_request_amount(connection,name,val) \ + do { \ + switch (TALER_MHD_parse_request_arg_amount (connection, \ + name, \ + val)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) + + +/** + * Determines which of the given choices is preferred + * by the client. Parses an HTTP header such as + * "Accept:" or "Language:" to find entries matching + * the list of strings given in the variadic argument + * list. Returns the index of the preferred choice. + * + * @param connection HTTP request handle + * @param header type of HTTP header to evaluate + * @param ... NULL-terminated list of choices to + * check for in the header + * @return -1 if none of the given choices is in + * the header, -2 if the header is missing, + * otherwise index of preferred choice in + * the varargs list + */ +int +TALER_MHD_check_accept (struct MHD_Connection *connection, + const char *header, + ...); + + +/** + * Extract fixed-size base32crockford encoded data from request argument. * * Queues an error response to the connection if the parameter is missing or * invalid. @@ -314,16 +641,195 @@ TALER_MHD_parse_json_array (struct MHD_Connection *connection, * @param param_name the name of the parameter with the key * @param[out] out_data pointer to store the result * @param out_size expected size of @a out_data + * @param[out] present set to true if argument was found * @return * #GNUNET_YES if the the argument is present - * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_NO if the argument is malformed * #GNUNET_SYSERR on internal error (error response could not be sent) */ enum GNUNET_GenericReturnValue TALER_MHD_parse_request_arg_data (struct MHD_Connection *connection, const char *param_name, void *out_data, - size_t out_size); + size_t out_size, + bool *present); + + +/** + * Extract fixed-size base32crockford encoded data from request header. + * + * Queues an error response to the connection if the parameter is missing or + * invalid. + * + * @param connection the MHD connection + * @param header_name the name of the HTTP header with the value + * @param[out] out_data pointer to store the result + * @param out_size expected size of @a out_data + * @param[out] present set to true if argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_parse_request_header_data (struct MHD_Connection *connection, + const char *header_name, + void *out_data, + size_t out_size, + bool *present); + +/** + * Extract fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the parameter with the key + * @param[out] val pointer to store the result, type must determine size + * @param[in,out] required pass true to require presence of this argument; if 'false' + * set to true if the argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_arg_auto(connection,name,val,required) \ + do { \ + bool p; \ + switch (TALER_MHD_parse_request_arg_data (connection, name, \ + val, sizeof (*val), &p)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + if (required & (! p)) \ + return TALER_MHD_reply_with_error ( \ + connection, \ + MHD_HTTP_BAD_REQUEST, \ + TALER_EC_GENERIC_PARAMETER_MISSING, \ + name); \ + required = p; \ + break; \ + } \ + } while (0) + + +/** + * Extract required fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the parameter with the key + * @param[out] val pointer to store the result, type must determine size + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_arg_auto_t(connection,name,val) \ + do { \ + bool b = true; \ + TALER_MHD_parse_request_arg_auto (connection,name,val,b); \ + } while (0) + +/** + * Extract fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the header with the key + * @param[out] val pointer to store the result, type must determine size + * @param[in,out] required pass true to require presence of this argument; if 'false' + * set to true if the argument was found + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_header_auto(connection,name,val,required) \ + do { \ + bool p; \ + switch (TALER_MHD_parse_request_header_data (connection, name, \ + val, sizeof (*val), &p)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + if (required & (! p)) \ + return TALER_MHD_reply_with_error ( \ + connection, \ + MHD_HTTP_BAD_REQUEST, \ + TALER_EC_GENERIC_PARAMETER_MISSING, \ + name); \ + required = p; \ + break; \ + } \ + } while (0) + + +/** + * Extract required fixed-size base32crockford encoded data from request. + * + * @param connection the MHD connection + * @param name the name of the header with the key + * @param[out] val pointer to store the result, type must determine size + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +#define TALER_MHD_parse_request_header_auto_t(connection,name,val) \ + do { \ + bool b = true; \ + TALER_MHD_parse_request_header_auto (connection,name,val,b); \ + } while (0) + + +/** + * Check that the 'Content-Length' header is giving + * a length below @a max_len. If not, return an + * appropriate error response and return the + * correct #MHD_YES/#MHD_NO value from this function. + * + * @param connection the MHD connection + * @param max_len maximum allowed content length + * @return + * #GNUNET_YES if the the argument is present + * #GNUNET_NO if the argument is absent or malformed + * #GNUNET_SYSERR on internal error (error response could not be sent) + */ +enum GNUNET_GenericReturnValue +TALER_MHD_check_content_length_ (struct MHD_Connection *connection, + unsigned long long max_len); + + +/** + * Check that the 'Content-Length' header is giving + * a length below @a max_len. If not, return an + * appropriate error response and return the + * correct #MHD_YES/#MHD_NO value from this function. + * + * @param connection the MHD connection + * @param max_len maximum allowed content length + */ +#define TALER_MHD_check_content_length(connection,max_len) \ + do { \ + switch (TALER_MHD_check_content_length_ (connection, max_len)) \ + { \ + case GNUNET_SYSERR: \ + GNUNET_break (0); \ + return MHD_NO; \ + case GNUNET_NO: \ + GNUNET_break_op (0); \ + return MHD_YES; \ + case GNUNET_OK: \ + break; \ + } \ + } while (0) /** @@ -390,6 +896,35 @@ TALER_MHD_bind (const struct GNUNET_CONFIGURATION_Handle *cfg, /** + * Start to run an event loop for @a daemon. + * Only one daemon can be running per process + * using this API. + * + * @param daemon the MHD service to run + */ +void +TALER_MHD_daemon_start (struct MHD_Daemon *daemon); + + +/** + * Stop running the event loop for MHD. + * + * @return the daemon that we were previously running, + * or NULL if none was active + */ +struct MHD_Daemon * +TALER_MHD_daemon_stop (void); + + +/** + * Trigger MHD daemon that is running. Needed when + * a connection was resumed. + */ +void +TALER_MHD_daemon_trigger (void); + + +/** * Prepared responses for legal documents * (terms of service, privacy policy). */ @@ -398,7 +933,7 @@ struct TALER_MHD_Legal; /** * Load set of legal documents as specified in @a cfg in section @a section - * where the Etag is given under the @param tagoption and the directory under + * where the Etag is given under the @a tagoption and the directory under * the @a diroption. * * @param cfg configuration to use diff --git a/src/include/taler_pq_lib.h b/src/include/taler_pq_lib.h index 4545b6d5d..f45de61d9 100644 --- a/src/include/taler_pq_lib.h +++ b/src/include/taler_pq_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014, 2015, 2016 Taler Systems SA + Copyright (C) 2014-2022 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -19,37 +19,112 @@ * @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 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 GNUNET_PQ_Context *db, + const struct TALER_Amount *amount); + + +/** + * 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 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_with_currency ( + const struct GNUNET_PQ_Context *db, + const struct TALER_Amount *amount); + + +/** + * Generate query parameter for a denomination public + * key. Internally, the various attributes of the + * public key will be serialized into on variable-size + * BLOB. + * + * @param denom_pub pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_denom_pub ( + const struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Generate query parameter for a denomination signature. Internally, the + * various attributes of the signature will be serialized into on + * variable-size BLOB. + * + * @param denom_sig pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_denom_sig ( + const struct TALER_DenominationSignature *denom_sig); + + +/** + * Generate query parameter for a blinded planchet. + * Internally, various attributes of the blinded + * planchet will be serialized into on + * variable-size BLOB. + * + * @param bp pointer to the query parameter to pass + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_blinded_planchet ( + const struct TALER_BlindedPlanchet *bp); + + +/** + * Generate query parameter for a blinded denomination signature. Internally, + * the various attributes of the signature will be serialized into on + * variable-size BLOB. * - * @param x pointer to the query parameter to pass + * @param denom_sig pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_amount_nbo (const struct TALER_AmountNBO *x); +TALER_PQ_query_param_blinded_denom_sig ( + const struct TALER_BlindedDenominationSignature *denom_sig); /** - * 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. + * Generate query parameter for the exchange's contribution during a + * withdraw. Internally, the various attributes of the @a alg_values will be + * serialized into on variable-size BLOB. * - * @param x pointer to the query parameter to pass + * @param alg_values 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_exchange_withdraw_values ( + const struct TALER_ExchangeWithdrawValues *alg_values); /** @@ -65,48 +140,115 @@ TALER_PQ_query_param_json (const json_t *x); /** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_PQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. + * Generate query parameter for an array of blinded denomination signatures + * + * @param num number of elements in @e denom_sigs + * @param denom_sigs array of blinded denomination signatures + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_blinded_denom_sig ( + size_t num, + const struct TALER_BlindedDenominationSignature *denom_sigs, + struct GNUNET_PQ_Context *db + ); + + +/** + * Generate query parameter for an array of blinded hashes of coin envelopes + * + * @param num number of elements in @e denom_sigs + * @param coin_evs array of blinded hashes of coin envelopes + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_blinded_coin_hash ( + size_t num, + const struct TALER_BlindedCoinHashP *coin_evs, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of GNUNET_HashCode + * + * @param num number of elements in @e hash_codes + * @param hashes array of GNUNET_HashCode + * @param db context for the db-connection + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_hash_code ( + size_t num, + const struct GNUNET_HashCode *hashes, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of amounts + * + * @param num of elements in @e amounts + * @param amounts continuous array of amounts + * @param db context for db-connection, needed for OID-lookup + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_amount ( + size_t num, + const struct TALER_Amount *amounts, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for an array of amounts + * + * @param num of elements in @e amounts + * @param amounts continuous array of amounts + * @param db context for db-connection, needed for OID-lookup + */ +struct GNUNET_PQ_QueryParam +TALER_PQ_query_param_array_amount_with_currency ( + size_t num, + const struct TALER_Amount *amounts, + struct GNUNET_PQ_Context *db); + + +/** + * Generate query parameter for a blind sign public key of variable size. * - * @param x pointer to the query parameter to pass + * @param public_key pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_absolute_time (const struct GNUNET_TIME_Absolute *x); +TALER_PQ_query_param_blind_sign_pub ( + const struct GNUNET_CRYPTO_BlindSignPublicKey *public_key); /** - * Generate query parameter for an absolute time value. - * In contrast to - * #GNUNET_PQ_query_param_absolute_time(), this function - * will abort (!) if the time given is not rounded! - * The database must store a 64-bit integer. + * Generate query parameter for a blind sign private key of variable size. * - * @param x pointer to the query parameter to pass + * @param private_key pointer to the query parameter to pass */ struct GNUNET_PQ_QueryParam -TALER_PQ_query_param_absolute_time_nbo (const struct - GNUNET_TIME_AbsoluteNBO *x); +TALER_PQ_query_param_blind_sign_priv ( + const struct GNUNET_CRYPTO_BlindSignPrivateKey *private_key); /** - * Currency amount expected. + * Currency amount expected, from a record-field of (DB) + * taler_amount_with_currency type. The currency must be stored in the + * database when using this function. * * @param name name of the field in the table - * @param currency currency to use for @a amount * @param[out] amount where to store the result * @return array entry for the result specification to use */ struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_amount_nbo (const char *name, - const char *currency, - struct TALER_AmountNBO *amount); +TALER_PQ_result_spec_amount_with_currency ( + const char *name, + struct TALER_Amount *amount); /** - * Currency amount expected. + * Currency amount expected, from a record-field of (DB) taler_amount type. + * The currency is NOT stored in the database when using this function, but + * instead passed as the @a currency argument. * * @param name name of the field in the table * @param currency currency to use for @a amount @@ -120,6 +262,69 @@ TALER_PQ_result_spec_amount (const char *name, /** + * Denomination public key expected. + * + * @param name name of the field in the table + * @param[out] denom_pub where to store the public key + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_denom_pub (const char *name, + struct TALER_DenominationPublicKey *denom_pub); + + +/** + * Denomination signature expected. + * + * @param name name of the field in the table + * @param[out] denom_sig where to store the denomination signature + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_denom_sig (const char *name, + struct TALER_DenominationSignature *denom_sig); + + +/** + * Blinded denomination signature expected. + * + * @param name name of the field in the table + * @param[out] denom_sig where to store the denomination signature + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blinded_denom_sig ( + const char *name, + struct TALER_BlindedDenominationSignature *denom_sig); + + +/** + * Exchange withdraw values expected. + * + * @param name name of the field in the table + * @param[out] ewv where to store the exchange values + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_exchange_withdraw_values ( + const char *name, + struct TALER_ExchangeWithdrawValues *ewv); + + +/** + * Blinded planchet expected. + * + * @param name name of the field in the table + * @param[out] bp where to store the blinded planchet + * @return array entry for the result specification to use + */ +struct GNUNET_PQ_ResultSpec +TALER_PQ_result_spec_blinded_planchet ( + const char *name, + struct TALER_BlindedPlanchet *bp); + + +/** * json_t expected. * * @param name name of the field in the table @@ -132,33 +337,89 @@ TALER_PQ_result_spec_json (const char *name, /** - * Rounded absolute time expected. - * In contrast to #GNUNET_PQ_query_param_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. + * Array of blinded denomination signature expected + * + * @param db context of the database connection + * @param name name of the field in the table + * @param[out] 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] at where to store the result + * @param[out] num number of elements in @e denom_sigs + * @param[out] h_coin_evs where to store the result * @return array entry for the result specification to use */ struct GNUNET_PQ_ResultSpec -TALER_PQ_result_spec_absolute_time (const char *name, - struct GNUNET_TIME_Absolute *at); +TALER_PQ_result_spec_array_blinded_coin_hash ( + struct GNUNET_PQ_Context *db, + const char *name, + size_t *num, + struct TALER_BlindedCoinHashP **h_coin_evs); /** - * Rounded absolute time expected. - * In contrast to #GNUNET_PQ_result_spec_absolute_time_nbo(), - * this function ensures that the result is rounded and can - * be converted to JSON. + * Array of 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[out] at where to store the result + * @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_absolute_time_nbo (const char *name, - struct GNUNET_TIME_AbsoluteNBO *at); +TALER_PQ_result_spec_array_amount ( + struct GNUNET_PQ_Context *db, + const char *name, + const char *currency, + size_t *num, + struct TALER_Amount **amounts); #endif /* TALER_PQ_LIB_H_ */ diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h deleted file mode 100644 index f55f0c2e4..000000000 --- a/src/include/taler_signatures.h +++ /dev/null @@ -1,1417 +0,0 @@ -/* - This file is part of TALER - Copyright (C) 2014-2017 Taler Systems SA - - TALER is free software; you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software - Foundation; either version 3, or (at your option) any later version. - - TALER is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR - A PARTICULAR PURPOSE. See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along with - TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -*/ -/** - * @file taler_signatures.h - * @brief message formats and signature constants used to define - * the binary formats of signatures in Taler - * @author Florian Dold - * @author Benedikt Mueller - * - * This file should define the constants and C structs that one needs - * to know to implement Taler clients (wallets or merchants or - * auditor) that need to produce or verify Taler signatures. - */ -#ifndef TALER_SIGNATURES_H -#define TALER_SIGNATURES_H - -#include <gnunet/gnunet_util_lib.h> -#include "taler_amount_lib.h" -#include "taler_crypto_lib.h" - -/** - * Cut-and-choose size for refreshing. Client looses the gamble (of - * unaccountable transfers) with probability 1/TALER_CNC_KAPPA. Refresh cost - * increases linearly with TALER_CNC_KAPPA, and 3 is sufficient up to a - * income/sales tax of 66% of total transaction value. As there is - * no good reason to change this security parameter, we declare it - * fixed and part of the protocol. - */ -#define TALER_CNC_KAPPA 3 - - -/*********************************************/ -/* Exchange offline signatures (with master key) */ -/*********************************************/ - -/** - * Purpose for signing public keys signed by the exchange master key. - */ -#define TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY 1024 - -/** - * Purpose for denomination keys signed by the exchange master key. - */ -#define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY 1025 - -/** - * Fees charged per (aggregate) wire transfer to the merchant. - */ -#define TALER_SIGNATURE_MASTER_WIRE_FEES 1028 - -/** - * The given revocation key was revoked and must no longer be used. - */ -#define TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED 1029 - -/** - * Signature where the Exchange confirms its IBAN details in - * the /wire response. - */ -#define TALER_SIGNATURE_MASTER_WIRE_DETAILS 1030 - -/*********************************************/ -/* Exchange online signatures (with signing key) */ -/*********************************************/ - -/** - * Purpose for the state of a reserve, signed by the exchange's signing - * key. - */ -#define TALER_SIGNATURE_EXCHANGE_RESERVE_STATUS 1032 - -/** - * Signature where the Exchange confirms a deposit request. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT 1033 - -/** - * Signature where the exchange (current signing key) confirms the - * no-reveal index for cut-and-choose and the validity of the melted - * coins. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT 1034 - -/** - * Signature where the Exchange confirms the full /keys response set. - */ -#define TALER_SIGNATURE_EXCHANGE_KEY_SET 1035 - -/** - * Signature where the Exchange confirms the /track/transaction response. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE 1036 - -/** - * Signature where the Exchange confirms the /wire/deposit response. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT 1037 - -/** - * Signature where the Exchange confirms a refund request. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND 1038 - -/** - * Signature where the Exchange confirms a recoup. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP 1039 - -/** - * Signature where the Exchange confirms it closed a reserve. - */ -#define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040 - -/** - * Signature where the Exchange confirms a recoup-refresh operation. - */ -#define TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH 1041 - - -/**********************/ -/* Auditor signatures */ -/**********************/ - -/** - * Signature where the auditor confirms that he is - * aware of certain denomination keys from the exchange. - */ -#define TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS 1064 - - -/***********************/ -/* Merchant signatures */ -/***********************/ - -/** - * Signature where the merchant confirms a contract (to the customer). - */ -#define TALER_SIGNATURE_MERCHANT_CONTRACT 1101 - -/** - * Signature where the merchant confirms a refund (of a coin). - */ -#define TALER_SIGNATURE_MERCHANT_REFUND 1102 - -/** - * Signature where the merchant confirms that he needs the wire - * transfer identifier for a deposit operation. - */ -#define TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION 1103 - -/** - * Signature where the merchant confirms that the payment was - * successful - */ -#define TALER_SIGNATURE_MERCHANT_PAYMENT_OK 1104 - -/** - * Signature where the merchant confirms that the user replayed - * a payment for a browser session. - */ -#define TALER_SIGNATURE_MERCHANT_PAY_SESSION 1106 - -/** - * Signature where the merchant confirms its own (salted) - * wire details (not yet really used). - */ -#define TALER_SIGNATURE_MERCHANT_WIRE_DETAILS 1107 - - -/*********************/ -/* Wallet signatures */ -/*********************/ - -/** - * Signature where the reserve key confirms a withdraw request. - */ -#define TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW 1200 - -/** - * Signature made by the wallet of a user to confirm a deposit of a coin. - */ -#define TALER_SIGNATURE_WALLET_COIN_DEPOSIT 1201 - -/** - * Signature using a coin key confirming the melting of a coin. - */ -#define TALER_SIGNATURE_WALLET_COIN_MELT 1202 - -/** - * Signature using a coin key requesting recoup. - */ -#define TALER_SIGNATURE_WALLET_COIN_RECOUP 1203 - -/** - * Signature using a coin key authenticating link data. - */ -#define TALER_SIGNATURE_WALLET_COIN_LINK 1204 - - -/*******************/ -/* Test signatures */ -/*******************/ - -/** - * EdDSA test signature. - */ -#define TALER_SIGNATURE_CLIENT_TEST_EDDSA 1302 - -/** - * EdDSA test signature. - */ -#define TALER_SIGNATURE_EXCHANGE_TEST_EDDSA 1303 - - -/************************/ -/* Anastasis signatures */ -/************************/ - -/** - * EdDSA signature for a policy upload. - */ -#define TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD 1400 - -/** - * EdDSA signature for a policy download. - */ -#define TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD 1401 - - -/*******************/ -/* Sync signatures */ -/*******************/ - - -/** - * EdDSA signature for a backup upload. - */ -#define TALER_SIGNATURE_SYNC_BACKUP_UPLOAD 1450 - - -GNUNET_NETWORK_STRUCT_BEGIN - -/** - * @brief Format used for to allow the wallet to authenticate - * link data provided by the exchange. - */ -struct TALER_LinkDataPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK. - * Used with an EdDSA signature of a `struct TALER_CoinPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the denomination public key of the new coin. - */ - struct GNUNET_HashCode h_denom_pub; - - /** - * Public key of the old coin being refreshed. - */ - struct TALER_CoinSpendPublicKeyP old_coin_pub; - - /** - * Transfer public key (for which the private key was not revealed) - */ - struct TALER_TransferPublicKeyP transfer_pub; - - /** - * Hash of the blinded new coin. - */ - struct GNUNET_HashCode coin_envelope_hash; -}; - - -/** - * @brief Format used for to generate the signature on a request to withdraw - * coins from a reserve. - */ -struct TALER_WithdrawRequestPS -{ - - /** - * Purpose must be #TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW. - * Used with an EdDSA signature of a `struct TALER_ReservePublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Reserve public key (which reserve to withdraw from). This is - * the public key which must match the signature. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Value of the coin being exchangeed (matching the denomination key) - * plus the transaction fee. We include this in what is being - * signed so that we can verify a reserve's remaining total balance - * without needing to access the respective denomination key - * information each time. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Withdrawal fee charged by the exchange. This must match the Exchange's - * denomination key's withdrawal fee. If the client puts in an - * invalid withdrawal fee (too high or too low) that does not match - * the Exchange's denomination key, the withdraw operation is invalid - * and will be rejected by the exchange. The @e amount_with_fee minus - * the @e withdraw_fee is must match the value of the generated - * coin. We include this in what is being signed so that we can - * verify a exchange's accounting without needing to access the - * respective denomination key information each time. - */ - struct TALER_AmountNBO withdraw_fee; - - /** - * Hash of the denomination public key for the coin that is withdrawn. - */ - struct GNUNET_HashCode h_denomination_pub GNUNET_PACKED; - - /** - * Hash of the (blinded) message to be signed by the Exchange. - */ - struct GNUNET_HashCode h_coin_envelope GNUNET_PACKED; -}; - - -/** - * @brief Format used to generate the signature on a request to deposit - * a coin into the account of a merchant. - */ -struct TALER_DepositRequestPS -{ - /** - * Purpose must be #TALER_SIGNATURE_WALLET_COIN_DEPOSIT. - * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the contract for which this deposit is made. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct GNUNET_HashCode h_wire GNUNET_PACKED; - - /** - * Time when this request was generated. Used, for example, to - * assess when (roughly) the income was achieved for tax purposes. - * Note that the Exchange will only check that the timestamp is not "too - * far" into the future (i.e. several days). The fact that the - * timestamp falls within the validity period of the coin's - * denomination key is irrelevant for the validity of the deposit - * request, as obviously the customer and merchant could conspire to - * set any timestamp. Also, the Exchange must accept very old deposit - * requests, as the merchant might have been unable to transmit the - * deposit request in a timely fashion (so back-dating is not - * prevented). - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much time does the merchant have to issue a refund request? - * Zero if refunds are not allowed. After this time, the coin - * cannot be refunded. - */ - struct GNUNET_TIME_AbsoluteNBO refund_deadline; - - /** - * Amount to be deposited, including deposit fee charged by the - * exchange. This is the total amount that the coin's value at the exchange - * will be reduced by. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Depositing fee charged by the exchange. This must match the Exchange's - * denomination key's depositing fee. If the client puts in an - * invalid deposit fee (too high or too low) that does not match the - * Exchange's denomination key, the deposit operation is invalid and - * will be rejected by the exchange. The @e amount_with_fee minus the - * @e deposit_fee is the amount that will be transferred to the - * account identified by @e h_wire. - */ - struct TALER_AmountNBO deposit_fee; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - -}; - - -/** - * @brief Format used to generate the signature on a confirmation - * from the exchange that a deposit request succeeded. - */ -struct TALER_DepositConfirmationPS -{ - /** - * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the contract for which this deposit is made. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct GNUNET_HashCode h_wire GNUNET_PACKED; - - /** - * Time when this confirmation was generated. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much time does the @e merchant have to issue a refund - * request? Zero if refunds are not allowed. After this time, the - * coin cannot be refunded. Note that the wire transfer will not be - * performed by the exchange until the refund deadline. This value - * is taken from the original deposit request. - */ - struct GNUNET_TIME_AbsoluteNBO refund_deadline; - - /** - * Amount to be deposited, excluding fee. Calculated from the - * amount with fee and the fee from the deposit request. - */ - struct TALER_AmountNBO amount_without_fee; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - -}; - - -/** - * @brief Format used to generate the signature on a request to refund - * a coin into the account of the customer. - */ -struct TALER_RefundRequestPS -{ - /** - * Purpose must be #TALER_SIGNATURE_MERCHANT_REFUND. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data to identify the contract - * which is being refunded. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * Merchant-generated transaction ID for the refund. - */ - uint64_t rtransaction_id GNUNET_PACKED; - - /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. - */ - struct TALER_AmountNBO refund_amount; - - /** - * Refund fee charged by the exchange. This must match the - * Exchange's denomination key's refund fee. If the client puts in - * an invalid refund fee (too high or too low) that does not match - * the Exchange's denomination key, the refund operation is invalid - * and will be rejected by the exchange. The @e amount_with_fee - * minus the @e refund_fee is the amount that will be credited to - * the original coin. - */ - struct TALER_AmountNBO refund_fee; - -}; - - -/** - * @brief Format used to generate the signature on a request to refund - * a coin into the account of the customer. - */ -struct TALER_RefundConfirmationPS -{ - /** - * Purpose must be #TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data to identify the contract - * which is being refunded. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * The Merchant's public key. Allows the merchant to later refund - * the transaction or to inquire about the wire transfer identifier. - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * Merchant-generated transaction ID for the refund. - */ - uint64_t rtransaction_id GNUNET_PACKED; - - /** - * Amount to be refunded, including refund fee charged by the - * exchange to the customer. - */ - struct TALER_AmountNBO refund_amount; - - /** - * Refund fee charged by the exchange. This must match the - * Exchange's denomination key's refund fee. If the client puts in - * an invalid refund fee (too high or too low) that does not match - * the Exchange's denomination key, the refund operation is invalid - * and will be rejected by the exchange. The @e amount_with_fee - * minus the @e refund_fee is the amount that will be credited to - * the original coin. - */ - struct TALER_AmountNBO refund_fee; - -}; - - -/** - * @brief Message signed by a coin to indicate that the coin should be - * melted. - */ -struct TALER_RefreshMeltCoinAffirmationPS -{ - /** - * Purpose is #TALER_SIGNATURE_WALLET_COIN_MELT. - * Used for an EdDSA signature with the `struct TALER_CoinSpendPublicKeyP`. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Which melt commitment is made by the wallet. - */ - struct TALER_RefreshCommitmentP rc GNUNET_PACKED; - - /** - * How much of the value of the coin should be melted? This amount - * includes the fees, so the final amount contributed to the melt is - * this value minus the fee for melting the coin. We include the - * fee in what is being signed so that we can verify a reserve's - * remaining total balance without needing to access the respective - * denomination key information each time. - */ - struct TALER_AmountNBO amount_with_fee; - - /** - * Melting fee charged by the exchange. This must match the Exchange's - * denomination key's melting fee. If the client puts in an invalid - * melting fee (too high or too low) that does not match the Exchange's - * denomination key, the melting operation is invalid and will be - * rejected by the exchange. The @e amount_with_fee minus the @e - * melt_fee is the amount that will be credited to the melting - * session. - */ - struct TALER_AmountNBO melt_fee; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. The deposit request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_CoinSpendPublicKeyP coin_pub; -}; - - -/** - * @brief Format of the block signed by the Exchange in response to a successful - * "/refresh/melt" request. Hereby the exchange affirms that all of the - * coins were successfully melted. This also commits the exchange to a - * particular index to not be revealed during the refresh. - */ -struct TALER_RefreshMeltConfirmationPS -{ - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_MELT. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Commitment made in the /refresh/melt. - */ - struct TALER_RefreshCommitmentP rc GNUNET_PACKED; - - /** - * Index that the client will not have to reveal, in NBO. - * Must be smaller than #TALER_CNC_KAPPA. - */ - uint32_t noreveal_index GNUNET_PACKED; - -}; - - -/** - * @brief Information about a signing key of the exchange. Signing keys are used - * to sign exchange messages other than coins, i.e. to confirm that a - * deposit was successful or that a refresh was accepted. - */ -struct TALER_ExchangeSigningKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_SIGNING_KEY_VALIDITY. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Master public key of the exchange corresponding to @e signature. - * This is the long-term offline master key of the exchange. - */ - struct TALER_MasterPublicKeyP master_public_key; - - /** - * When does this signing key begin to be valid? - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * When does this signing key expire? Note: This is currently when - * the Exchange will definitively stop using it. Signatures made with - * the key remain valid until @e end. When checking validity periods, - * clients should allow for some overlap between keys and tolerate - * the use of either key during the overlap time (due to the - * possibility of clock skew). - */ - struct GNUNET_TIME_AbsoluteNBO expire; - - /** - * When do signatures with this signing key become invalid? After - * this point, these signatures cannot be used in (legal) disputes - * anymore, as the Exchange is then allowed to destroy its side of the - * evidence. @e end is expected to be significantly larger than @e - * expire (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO end; - - /** - * The public online signing key that the exchange will use - * between @e start and @e expire. - */ - struct TALER_ExchangePublicKeyP signkey_pub; -}; - - -/** - * @brief Signature made by the exchange over the full set of keys, used - * to detect cheating exchanges that give out different sets to - * different users. - */ -struct TALER_ExchangeKeySetPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_KEY_SET. Signed - * by a `struct TALER_ExchangePublicKeyP` using EdDSA. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Time of the key set issue. - */ - struct GNUNET_TIME_AbsoluteNBO list_issue_date; - - /** - * Hash over the various denomination signing keys returned. - */ - struct GNUNET_HashCode hc GNUNET_PACKED; -}; - - -/** - * @brief Information about a denomination key. Denomination keys - * are used to sign coins of a certain value into existence. - */ -struct TALER_DenominationKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * The long-term offline master key of the exchange that was - * used to create @e signature. - */ - struct TALER_MasterPublicKeyP master; - - /** - * Start time of the validity period for this key. - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * The exchange will sign fresh coins between @e start and this time. - * @e expire_withdraw will be somewhat larger than @e start to - * ensure a sufficiently large anonymity set, while also allowing - * the Exchange to limit the financial damage in case of a key being - * compromised. Thus, exchanges with low volume are expected to have a - * longer withdraw period (@e expire_withdraw - @e start) than exchanges - * with high transaction volume. The period may also differ between - * types of coins. A exchange may also have a few denomination keys - * with the same value with overlapping validity periods, to address - * issues such as clock skew. - */ - struct GNUNET_TIME_AbsoluteNBO expire_withdraw; - - /** - * Coins signed with the denomination key must be spent or refreshed - * between @e start and this expiration time. After this time, the - * exchange will refuse transactions involving this key as it will - * "drop" the table with double-spending information (shortly after) - * this time. Note that wallets should refresh coins significantly - * before this time to be on the safe side. @e expire_deposit must be - * significantly larger than @e expire_withdraw (by months or even - * years). - */ - struct GNUNET_TIME_AbsoluteNBO expire_deposit; - - /** - * When do signatures with this denomination key become invalid? - * After this point, these signatures cannot be used in (legal) - * disputes anymore, as the Exchange is then allowed to destroy its side - * of the evidence. @e expire_legal is expected to be significantly - * larger than @e expire_deposit (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO expire_legal; - - /** - * The value of the coins signed with this denomination key. - */ - struct TALER_AmountNBO value; - - /** - * The fee the exchange charges when a coin of this type is withdrawn. - * (can be zero). - */ - struct TALER_AmountNBO fee_withdraw; - - /** - * The fee the exchange charges when a coin of this type is deposited. - * (can be zero). - */ - struct TALER_AmountNBO fee_deposit; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refresh; - - /** - * The fee the exchange charges when a coin of this type is refunded. - * (can be zero). Note that refund fees are charged to the customer; - * if a refund is given, the deposit fee is also refunded. - */ - struct TALER_AmountNBO fee_refund; - - /** - * Hash code of the denomination public key. (Used to avoid having - * the variable-size RSA key in this struct.) - */ - struct GNUNET_HashCode denom_hash GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by an auditor affirming - * the master public key and the denomination keys - * of a exchange. - */ -struct TALER_ExchangeKeyValidityPS -{ - - /** - * Purpose is #TALER_SIGNATURE_AUDITOR_EXCHANGE_KEYS. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the auditor's URL (including 0-terminator). - */ - struct GNUNET_HashCode auditor_url_hash; - - /** - * The long-term offline master key of the exchange, affirmed by the - * auditor. Hashed string, including 0-terminator. - */ - struct TALER_MasterPublicKeyP master; - - /** - * Start time of the validity period for this key. - */ - struct GNUNET_TIME_AbsoluteNBO start; - - /** - * The exchange will sign fresh coins between @e start and this time. - * @e expire_withdraw will be somewhat larger than @e start to - * ensure a sufficiently large anonymity set, while also allowing - * the Exchange to limit the financial damage in case of a key being - * compromised. Thus, exchanges with low volume are expected to have a - * longer withdraw period (@e expire_withdraw - @e start) than exchanges - * with high transaction volume. The period may also differ between - * types of coins. A exchange may also have a few denomination keys - * with the same value with overlapping validity periods, to address - * issues such as clock skew. - */ - struct GNUNET_TIME_AbsoluteNBO expire_withdraw; - - /** - * Coins signed with the denomination key must be spent or refreshed - * between @e start and this expiration time. After this time, the - * exchange will refuse transactions involving this key as it will - * "drop" the table with double-spending information (shortly after) - * this time. Note that wallets should refresh coins significantly - * before this time to be on the safe side. @e expire_deposit must be - * significantly larger than @e expire_withdraw (by months or even - * years). - */ - struct GNUNET_TIME_AbsoluteNBO expire_deposit; - - /** - * When do signatures with this denomination key become invalid? - * After this point, these signatures cannot be used in (legal) - * disputes anymore, as the Exchange is then allowed to destroy its side - * of the evidence. @e expire_legal is expected to be significantly - * larger than @e expire_deposit (by a year or more). - */ - struct GNUNET_TIME_AbsoluteNBO expire_legal; - - /** - * The value of the coins signed with this denomination key. - */ - struct TALER_AmountNBO value; - - /** - * The fee the exchange charges when a coin of this type is withdrawn. - * (can be zero). - */ - struct TALER_AmountNBO fee_withdraw; - - /** - * The fee the exchange charges when a coin of this type is deposited. - * (can be zero). - */ - struct TALER_AmountNBO fee_deposit; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refresh; - - /** - * The fee the exchange charges when a coin of this type is refreshed. - * (can be zero). - */ - struct TALER_AmountNBO fee_refund; - - /** - * Hash code of the denomination public key. (Used to avoid having - * the variable-size RSA key in this struct.) - */ - struct GNUNET_HashCode denom_hash GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by the exchange's master - * key affirming the IBAN details for the exchange. - */ -struct TALER_MasterWireDetailsPS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_WIRE_DETAILS. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the account holder's payto:// URL and - * the salt, as done by #TALER_exchange_wire_signature_hash(). - */ - struct GNUNET_HashCode h_wire_details GNUNET_PACKED; - -}; - - -/** - * @brief Information signed by the exchange's master - * key stating the wire fee to be paid per wire transfer. - */ -struct TALER_MasterWireFeePS -{ - - /** - * Purpose is #TALER_SIGNATURE_MASTER_WIRE_FEES. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the wire method (yes, H("x-taler-bank") or H("iban")), in lower - * case, including 0-terminator. Used to uniquely identify which - * wire method these fees apply to. - */ - struct GNUNET_HashCode h_wire_method; - - /** - * Start date when the fee goes into effect. - */ - struct GNUNET_TIME_AbsoluteNBO start_date; - - /** - * End date when the fee stops being in effect (exclusive) - */ - struct GNUNET_TIME_AbsoluteNBO end_date; - - /** - * Fee charged to the merchant per wire transfer. - */ - struct TALER_AmountNBO wire_fee; - - /** - * Closing fee charged when we wire back funds of a reserve. - */ - struct TALER_AmountNBO closing_fee; - -}; - - -/** - * @brief Message confirming that a denomination key was revoked. - */ -struct TALER_MasterDenominationKeyRevocationPS -{ - /** - * Purpose is #TALER_SIGNATURE_MASTER_DENOMINATION_KEY_REVOKED. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the denomination key. - */ - struct GNUNET_HashCode h_denom_pub; - -}; - - -/** - * @brief Format used to generate the signature on a request to obtain - * the wire transfer identifier associated with a deposit. - */ -struct TALER_DepositTrackPS -{ - /** - * Purpose must be #TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the proposal data of the contract for which this deposit is made. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * Hash over the wiring information of the merchant. - */ - struct GNUNET_HashCode h_wire GNUNET_PACKED; - - /** - * The Merchant's public key. The deposit inquiry request is to be - * signed by the corresponding private key (using EdDSA). - */ - struct TALER_MerchantPublicKeyP merchant; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - -}; - - -/** - * @brief Format internally used for packing the detailed information - * to generate the signature for /track/transfer signatures. - */ -struct TALER_WireDepositDetailP -{ - - /** - * Hash of the contract - */ - struct GNUNET_HashCode h_contract_terms; - - /** - * Time when the wire transfer was performed by the exchange. - */ - struct GNUNET_TIME_AbsoluteNBO execution_time; - - /** - * Coin's public key. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Total value of the coin. - */ - struct TALER_AmountNBO deposit_value; - - /** - * Fees charged by the exchange for the deposit. - */ - struct TALER_AmountNBO deposit_fee; - -}; - - -/** - * @brief Format used to generate the signature for /wire/deposit - * replies. - */ -struct TALER_WireDepositDataPS -{ - /** - * Purpose header for the signature over the contract with - * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE_DEPOSIT. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Total amount that was transferred. - */ - struct TALER_AmountNBO total; - - /** - * Wire fee that was charged. - */ - struct TALER_AmountNBO wire_fee; - - /** - * Public key of the merchant (for all aggregated transactions). - */ - struct TALER_MerchantPublicKeyP merchant_pub; - - /** - * Hash of wire details of the merchant. - */ - struct GNUNET_HashCode h_wire; - - /** - * Hash of the individual deposits that were aggregated, - * each in the format of a `struct TALER_WireDepositDetailP`. - */ - struct GNUNET_HashCode h_details; - -}; - -/** - * The contract sent by the merchant to the wallet. - */ -struct TALER_ProposalDataPS -{ - /** - * Purpose header for the signature over the proposal data - * with purpose #TALER_SIGNATURE_MERCHANT_CONTRACT. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the JSON contract in UTF-8 including 0-termination, - * using JSON_COMPACT | JSON_SORT_KEYS - */ - struct GNUNET_HashCode hash; -}; - -/** - * Used by merchants to return signed responses to /pay requests. - * Currently only used to return 200 OK signed responses. - */ -struct PaymentResponsePS -{ - /** - * Set to TALER_SIGNATURE_MERCHANT_PAYMENT_OK so far. Note that - * unsuccessful payments are usually proven by some exchange's signature, - * thus it is unlikely that a merchant needs to set a purpose other than - * the above mentioned - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash of the proposal data associated with this confirmation - */ - struct GNUNET_HashCode h_contract_terms; -}; - - -/** - * Details affirmed by the exchange about a wire transfer the exchange - * claims to have done with respect to a deposit operation. - */ -struct TALER_ConfirmWirePS -{ - /** - * Purpose header for the signature over the contract with - * purpose #TALER_SIGNATURE_EXCHANGE_CONFIRM_WIRE. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hash over the wiring information of the merchant. - */ - struct GNUNET_HashCode h_wire GNUNET_PACKED; - - /** - * Hash over the contract for which this deposit is made. - */ - struct GNUNET_HashCode h_contract_terms GNUNET_PACKED; - - /** - * Raw value (binary encoding) of the wire transfer subject. - */ - struct TALER_WireTransferIdentifierRawP wtid; - - /** - * The coin's public key. This is the value that must have been - * signed (blindly) by the Exchange. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * When did the exchange execute this transfer? Note that the - * timestamp may not be exactly the same on the wire, i.e. - * because the wire has a different timezone or resolution. - */ - struct GNUNET_TIME_AbsoluteNBO execution_time; - - /** - * The contribution of @e coin_pub to the total transfer volume. - * This is the value of the deposit minus the fee. - */ - struct TALER_AmountNBO coin_contribution; - -}; - - -/** - * Signed data to request that a coin should be refunded as part of - * the "emergency" /recoup protocol. The refund will go back to the bank - * account that created the reserve. - */ -struct TALER_RecoupRequestPS -{ - /** - * Purpose is #TALER_SIGNATURE_WALLET_COIN_RECOUP - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Public key of the coin to be refunded. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Hash of the denomination public key of the coin. - */ - struct GNUNET_HashCode h_denom_pub; - - /** - * Blinding factor that was used to withdraw the coin. - */ - struct TALER_DenominationBlindingKeyP coin_blind; -}; - - -/** - * Response by which the exchange affirms that it will - * refund a coin as part of the emergency /recoup - * protocol. The recoup will go back to the bank - * account that created the reserve. - */ -struct TALER_RecoupConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange receive the recoup request? - * Indirectly determines when the wire transfer is (likely) - * to happen. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much of the coin's value will the exchange transfer? - * (Needed in case the coin was partially spent.) - */ - struct TALER_AmountNBO recoup_amount; - - /** - * Public key of the coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Public key of the reserve that will receive the recoup. - */ - struct TALER_ReservePublicKeyP reserve_pub; -}; - - -/** - * Response by which the exchange affirms that it will refund a refreshed coin - * as part of the emergency /recoup protocol. The recoup will go back to the - * old coin's balance. - */ -struct TALER_RecoupRefreshConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP_REFRESH - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange receive the recoup request? - * Indirectly determines when the wire transfer is (likely) - * to happen. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much of the coin's value will the exchange transfer? - * (Needed in case the coin was partially spent.) - */ - struct TALER_AmountNBO recoup_amount; - - /** - * Public key of the refreshed coin. - */ - struct TALER_CoinSpendPublicKeyP coin_pub; - - /** - * Public key of the old coin that will receive the recoup. - */ - struct TALER_CoinSpendPublicKeyP old_coin_pub; -}; - - -/** - * Response by which the exchange affirms that it has - * closed a reserve and send back the funds. - */ -struct TALER_ReserveCloseConfirmationPS -{ - - /** - * Purpose is #TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * When did the exchange initiate the wire transfer. - */ - struct GNUNET_TIME_AbsoluteNBO timestamp; - - /** - * How much did the exchange send? - */ - struct TALER_AmountNBO closing_amount; - - /** - * How much did the exchange charge for closing the reserve? - */ - struct TALER_AmountNBO closing_fee; - - /** - * Public key of the reserve that received the recoup. - */ - struct TALER_ReservePublicKeyP reserve_pub; - - /** - * Hash of the receiver's bank account. - */ - struct GNUNET_HashCode h_wire; - - /** - * Wire transfer subject. - */ - struct TALER_WireTransferIdentifierRawP wtid; -}; - - -/** - * Used by the merchant to confirm with a signature that the refund has - * been successfully done. Even though the frontend doesn't usually do crypto, - * this signature may turn useful in court. - */ -struct TALER_MerchantRefundConfirmationPS -{ - /** - * Set to #TALER_SIGNATURE_MERCHANT_REFUND_OK. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hashed order id; in case frontend wants to check it. - * Hashed without the 0-termination. - */ - struct GNUNET_HashCode h_order_id GNUNET_PACKED; - -}; - -/** - * Used by the merchant to confirm to the frontend that - * the user did a payment replay with the current browser session. - */ -struct TALER_MerchantPaySessionSigPS -{ - /** - * Set to #TALER_SIGNATURE_MERCHANT_PAY_SESSION. - */ - struct GNUNET_CRYPTO_EccSignaturePurpose purpose; - - /** - * Hashed order id. - * Hashed without the 0-termination. - */ - struct GNUNET_HashCode h_order_id GNUNET_PACKED; - - /** - * Hashed session id. - * Hashed without the 0-termination. - */ - struct GNUNET_HashCode h_session_id GNUNET_PACKED; - -}; - - -GNUNET_NETWORK_STRUCT_END - -#endif diff --git a/src/include/taler_sq_lib.h b/src/include/taler_sq_lib.h new file mode 100644 index 000000000..b5749308e --- /dev/null +++ b/src/include/taler_sq_lib.h @@ -0,0 +1,99 @@ +/* + This file is part of TALER + Copyright (C) 2020 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file include/taler_sq_lib.h + * @brief helper functions for DB interactions with SQLite + * @author Jonathan Buchanan + */ +#ifndef TALER_SQ_LIB_H_ +#define TALER_SQ_LIB_H_ + +#include <sqlite3.h> +#include <jansson.h> +#include <gnunet/gnunet_sq_lib.h> +#include "taler_util.h" + +/** + * Generate query parameter for a currency, consisting of the + * components "value", "fraction" in this order. The + * types must be a 64-bit integer and a 64-bit integer. + * + * @param x pointer to the query parameter to pass + */ +struct GNUNET_SQ_QueryParam +TALER_SQ_query_param_amount_nbo (const struct TALER_AmountNBO *x); + + +/** + * Generate query parameter for a currency, consisting of the + * components "value", "fraction" in this order. The + * types must be a 64-bit integer and a 64-bit integer. + * + * @param x pointer to the query parameter to pass + */ +struct GNUNET_SQ_QueryParam +TALER_SQ_query_param_amount (const struct TALER_Amount *x); + + +/** + * Generate query parameter for a JSON object (stored as a string + * in the DB). Note that @a x must really be a JSON object or array, + * passing just a value (string, integer) is not supported and will + * result in an abort. + * + * @param x pointer to the json object to pass + */ +struct GNUNET_SQ_QueryParam +TALER_SQ_query_param_json (const json_t *x); + + +/** + * Currency amount expected. + * + * @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_SQ_ResultSpec +TALER_SQ_result_spec_amount_nbo (const char *currency, + struct TALER_AmountNBO *amount); + + +/** + * Currency amount expected. + * + * @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_SQ_ResultSpec +TALER_SQ_result_spec_amount (const char *currency, + struct TALER_Amount *amount); + + +/** + * json_t expected. + * + * @param[out] jp where to store the result + * @return array entry for the result specification to use + */ +struct GNUNET_SQ_ResultSpec +TALER_SQ_result_spec_json (json_t **jp); + + +#endif /* TALER_SQ_LIB_H_ */ + +/* end of include/taler_sq_lib.h */ diff --git a/src/include/taler_templating_lib.h b/src/include/taler_templating_lib.h new file mode 100644 index 000000000..6af6db715 --- /dev/null +++ b/src/include/taler_templating_lib.h @@ -0,0 +1,130 @@ +/* + This file is part of TALER + Copyright (C) 2020, 2022 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + TALER is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file taler_templating_lib.h + * @brief logic to load and complete HTML templates + * @author Christian Grothoff + */ +#ifndef TALER_TEMPLATING_LIB_H +#define TALER_TEMPLATING_LIB_H + +#include <microhttpd.h> +#include "taler_mhd_lib.h" + +/** + * Fill in Mustach template @a tmpl using the data from @a root + * and return the result in @a result. + * + * @param tmpl 0-terminated string with Mustach template + * @param root JSON data to fill into the template + * @param[out] result where to write the result + * @param[out] result_size where to write the length of the result + * @return 0 on success, otherwise Mustach-specific error code + */ +int +TALER_TEMPLATING_fill (const char *tmpl, + const json_t *root, + void **result, + size_t *result_size); + + +/** + * Load a @a template and substitute using @a root, returning the result in a + * @a reply encoded suitable for the @a connection with the given @a + * http_status code. On errors, the @a http_status code + * is updated to reflect the type of error encoded in the + * @a reply. + * + * @param connection the connection we act upon + * @param[in,out] http_status code to use on success, + * set to alternative code on failure + * @param template basename of the template to load + * @param instance_id instance ID, used to compute static files URL + * @param taler_uri value for "Taler:" header to set, or NULL + * @param root JSON object to pass as the root context + * @param[out] reply where to write the response object + * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, + * #GNUNET_SYSERR on failure (to queue an error) + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_build (struct MHD_Connection *connection, + unsigned int *http_status, + const char *template, + const char *instance_id, + const char *taler_uri, + const json_t *root, + struct MHD_Response **reply); + + +/** + * Load a @a template and substitute using @a root, returning + * the result to the @a connection with the given + * @a http_status code. + * + * @param connection the connection we act upon + * @param http_status code to use on success + * @param template basename of the template to load + * @param instance_id instance ID, used to compute static files URL + * @param taler_uri value for "Taler:" header to set, or NULL + * @param root JSON object to pass as the root context + * @return #GNUNET_OK on success (reply queued), #GNUNET_NO if an error was queued, + * #GNUNET_SYSERR on failure (to queue an error) + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_reply (struct MHD_Connection *connection, + unsigned int http_status, + const char *template, + const char *instance_id, + const char *taler_uri, + const json_t *root); + + +/** + * Load a @a template and substitute an error message based on @a ec and @a + * detail, returning the result to the @a connection with the given @a + * http_status code. + * + * @param connection the connection we act upon + * @param template_basename basename of the template to load + * @param http_status code to use on success + * @param ec error code to return + * @param detail optional text to add to the template + * @return #MHD_YES on success, #MHD_NO to just close the connection + */ +MHD_RESULT +TALER_TEMPLATING_reply_error (struct MHD_Connection *connection, + const char *template_basename, + unsigned int http_status, + enum TALER_ErrorCode ec, + const char *detail); + +/** + * Preload templates. + * + * @param subsystem name of the subsystem, "merchant" or "exchange" + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_TEMPLATING_init (const char *subsystem); + + +/** + * Nicely shut down templating subsystem. + */ +void +TALER_TEMPLATING_done (void); + +#endif diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h index 1194cb4b4..f07d9be20 100644 --- a/src/include/taler_testing_lib.h +++ b/src/include/taler_testing_lib.h @@ -1,6 +1,6 @@ /* This file is part of TALER - (C) 2018 Taler Systems SA + (C) 2018-2023 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -20,6 +20,8 @@ /** * @file include/taler_testing_lib.h * @brief API for writing an interpreter to test Taler components + * This library is not thread-safe, all APIs must only be used from a single thread. + * This library calls abort() if it runs out of memory. Be aware of these limitations. * @author Christian Grothoff <christian@grothoff.org> * @author Marcello Stanisci */ @@ -27,11 +29,13 @@ #define TALER_TESTING_LIB_H #include "taler_util.h" -#include "taler_exchange_service.h" +#include <microhttpd.h> #include <gnunet/gnunet_json_lib.h> #include "taler_json_lib.h" +#include "taler_auditor_service.h" #include "taler_bank_service.h" -#include <microhttpd.h> +#include "taler_exchange_service.h" +#include "taler_fakebank_lib.h" /* ********************* Helper functions ********************* */ @@ -50,133 +54,156 @@ /** - * Allocate and return a piece of wire-details. Combines - * a @a payto -URL and adds some salt to create the JSON. + * Log an error message about us receiving an unexpected HTTP + * status code at the current command and fail the test. * - * @param payto payto://-URL to encapsulate - * @return JSON describing the account, including the - * payto://-URL of the account, must be manually decref'd + * @param is interpreter to fail + * @param status unexpected HTTP status code received + * @param expected expected HTTP status code */ -json_t * -TALER_TESTING_make_wire_details (const char *payto); +#define TALER_TESTING_unexpected_status(is,status,expected) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Unexpected response code %u (expected: %u) to command %s in %s:%u\n", \ + status, \ + expected, \ + TALER_TESTING_interpreter_get_current_label (is), \ + __FILE__, \ + __LINE__); \ + TALER_TESTING_interpreter_fail (is); \ + } while (0) + +/** + * Log an error message about us receiving an unexpected HTTP + * status code at the current command and fail the test and print the response + * body (expected as json). + * + * @param is interpreter to fail + * @param status unexpected HTTP status code received + * @param expected expected HTTP status code + * @param body received JSON-reply + */ +#define TALER_TESTING_unexpected_status_with_body(is,status,expected,body) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Unexpected response code %u (expected: %u) to " \ + "command %s in %s:%u\nwith body:\n>>%s<<\n", \ + status, \ + expected, \ + TALER_TESTING_interpreter_get_current_label (is), \ + __FILE__, \ + __LINE__, \ + json_dumps (body, JSON_INDENT (2))); \ + TALER_TESTING_interpreter_fail (is); \ + } while (0) /** - * Find denomination key matching the given amount. + * Log an error message about a command not having + * run to completion. * - * @param keys array of keys to search - * @param amount coin value to look for - * @return NULL if no matching key was found + * @param is interpreter + * @param label command label of the incomplete command */ -const struct TALER_EXCHANGE_DenomPublicKey * -TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys, - const struct TALER_Amount *amount); +#define TALER_TESTING_command_incomplete(is,label) \ + do { \ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, \ + "Command %s (%s:%u) did not complete (at %s)\n", \ + label, \ + __FILE__, \ + __LINE__, \ + TALER_TESTING_interpreter_get_current_label (is)); \ + } while (0) /** - * Configuration data for an exchange. + * Common credentials used in a test. */ -struct TALER_TESTING_ExchangeConfiguration +struct TALER_TESTING_Credentials { /** - * Exchange base URL as it appears in the configuration. Note - * that it might differ from the one where the exchange actually - * listens from. + * Bank authentication details for the exchange bank + * account. */ - char *exchange_url; + struct TALER_BANK_AuthenticationData ba; /** - * Auditor base URL as it appears in the configuration. Note - * that it might differ from the one where the auditor actually - * listens from. + * Bank authentication details for the admin bank + * account. */ - char *auditor_url; + struct TALER_BANK_AuthenticationData ba_admin; -}; + /** + * Configuration file data. + */ + struct GNUNET_CONFIGURATION_Handle *cfg; -/** - * Connection to the database: aggregates - * plugin and session handles. - */ -struct TALER_TESTING_DatabaseConnection -{ /** - * Database plugin. + * Base URL of the exchange. */ - struct TALER_EXCHANGEDB_Plugin *plugin; + char *exchange_url; /** - * Session with the database. + * Base URL of the auditor. */ - struct TALER_EXCHANGEDB_Session *session; -}; + char *auditor_url; -/** - * Prepare launching an exchange. Checks that the configured - * port is available, runs taler-exchange-keyup, - * taler-auditor-sign and taler-exchange-dbinit. Does not - * launch the exchange process itself. - * - * @param config_filename configuration file to use - * @param reset_db should we reset the database - * @param[out] ec will be set to the exchange configuration data - * @return #GNUNET_OK on success, #GNUNET_NO if test should be - * skipped, #GNUNET_SYSERR on test failure - */ -int -TALER_TESTING_prepare_exchange (const char *config_filename, - int reset_db, - struct TALER_TESTING_ExchangeConfiguration *ec); + /** + * RFC 8905 URI of the exchange. + */ + char *exchange_payto; + /** + * RFC 8905 URI of a user. + */ + char *user42_payto; -/** - * "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); + /** + * RFC 8905 URI of a user. + */ + char *user43_payto; +}; /** - * 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 the auditor to have started. Waits for at - * most 10s, after that returns 77 to indicate an error. + * Obtain bank credentials for a given @a cfg_file using + * @a exchange_account_section as the basis for the + * exchange account. * - * @param base_url what URL should we expect the auditor - * to be running at - * @return 0 on success + * @param cfg_file name of configuration to parse + * @param exchange_account_section configuration section name for the exchange account to use + * @param bs type of bank to use + * @param[out] ua where to write user account details + * and other credentials */ -int -TALER_TESTING_wait_auditor_ready (const char *base_url); +enum GNUNET_GenericReturnValue +TALER_TESTING_get_credentials ( + const char *cfg_file, + const char *exchange_account_section, + enum TALER_TESTING_BankSystem bs, + struct TALER_TESTING_Credentials *ua); /** - * Remove files from previous runs + * Allocate and return a piece of wire-details. Combines + * a @a payto -URL and adds some salt to create the JSON. * - * @param config_name configuration file to use+ + * @param payto payto://-URL to encapsulate + * @return JSON describing the account, including the + * payto://-URL of the account, must be manually decref'd */ -void -TALER_TESTING_cleanup_files (const char *config_name); +json_t * +TALER_TESTING_make_wire_details (const char *payto); /** @@ -186,75 +213,23 @@ TALER_TESTING_cleanup_files (const char *config_name); * @param cfg configuration * @return #GNUNET_OK on success */ -int +enum GNUNET_GenericReturnValue TALER_TESTING_cleanup_files_cfg (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg); /** - * Run `taler-exchange-keyup`. - * - * @param config_filename configuration file to use - * @param output_filename where to write the output for the auditor - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_run_keyup (const char *config_filename, - const char *output_filename); - - -/** - * Run `taler-auditor-dbinit -r` (reset auditor database). - * - * @param config_filename configuration file to use - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_auditor_db_reset (const char *config_filename); - - -/** - * Run `taler-exchange-dbinit -r` (reset exchange database). - * - * @param config_filename configuration file to use - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_exchange_db_reset (const char *config_filename); - - -/** - * Run `taler-auditor-sign`. - * - * @param config_filename configuration file to use - * @param exchange_master_pub master public key of the exchange - * @param auditor_base_url what is the base URL of the auditor - * @param signdata_in where is the information from taler-exchange-keyup - * @param signdata_out where to write the output for the exchange - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_run_auditor_sign (const char *config_filename, - const char *exchange_master_pub, - const char *auditor_base_url, - const char *signdata_in, - const char *signdata_out); - - -/** - * Run `taler-auditor-exchange`. + * Find denomination key matching the given amount. * - * @param config_filename configuration file to use - * @param exchange_master_pub master public key of the exchange - * @param exchange_base_url what is the base URL of the exchange - * @param do_remove #GNUNET_NO to add exchange, #GNUNET_YES to remove - * @return #GNUNET_OK on success + * @param keys array of keys to search + * @param amount coin value to look for + * @param age_restricted must the denomination be age restricted? + * @return NULL if no matching key was found */ -int -TALER_TESTING_run_auditor_exchange (const char *config_filename, - const char *exchange_master_pub, - const char *exchange_base_url, - int do_remove); +const struct TALER_EXCHANGE_DenomPublicKey * +TALER_TESTING_find_pk (const struct TALER_EXCHANGE_Keys *keys, + const struct TALER_Amount *amount, + bool age_restricted); /** @@ -263,176 +238,17 @@ TALER_TESTING_run_auditor_exchange (const char *config_filename, * @param url URL to extract port from, 80 is default * @return #GNUNET_OK if the port is free */ -int +enum GNUNET_GenericReturnValue TALER_TESTING_url_port_free (const char *url); -/** - * Configuration data for a bank. - */ -struct TALER_TESTING_BankConfiguration -{ - - /** - * Authentication data for the exchange user at the bank. - */ - struct TALER_BANK_AuthenticationData exchange_auth; - - /** - * Payto URL of the exchange's account ("2") - */ - char *exchange_payto; - - /** - * Payto URL of a user account ("42") - */ - char *user42_payto; - - /** - * Payto URL of another user's account ("43") - */ - char *user43_payto; - -}; - -/** - * Prepare launching a fakebank. Check that the configuration - * file has the right option, and that the port is available. - * If everything is OK, return the configuration data of the fakebank. - * - * @param config_filename configuration file to use - * @param config_section which account to use - * (must match x-taler-bank) - * @param[out] bc set to the bank's configuration data - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_prepare_fakebank (const char *config_filename, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); - - /* ******************* Generic interpreter logic ************ */ /** * Global state of the interpreter, used by a command * to access information about other commands. */ -struct TALER_TESTING_Interpreter -{ - - /** - * Commands the interpreter will run. - */ - struct TALER_TESTING_Command *commands; - - /** - * Interpreter task (if one is scheduled). - */ - struct GNUNET_SCHEDULER_Task *task; - - /** - * ID of task called whenever we get a SIGCHILD. - * Used for #TALER_TESTING_wait_for_sigchld(). - */ - struct GNUNET_SCHEDULER_Task *child_death_task; - - /** - * Main execution context for the main loop. - */ - struct GNUNET_CURL_Context *ctx; - - /** - * Our configuration. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Context for running the CURL event loop. - */ - struct GNUNET_CURL_RescheduleContext *rc; - - /** - * Handle to our fakebank, if #TALER_TESTING_run_with_fakebank() - * was used. Otherwise NULL. - */ - struct TALER_FAKEBANK_Handle *fakebank; - - /** - * Task run on timeout. - */ - struct GNUNET_SCHEDULER_Task *timeout_task; - - /** - * Function to call for cleanup at the end. Can be NULL. - */ - GNUNET_SCHEDULER_TaskCallback final_cleanup_cb; - - /** - * Closure for #final_cleanup_cb(). - */ - void *final_cleanup_cb_cls; - - /** - * Instruction pointer. Tells #interpreter_run() which - * instruction to run next. Need (signed) int because - * it gets -1 when rewinding the interpreter to the first - * CMD. - */ - int ip; - - /** - * Result of the testcases, #GNUNET_OK on success - */ - int result; - - /** - * Handle to the exchange. - */ - struct TALER_EXCHANGE_Handle *exchange; - - /** - * Handle to the auditor. NULL unless specifically initialized - * as part of #TALER_TESTING_auditor_setup(). - */ - struct TALER_AUDITOR_Handle *auditor; - - /** - * Handle to exchange process; some commands need it - * to send signals. E.g. to trigger the key state reload. - */ - struct GNUNET_OS_Process *exchanged; - - /** - * GNUNET_OK if key state should be reloaded. NOTE: this - * field can be removed because a new "send signal" command - * has been introduced. - */ - int reload_keys; - - /** - * 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; /** @@ -453,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, @@ -462,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); /** @@ -491,7 +312,7 @@ struct TALER_TESTING_Command * @param index index number of the object to extract. * @return #GNUNET_OK on success */ - int + enum GNUNET_GenericReturnValue (*traits)(void *cls, const void **ret, const char *trait, @@ -534,8 +355,43 @@ const struct TALER_TESTING_Command * TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is, const char *label); + /** - * 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. @@ -543,6 +399,7 @@ TALER_TESTING_interpreter_lookup_command (struct TALER_TESTING_Interpreter *is, struct GNUNET_CURL_Context * TALER_TESTING_interpreter_get_context (struct TALER_TESTING_Interpreter *is); + /** * Obtain label of the command being now run. * @@ -555,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. @@ -579,13 +427,20 @@ TALER_TESTING_interpreter_next (struct TALER_TESTING_Interpreter *is); void TALER_TESTING_interpreter_fail (struct TALER_TESTING_Interpreter *is); + /** - * Create command array terminator. + * Make the instruction pointer point to @a target_label + * only if @a counter is greater than zero. * - * @return a end-command. + * @param label command label + * @param target_label label of the new instruction pointer's destination after the jump; + * must be before the current instruction + * @param counter counts how many times the rewinding is to happen. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_end (); +TALER_TESTING_cmd_rewind_ip (const char *label, + const char *target_label, + unsigned int counter); /** @@ -628,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 @@ -656,233 +497,212 @@ typedef void /** - * Install signal handlers plus schedules the main wrapper - * around the "run" method. + * Run Taler testing loop. Starts the GNUnet SCHEDULER (event loop). * - * @param main_cb the "run" method which coontains all the - * commands. - * @param main_cb_cls a closure for "run", typically NULL. - * @param cfg configuration to use - * @param exchanged exchange process handle: will be put in the - * state as some commands - e.g. revoke - need to send - * signal to it, for example to let it know to reload the - * key state.. if NULL, the interpreter will run without - * trying to connect to the exchange first. - * @param exchange_connect GNUNET_YES if the test should connect - * to the exchange, GNUNET_NO otherwise - * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise. - * non-GNUNET_OK codes are #GNUNET_SYSERR most of the - * times. + * @param main_cb main function to run + * @param main_cb_cls closure for @a main_cb */ -int -TALER_TESTING_setup (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const struct GNUNET_CONFIGURATION_Handle *cfg, - struct GNUNET_OS_Process *exchanged, - int exchange_connect); +enum GNUNET_GenericReturnValue +TALER_TESTING_loop (TALER_TESTING_Main main_cb, + void *main_cb_cls); /** - * Install signal handlers plus schedules the main wrapper - * around the "run" method. + * Convenience function to run a test. * - * @param main_cb the "run" method which contains all the - * commands. - * @param main_cb_cls a closure for "run", typically NULL. - * @param config_filename configuration filename. - * @return #GNUNET_OK if all is okay, != #GNUNET_OK otherwise. - * non-GNUNET_OK codes are #GNUNET_SYSERR most of the - * times. + * @param argv command-line arguments given + * @param loglevel log level to use + * @param cfg_file configuration file to use + * @param exchange_account_section configuration section + * with exchange bank account to use + * @param bs bank system to use + * @param[in,out] cred global credentials to initialize + * @param main_cb main test function to run + * @param main_cb_cls closure for @a main_cb + * @return 0 on success, 77 on setup trouble, non-zero process status code otherwise */ int -TALER_TESTING_auditor_setup (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_filename); +TALER_TESTING_main (char *const *argv, + const char *loglevel, + const char *cfg_file, + const char *exchange_account_section, + enum TALER_TESTING_BankSystem bs, + struct TALER_TESTING_Credentials *cred, + TALER_TESTING_Main main_cb, + void *main_cb_cls); /** - * Closure for #TALER_TESTING_setup_with_exchange_cfg(). + * Callback over commands of an interpreter. + * + * @param cls closure + * @param cmd a command to process */ -struct TALER_TESTING_SetupContext -{ - /** - * Main function of the test to run. - */ - TALER_TESTING_Main main_cb; - - /** - * Closure for @e main_cb. - */ - void *main_cb_cls; - - /** - * Name of the configuration file. - */ - const char *config_filename; -}; +typedef void +(*TALER_TESTING_CommandIterator)( + void *cls, + const struct TALER_TESTING_Command *cmd); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the exchange using the given - * configuration file. + * Iterates over all of the top-level commands of an + * interpreter. * - * @param cls must be a `struct TALER_TESTING_SetupContext *` - * @param cfg configuration to use. - * @return #GNUNET_OK if no errors occurred. + * @param[in] is interpreter to iterate over + * @param asc true in execution order, false for reverse execution order + * @param cb function to call on each command + * @param cb_cls closure for cb */ -int -TALER_TESTING_setup_with_exchange_cfg ( - void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg); +void +TALER_TESTING_iterate (struct TALER_TESTING_Interpreter *is, + bool asc, + TALER_TESTING_CommandIterator cb, + void *cb_cls); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the exchange using the given - * configuration file. + * Look for substring in a programs' name. * - * @param main_cb main method. - * @param main_cb_cls main method closure. - * @param config_file configuration file name. Is is used - * by both this function and the exchange itself. In the - * first case it gives out the exchange port number and - * the exchange base URL so as to check whether the port - * is available and the exchange responds when requested - * at its base URL. - * @return #GNUNET_OK if no errors occurred. + * @param prog program's name to look into + * @param marker chunk to find in @a prog + * @return true if @a marker is in @a prog */ -int -TALER_TESTING_setup_with_exchange (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_file); +bool +TALER_TESTING_has_in_name (const char *prog, + const char *marker); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the auditor and exchange using - * the given configuration file. + * Wait for an HTTPD service to have started. Waits for at + * most 10s, after that returns 77 to indicate an error. * - * @param cls must be a `struct TALER_TESTING_SetupContext *` - * @param cfg configuration to use. - * @return #GNUNET_OK if no errors occurred. + * @param base_url what URL should we expect the exchange + * to be running at + * @return 0 on success */ int -TALER_TESTING_setup_with_auditor_and_exchange_cfg ( - void *cls, - const struct GNUNET_CONFIGURATION_Handle *cfg); +TALER_TESTING_wait_httpd_ready (const char *base_url); /** - * Initialize scheduler loop and curl context for the test case - * including starting and stopping the auditor and exchange using - * the given configuration file. + * Parse reference to a coin. * - * @param main_cb main method. - * @param main_cb_cls main method closure. - * @param config_file configuration file name. Is is used - * by both this function and the exchange itself. In the - * first case it gives out the exchange port number and - * the exchange base URL so as to check whether the port - * is available and the exchange responds when requested - * at its base URL. - * @return #GNUNET_OK if no errors occurred. + * @param coin_reference of format $LABEL['#' $INDEX]? + * @param[out] cref where we return a copy of $LABEL + * @param[out] idx where we set $INDEX + * @return #GNUNET_SYSERR if $INDEX is present but not numeric */ -int -TALER_TESTING_setup_with_auditor_and_exchange (TALER_TESTING_Main main_cb, - void *main_cb_cls, - const char *config_file); +enum GNUNET_GenericReturnValue +TALER_TESTING_parse_coin_reference ( + const char *coin_reference, + char **cref, + unsigned int *idx); + + +/* ************** Specific interpreter commands ************ */ /** - * Start the (Python) bank process. Assume the port - * is available and the database is clean. Use the "prepare - * bank" function to do such tasks. - * - * @param config_filename configuration filename. - * @param bank_url base URL of the bank, used by `wget' to check - * that the bank was started right. + * Create command array terminator. * - * @return the process, or NULL if the process could not - * be started. + * @return a end-command. */ -struct GNUNET_OS_Process * -TALER_TESTING_run_bank (const char *config_filename, - const char *bank_url); +struct TALER_TESTING_Command +TALER_TESTING_cmd_end (void); + /** - * Start the (nexus) bank process. Assume the port - * is available and the database is clean. Use the "prepare - * bank" function to do such tasks. This function is also - * responsible to create the exchange EBICS subscriber at - * the nexus. + * Set variable to command as side-effect of + * running a command. * - * @param 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. + * @param name name of the variable to set + * @param cmd command to set to variable when run + * @return modified command */ -struct GNUNET_OS_Process * -TALER_TESTING_run_nexus (const struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_var (const char *name, + struct TALER_TESTING_Command cmd); + /** - * Runs the Fakebank by guessing / extracting the portnumber - * from the base URL. + * Launch GNU Taler setup. * - * @param bank_url bank's base URL. - * @param currency currency the bank uses - * @return the fakebank process handle, or NULL if any - * error occurs. + * @param label command label. + * @param config_file configuration file to use + * @param ... NULL-terminated (const char *) arguments to pass to taler-benchmark-setup.sh + * @return the command. */ -struct TALER_FAKEBANK_Handle * -TALER_TESTING_run_fakebank (const char *bank_url, - const char *currency); +struct TALER_TESTING_Command +TALER_TESTING_cmd_system_start ( + const char *label, + const char *config_file, + ...); /** - * Prepare the bank execution. Check if the port is available - * and reset database. + * Connects to the exchange. * - * @param config_filename configuration file name. - * @param reset_db should we reset the bank's database - * @param[out] bc set to the bank's configuration data - * @return #GNUNET_OK on success + * @param label command label + * @param cfg configuration to use + * @param last_keys_ref reference to command with prior /keys response, NULL for none + * @param wait_for_keys block until we got /keys + * @param load_private_key obtain private key from file indicated in @a cfg + * @return the command. */ -int -TALER_TESTING_prepare_bank (const char *config_filename, - int reset_db, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_exchange ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *last_keys_ref, + bool wait_for_keys, + bool load_private_key); + /** - * Prepare the Nexus execution. Check if the port is available - * and delete old database. + * Connects to the auditor. * - * @param config_filename configuration file name. - * @param reset_db should we reset the bank's database - * @param config_section section of the configuration with the exchange's account - * @param[out] bc set to the bank's configuration data - * @return the base url, or NULL upon errors. Must be freed - * by the caller. + * @param label command label + * @param cfg configuration to use + * @param load_auditor_keys obtain auditor keys from file indicated in @a cfg + * @return the command. */ -int -TALER_TESTING_prepare_nexus (const char *config_filename, - int reset_db, - const char *config_section, - struct TALER_TESTING_BankConfiguration *bc); +struct TALER_TESTING_Command +TALER_TESTING_cmd_get_auditor ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + bool load_auditor_keys); + /** - * Look for substring in a programs' name. + * Runs the Fakebank in-process by guessing / extracting the portnumber + * from the base URL. * - * @param prog program's name to look into - * @param marker chunk to find in @a prog + * @param label command label + * @param cfg configuration to use + * @param exchange_account_section configuration section + * to use to determine bank account of the exchange + * @return the command. */ -int -TALER_TESTING_has_in_name (const char *prog, - const char *marker); +struct TALER_TESTING_Command +TALER_TESTING_cmd_run_fakebank ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *exchange_account_section); -/* ************** Specific interpreter commands ************ */ +/** + * Command to modify authorization header used in the CURL context. + * This will destroy the existing CURL context and create a fresh + * one. The command will fail (badly) if the existing CURL context + * still has active HTTP requests associated with it. + * + * @param label command label. + * @param auth_token auth token to use henceforth, can be NULL + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_authorization (const char *label, + const char *auth_token); /** @@ -926,10 +746,11 @@ TALER_TESTING_cmd_bank_debits (const char *label, /** * Create transfer command. * - * @param label command label. - * @param amount amount to transfer. + * @param label command label + * @param amount amount to transfer * @param auth authentication data to use - * @param payto_credit_account which account receives money. + * @param payto_debit_account which account to withdraw money from + * @param payto_credit_account which account receives money * @param wtid wire transfer identifier to use * @param exchange_base_url exchange URL to use * @return the command. @@ -945,6 +766,17 @@ TALER_TESTING_cmd_transfer (const char *label, /** + * Modify a transfer command to enable retries when the reserve is not yet + * full or we get other transient errors from the bank. + * + * @param cmd a fakebank transfer command + * @return the command with retries enabled + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_transfer_retry (struct TALER_TESTING_Command cmd); + + +/** * Make the "exec-auditor" CMD. * * @param label command label. @@ -972,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); /** @@ -1001,53 +829,10 @@ TALER_TESTING_cmd_deposit_confirmation (const char *label, */ struct TALER_TESTING_Command TALER_TESTING_cmd_deposit_confirmation_with_retry ( - struct TALER_TESTING_Command - cmd); - - -/** - * Create a "list exchanges" command. - * - * @param label command label. - * @param auditor auditor connection. - * @param expected_response_code expected HTTP response code. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_exchanges (const char *label, - struct TALER_AUDITOR_Handle *auditor, - unsigned int expected_response_code); + struct TALER_TESTING_Command cmd); /** - * 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); - - -/* ***** Commands ONLY for testing (/admin-API) **** */ - -/** * Create /admin/add-incoming command. * * @param label command label. @@ -1075,7 +860,8 @@ TALER_TESTING_cmd_admin_add_incoming ( * @param payto_debit_account which account sends money. * @param auth authentication data * @param ref reference to a command that can offer a reserve - * private key. + * private key or public key. + * @param http_status expected HTTP status * @return the command. */ struct TALER_TESTING_Command @@ -1084,35 +870,8 @@ TALER_TESTING_cmd_admin_add_incoming_with_ref ( const char *amount, const struct TALER_BANK_AuthenticationData *auth, const char *payto_debit_account, - const char *ref); - - -/** - * Create "fakebank transfer" CMD, letting the caller specifying - * the merchant instance. This version is useful when a tip - * reserve should be topped up, in fact the interpreter will need - * the "tipping instance" in order to get the instance public key - * and make a wire transfer subject out of it. - * - * @param label command label. - * @param amount amount to transfer. - * @param payto_debit_account which account sends money. - * @param auth authentication data - * @param instance the instance that runs the tipping. Under this - * instance, the configuration file will provide the private - * key of the tipping reserve. This data will then used to - * construct the wire transfer subject line. - * @param config_filename configuration file to use. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_admin_add_incoming_with_instance ( - const char *label, - const char *amount, - const struct TALER_BANK_AuthenticationData *auth, - const char *payto_debit_account, - const char *instance, - const char *config_filename); + const char *ref, + unsigned int http_status); /** @@ -1132,15 +891,65 @@ TALER_TESTING_cmd_admin_add_incoming_retry (struct TALER_TESTING_Command cmd); * * @param label command label. * @param config_filename configuration filename. - * * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_exec_wirewatch (const char *label, const char *config_filename); + +/** + * Make a "wirewatch" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @param account_section section to run wirewatch against + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_wirewatch2 (const char *label, + const char *config_filename, + const char *account_section); + + +/** + * Request URL via "wget". + * + * @param label command label. + * @param url URL to fetch + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_wget (const char *label, + const char *url); + + +/** + * Make a "expire" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_expire (const char *label, + const char *config_filename); + + +/** + * Make a "router" CMD. + * + * @param label command label. + * @param config_filename configuration filename. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_router (const char *label, + const char *config_filename); + + /** - * Make a "aggregator" CMD. + * Run a "taler-exchange-aggregator" CMD. * * @param label command label. * @param config_filename configuration file for the @@ -1153,6 +962,32 @@ TALER_TESTING_cmd_exec_aggregator (const char *label, /** + * Run a "taler-auditor-offline" CMD. + * + * @param label command label. + * @param config_filename configuration file for the + * aggregator to use. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_auditor_offline (const char *label, + const char *config_filename); + + +/** + * Make a "aggregator" CMD and do not disable KYC checks. + * + * @param label command label. + * @param config_filename configuration file for the + * aggregator to use. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_aggregator_with_kyc (const char *label, + const char *config_filename); + + +/** * Make a "closer" CMD. Note that it is right now not supported to run the * closer to close multiple reserves in combination with a subsequent reserve * status call, as we cannot generate the traits necessary for multiple closed @@ -1190,81 +1025,145 @@ TALER_TESTING_cmd_exec_transfer (const char *label, /** - * Make the "keyup" CMD. + * Create a withdraw command, letting the caller specify + * the desired amount as string. * * @param label command label. - * @param config_filename configuration filename. - * @return the command. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param amount how much we withdraw. + * @param age if > 0, age restriction applies + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @return the withdraw command to be executed by the interpreter. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_exec_keyup (const char *label, - const char *config_filename); +TALER_TESTING_cmd_withdraw_amount (const char *label, + const char *reserve_reference, + const char *amount, + uint8_t age, + unsigned int expected_response_code); /** - * Make the "keyup" CMD, with "--timestamp" option. + * 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 config_filename configuration filename. - * @param now Unix timestamp representing the fake "now". - * @return the command. + * @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_exec_keyup_with_now (const char *label, - const char *config_filename, - struct GNUNET_TIME_Absolute now); - +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, + ...); /** - * Make a "check keys" command. This type of command - * checks whether the number of denomination keys from - * @a exchange matches @a num_denom_keys. + * 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 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 num_denom_keys expected number of denomination keys. - * @param now timestamp to use when fetching keys - * @return the command. + * @param label command label. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param age if > 0, age restriction applies (same for all coins) + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @param amount how much we withdraw for the first coin + * @param ... NULL-terminated list of additional amounts to withdraw (one per coin) + * @return the withdraw command to be executed by the interpreter. + */ +#define TALER_TESTING_cmd_batch_withdraw(label, \ + reserve_reference, \ + age, \ + expected_response_code, \ + amount, \ + ...) \ + TALER_TESTING_cmd_batch_withdraw_with_conflict ( \ + (label), \ + (reserve_reference), \ + false, \ + (age), \ + (expected_response_code), \ + (amount), \ + __VA_ARGS__) + +/** + * Create an age-withdraw command, letting the caller specify + * the maximum agend and desired amounts as string. Takes a variable, + * non-empty list of the denomination amounts via VARARGS, similar to + * #TALER_TESTING_cmd_withdraw_amount(), just using a batch withdraw. + * + * @param label command label. + * @param reserve_reference command providing us with a reserve to withdraw from + * @param max_age maximum allowed age, same for each coin + * @param expected_response_code which HTTP response code + * we expect from the exchange. + * @param amount how much we withdraw for the first coin + * @param ... NULL-terminated list of additional amounts to withdraw (one per coin) + * @return the withdraw command to be executed by the interpreter. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys_with_now (const char *label, - unsigned int generation, - unsigned int num_denom_keys, - struct GNUNET_TIME_Absolute now); - +TALER_TESTING_cmd_age_withdraw (const char *label, + const char *reserve_reference, + uint8_t max_age, + unsigned int expected_response_code, + const char *amount, + ...); /** - * Make a "auditor sign" CMD. + * Create a "age-withdraw reveal" command. * - * @param label command label - * @param config_filename configuration filename + * @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_exec_auditor_sign (const char *label, - const char *config_filename); - +TALER_TESTING_cmd_age_withdraw_reveal ( + const char *label, + const char *age_withdraw_reference, + unsigned int expected_response_code); /** * Create a withdraw command, letting the caller specify - * the desired amount as string. + * the desired amount as string and also re-using an existing + * coin private key in the process (violating the specification, + * which will result in an error when spending the coin!). * * @param label command label. * @param reserve_reference command providing us with a reserve to withdraw from * @param amount how much we withdraw. + * @param age if > 0, age restriction applies. + * @param coin_ref reference to (withdraw/reveal) command of a coin + * from which we should 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. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_withdraw_amount (const char *label, - const char *reserve_reference, - const char *amount, - unsigned int expected_response_code); +TALER_TESTING_cmd_withdraw_amount_reuse_key ( + const char *label, + const char *reserve_reference, + const char *amount, + uint8_t age, + const char *coin_ref, + unsigned int expected_response_code); /** @@ -1299,37 +1198,155 @@ TALER_TESTING_cmd_withdraw_with_retry (struct TALER_TESTING_Command cmd); /** - * Create a "wire" command. + * Create a GET "reserves" command. * * @param label the command label. - * @param expected_method which wire-transfer method is expected - * to be offered by the exchange. - * @param expected_fee the fee the exchange should charge. - * @param expected_response_code the HTTP response the exchange - * should return. + * @param reserve_reference reference to the reserve to check. + * @param expected_balance expected balance for the reserve. + * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_wire (const char *label, - const char *expected_method, - const char *expected_fee, - unsigned int expected_response_code); +TALER_TESTING_cmd_status (const char *label, + const char *reserve_reference, + const char *expected_balance, + unsigned int expected_response_code); /** - * Create a GET "reserves" command. + * Create a GET "reserves" command with a @a timeout. * * @param label the command label. * @param reserve_reference reference to the reserve to check. * @param expected_balance expected balance for the reserve. + * @param timeout how long to long-poll for the reserve to exist. * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_status (const char *label, - const char *reserve_reference, - const char *expected_balance, - unsigned int expected_response_code); +TALER_TESTING_cmd_reserve_poll (const char *label, + const char *reserve_reference, + const char *expected_balance, + struct GNUNET_TIME_Relative timeout, + unsigned int expected_response_code); + + +/** + * Wait for #TALER_TESTING_cmd_reserve_poll() to finish. + * Fail if it did not conclude by the timeout. + * + * @param label our label + * @param timeout how long to give the long poll to finish + * @param poll_reference reference to a #TALER_TESTING_cmd_reserve_poll() command + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_poll_finish (const char *label, + struct GNUNET_TIME_Relative timeout, + const char *poll_reference); + + +/** + * Create a GET "/reserves/$RID/history" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to check. + * @param expected_balance expected balance for the reserve. + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_history (const char *label, + const char *reserve_reference, + const char *expected_balance, + unsigned int expected_response_code); + + +/** + * Create a GET "/coins/$COIN_PUB/history" command. + * + * @param label the command label. + * @param coin_reference reference to the coin to check. + * @param expected_balance expected balance for the coin. + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_coin_history (const char *label, + const char *coin_reference, + const char *expected_balance, + unsigned int expected_response_code); + + +/** + * Create a POST "/reserves/$RID/open" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to open. + * @param reserve_pay amount to pay from the reserve balance + * @param expiration_time how long into the future should the reserve remain open + * @param min_purses minimum number of purses to allow + * @param expected_response_code expected HTTP response code. + * @param ... NULL terminated list of pairs of coin references and amounts + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_open (const char *label, + const char *reserve_reference, + const char *reserve_pay, + struct GNUNET_TIME_Relative expiration_time, + uint32_t min_purses, + unsigned int expected_response_code, + ...); + + +/** + * Create a GET "/reserves/$RID/attest" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to get attestable attributes of. + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list of attributes expected + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_get_attestable (const char *label, + const char *reserve_reference, + unsigned int expected_response_code, + ...); + + +/** + * Create a POST "/reserves/$RID/attest" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to get attests for + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list of attributes that should be attested + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_attest (const char *label, + const char *reserve_reference, + unsigned int expected_response_code, + ...); + + +/** + * Create a POST "/reserves/$RID/close" command. + * + * @param label the command label. + * @param reserve_reference reference to the reserve to close. + * @param target_account where to wire funds remaining, can be NULL + * @param expected_response_code expected HTTP response code. + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_reserve_close (const char *label, + const char *reserve_reference, + const char *target_account, + unsigned int expected_response_code); + /** * Create a "deposit" command. @@ -1422,6 +1439,31 @@ TALER_TESTING_cmd_deposit_replay (const char *label, /** + * Create a "batch deposit" command. + * + * @param label command label. + * @param target_account_payto target account for the "deposit" + * request. + * @param contract_terms contract terms to be signed over by the + * coin. + * @param refund_deadline refund deadline, zero means 'no refunds'. + * @param expected_response_code expected HTTP response code. + * @param ... NULL-terminated list with an even number of + * strings that alternate referring to coins + * (possibly with index using label#index notation) + * and the amount of that coin to deposit + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_batch_deposit (const char *label, + const char *target_account_payto, + const char *contract_terms, + struct GNUNET_TIME_Relative refund_deadline, + unsigned int expected_response_code, + ...); + + +/** * Create a "refresh melt" command. * * @param label command label. @@ -1526,7 +1568,6 @@ TALER_TESTING_cmd_refresh_link_with_retry (struct TALER_TESTING_Command cmd); * @param bank_transfer_reference reference to a command that * can offer a WTID so as to check that against what WTID * the tracked operation has. Set as NULL if not needed. - * * @return the command. */ struct TALER_TESTING_Command @@ -1547,15 +1588,12 @@ TALER_TESTING_cmd_track_transaction (const char *label, * a wtid. If NULL is given, then a all zeroed WTID is * used that will at 99.9999% probability NOT match any * existing WTID known to the exchange. - * @param index index number of the WTID to track, in case there - * are multiple on offer. * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_track_transfer_empty (const char *label, const char *wtid_reference, - unsigned int index, unsigned int expected_response_code); @@ -1566,8 +1604,6 @@ TALER_TESTING_cmd_track_transfer_empty (const char *label, * @param label the command label. * @param wtid_reference reference to any command which can provide * a wtid. Will be the one tracked. - * @param index in case there are multiple WTID offered, this - * parameter selects a particular one. * @param expected_response_code expected HTTP response code. * @param expected_total_amount how much money we expect being moved * with this wire-transfer. @@ -1577,11 +1613,11 @@ TALER_TESTING_cmd_track_transfer_empty (const char *label, struct TALER_TESTING_Command TALER_TESTING_cmd_track_transfer (const char *label, const char *wtid_reference, - unsigned int index, unsigned int expected_response_code, const char *expected_total_amount, const char *expected_wire_fee); + /** * Make a "bank check" CMD. It checks whether a particular wire transfer from * the exchange (debit) has been made or not. @@ -1656,20 +1692,17 @@ TALER_TESTING_cmd_check_bank_empty (const char *label); * @param label command label. * @param expected_response_code expected HTTP status code. * @param refund_amount the amount to ask a refund for. - * @param refund_fee expected refund fee. * @param coin_reference reference to a command that can * provide a coin to be refunded. * @param refund_transaction_id transaction id to use * in the request. - * * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_refund_with_id (const char *label, unsigned int expected_response_code, const char *refund_amount, - const char *refund_fee, - const char *deposit_reference, + const char *coin_reference, uint64_t refund_transaction_id); @@ -1679,18 +1712,15 @@ TALER_TESTING_cmd_refund_with_id (const char *label, * @param label command label. * @param expected_response_code expected HTTP status code. * @param refund_amount the amount to ask a refund for. - * @param refund_fee expected refund fee. * @param coin_reference reference to a command that can * provide a coin to be refunded. - * * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_refund (const char *label, unsigned int expected_response_code, const char *refund_amount, - const char *refund_fee, - const char *deposit_reference); + const char *coin_reference); /** @@ -1702,7 +1732,6 @@ TALER_TESTING_cmd_refund (const char *label, * offers a coin and reserve private key. May specify * the index of the coin using "$LABEL#$INDEX" syntax. * Here, $INDEX must be a non-negative number. - * @param melt_reference NULL if coin was not refreshed, otherwise label of the melt operation * @param amount how much do we expect to recoup, NULL for nothing * @return the command. */ @@ -1710,11 +1739,31 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_recoup (const char *label, unsigned int expected_response_code, const char *coin_reference, - const char *melt_reference, const char *amount); /** + * Make a "recoup-refresh" command. + * + * @param label the command label + * @param expected_response_code expected HTTP status code + * @param coin_reference reference to any command which + * offers a coin and reserve private key. May specify + * the index of the coin using "$LABEL#$INDEX" syntax. + * Here, $INDEX must be a non-negative number. + * @param melt_reference label of the melt operation + * @param amount how much do we expect to recoup, NULL for nothing + * @return the command. + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_recoup_refresh (const char *label, + unsigned int expected_response_code, + const char *coin_reference, + const char *melt_reference, + const char *amount); + + +/** * Make a "revoke" command. * * @param label the command label. @@ -1770,71 +1819,6 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_wait_service (const char *label, const char *url); - -/** - * Make a "check keys" command. This type of command - * checks whether the number of denomination keys from - * @a exchange matches @a num_denom_keys. - * - * @param label command label - * @param generation how many /keys responses are expected to - * have been returned when this CMD will be run. - * @param num_denom_keys expected number of denomination keys. - * - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys (const char *label, - unsigned int generation, - unsigned int num_denom_keys); - - -/** - * Make a "check keys" command that forcedly does NOT cherry pick; - * just redownload the whole /keys. Then checks whether the number - * of denomination keys from @a exchange matches @a num_denom_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 num_denom_keys expected number of denomination keys. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys_pull_all_keys (const char *label, - unsigned int generation, - unsigned int num_denom_keys); - - -/** - * Make a "check keys" command. This type of command - * checks whether the number of denomination keys from - * @a exchange matches @a num_denom_keys. Additionally, - * 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 num_denom_keys expected number of denomination keys. - * @param last_denom_date date to be set in the "last_denom_issue" - * URL parameter of /keys. - * @return the command. - */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_check_keys_with_last_denom (const char *label, - unsigned int generation, - unsigned int num_denom_keys, - struct GNUNET_TIME_Absolute - last_denom_date); - - /** * Create a "batch" command. Such command takes a * end_CMD-terminated array of CMDs and executed them. @@ -1857,16 +1841,21 @@ TALER_TESTING_cmd_batch (const char *label, * * @return false if not, true if it is a batch command */ -int +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. @@ -1876,37 +1865,26 @@ TALER_TESTING_cmd_batch_next (struct TALER_TESTING_Interpreter *is); struct TALER_TESTING_Command * TALER_TESTING_cmd_batch_get_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. + * Set what command the batch should be at. * - * @param label command label - * @param state_reference label of a CMD offering - * a serialized key state. - * @return the CMD. + * @param cmd current batch command + * @param new_ip where to move the IP */ -struct TALER_TESTING_Command -TALER_TESTING_cmd_connect_with_state (const char *label, - const char *state_reference); +void +TALER_TESTING_cmd_batch_set_current (const struct TALER_TESTING_Command *cmd, + unsigned int new_ip); + /** * 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 * @param wire_deadline point in time where the aggregator should have * wired money to the merchant. * @param amount_with_fee amount to deposit (inclusive of deposit fee) @@ -1914,14 +1892,15 @@ TALER_TESTING_cmd_connect_with_state (const char *label, * @return the command. */ struct TALER_TESTING_Command -TALER_TESTING_cmd_insert_deposit (const char *label, - const struct - TALER_TESTING_DatabaseConnection *dbc, - const char *merchant_name, - const char *merchant_account, - struct GNUNET_TIME_Relative wire_deadline, - const char *amount_with_fee, - const char *deposit_fee); +TALER_TESTING_cmd_insert_deposit ( + const char *label, + const struct GNUNET_CONFIGURATION_Handle *db_cfg, + const char *merchant_name, + const char *merchant_account, + struct GNUNET_TIME_Timestamp exchange_timestamp, + struct GNUNET_TIME_Relative wire_deadline, + const char *amount_with_fee, + const char *deposit_fee); /** @@ -1940,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; @@ -1967,877 +1946,792 @@ struct TALER_TESTING_Command TALER_TESTING_cmd_stat (struct TALER_TESTING_Timer *timers); -/* *** Generic trait logic for implementing traits ********* */ - -/** - * A trait. - */ -struct TALER_TESTING_Trait -{ - /** - * Index number associated with the trait. This gives the - * possibility to have _multiple_ traits on offer under the - * same name. - */ - unsigned int index; - - /** - * Trait type, for example "reserve-pub" or "coin-priv". - */ - const char *trait_name; - - /** - * Pointer to the piece of data to offer. - */ - const void *ptr; -}; - - -/** - * "end" trait. Because traits are offered into arrays, - * this type of trait is used to mark the end of such arrays; - * useful when iterating over those. - */ -struct TALER_TESTING_Trait -TALER_TESTING_trait_end (void); - - /** - * Extract a trait. + * Add the auditor to the exchange's list of auditors. + * The information about the auditor is taken from the + * "[auditor]" section in the configuration file. * - * @param traits the array of all the traits. - * @param[out] ret where to store the result. - * @param trait type of the trait to extract. - * @param index index number of the trait to extract. - * @return #GNUNET_OK when the trait is found. - */ -int -TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, - const void **ret, - const char *trait, - unsigned int index); - - -/* ****** Specific traits supported by this component ******* */ - - -/** - * Obtain a bank transaction row value from @a cmd. - * - * @param cmd command to extract the number from. - * @param[out] row set to the number coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_bank_row (const struct TALER_TESTING_Command *cmd, - const uint64_t **row); - - -/** - * Offer bank transaction row trait. - * - * @param row number to offer. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_bank_row (const uint64_t *row); - - -/** - * Offer a reserve private key. - * - * @param index reserve priv's index number. - * @param reserve_priv reserve private key to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_reserve_priv ( - unsigned int index, - const struct TALER_ReservePrivateKeyP *reserve_priv); - - -/** - * Obtain a reserve private key from a @a cmd. - * - * @param cmd command to extract the reserve priv from. - * @param index reserve priv's index number. - * @param[out] reserve_priv set to the reserve priv. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_reserve_priv ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_ReservePrivateKeyP **reserve_priv); - - -/** - * Offer a reserve public key. - * - * @param index reserve pubs's index number. - * @param reserve_pub reserve public key to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_reserve_pub ( - unsigned int index, - const struct TALER_ReservePublicKeyP *reserve_pub); - - -/** - * Obtain a reserve public key from a @a cmd. - * - * @param cmd command to extract the reserve pub from. - * @param index reserve pub's index number. - * @param[out] reserve_pub set to the reserve pub. - * @return #GNUNET_OK on success. + * @param label command label. + * @param expected_http_status expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @return the command */ -int -TALER_TESTING_get_trait_reserve_pub ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_ReservePublicKeyP **reserve_pub); +struct TALER_TESTING_Command +TALER_TESTING_cmd_auditor_add (const char *label, + unsigned int expected_http_status, + bool bad_sig); /** - * Offer a reserve history entry. + * Remove the auditor from the exchange's list of auditors. + * The information about the auditor is taken from the + * "[auditor]" section in the configuration file. * - * @param index reserve pubs's index number. - * @param rh reserve history entry to offer. - * @return the trait. + * @param label command label. + * @param expected_http_status expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_reserve_history ( - unsigned int index, - const struct TALER_EXCHANGE_ReserveHistory *rh); +struct TALER_TESTING_Command +TALER_TESTING_cmd_auditor_del (const char *label, + unsigned int expected_http_status, + bool bad_sig); /** - * Obtain a reserve history entry from a @a cmd. + * Add affirmation that the auditor is auditing the given + * denomination. + * The information about the auditor is taken from the + * "[auditor]" section in the configuration file. * - * @param cmd command to extract the reserve history from. - * @param index reserve history's index number. - * @param[out] rhp set to the reserve history. - * @return #GNUNET_OK on success. + * @param label command label. + * @param expected_http_status expected HTTP status from exchange + * @param denom_ref reference to a command identifying a denomination key + * @param bad_sig should we use a bogus signature? + * @return the command */ -int -TALER_TESTING_get_trait_reserve_history ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_EXCHANGE_ReserveHistory **rhp); +struct TALER_TESTING_Command +TALER_TESTING_cmd_auditor_add_denom_sig (const char *label, + unsigned int expected_http_status, + const char *denom_ref, + bool bad_sig); /** - * Make a trait for a exchange signature. - * - * @param index index number to associate to the offered exchange pub. - * @param exchange_sig exchange signature to offer with this trait. + * Add statement about wire fees of the exchange. This is always + * done for a few hours around the current time (for the test). * - * @return the trait. + * @param label command label. + * @param wire_method wire method to set wire fees for + * @param wire_fee the wire fee to affirm + * @param closing_fee the closing fee to affirm + * @param expected_http_status expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_exchange_sig ( - unsigned int index, - const struct TALER_ExchangeSignatureP *exchange_sig); +struct TALER_TESTING_Command +TALER_TESTING_cmd_set_wire_fee (const char *label, + const char *wire_method, + const char *wire_fee, + const char *closing_fee, + unsigned int expected_http_status, + bool bad_sig); /** - * Obtain a exchange signature (online sig) from a @a cmd. + * Add the given payto-URI bank account to the list of bank + * accounts used by the exchange. * - * @param cmd command to extract trait from - * @param index index number of the exchange to obtain. - * @param[out] exchange_sig set to the offered exchange signature. - * @return #GNUNET_OK on success. + * @param label command label. + * @param payto_uri URI identifying the bank account + * @param expected_http_status expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @return the command */ -int -TALER_TESTING_get_trait_exchange_sig ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_ExchangeSignatureP **exchange_sig); +struct TALER_TESTING_Command +TALER_TESTING_cmd_wire_add (const char *label, + const char *payto_uri, + unsigned int expected_http_status, + bool bad_sig); /** - * Make a trait for a exchange public key. + * Remove the given payto-URI bank account from the list of bank + * accounts used by the exchange. * - * @param index index number to associate to the offered exchange pub. - * @param exchange_pub exchange pub to offer with this trait. - * - * @return the trait. + * @param label command label. + * @param payto_uri URI identifying the bank account + * @param expected_http_status expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_exchange_pub ( - unsigned int index, - const struct TALER_ExchangePublicKeyP *exchange_pub); - +struct TALER_TESTING_Command +TALER_TESTING_cmd_wire_del (const char *label, + const char *payto_uri, + unsigned int expected_http_status, + bool bad_sig); /** - * Obtain a exchange public key from a @a cmd. + * Sign all extensions that the exchange has to offer, f. e. the extension for + * age restriction. This has to be run before any withdrawal of age restricted + * can be performed. * - * @param cmd command to extract trait from - * @param index index number of the exchange to obtain. - * @param[out] exchange_pub set to the offered exchange pub. - * @return #GNUNET_OK on success. + * @param label command label. + * @param config_filename configuration filename. + * @return the command */ -int -TALER_TESTING_get_trait_exchange_pub ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_ExchangePublicKeyP **exchange_pub); +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_extensions (const char *label, + const char *config_filename); /** - * Obtain location where a command stores a pointer to a process. + * Sign all exchange denomination and online signing keys + * with the "offline" key and provide those signatures to + * the exchange. (Downloads the keys, makes the signature + * and uploads the result, all in one.) * - * @param cmd command to extract trait from. - * @param index which process to pick if @a cmd - * has multiple on offer. - * @param[out] processp set to the address of the pointer to the - * process. - * @return #GNUNET_OK on success. + * @param label command label. + * @param config_filename configuration filename. + * @return the command */ -int -TALER_TESTING_get_trait_process (const struct TALER_TESTING_Command *cmd, - unsigned int index, - struct GNUNET_OS_Process ***processp); +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_keys (const char *label, + const char *config_filename); /** - * Offer location where a command stores a pointer to a process. + * Sign a wire fee structure. * - * @param index offered location index number, in case there are - * multiple on offer. - * @param processp process location to offer. - * @return the trait. + * @param label command label. + * @param config_filename configuration filename. + * @param wire_fee the wire fee to affirm (for the current year) + * @param closing_fee the closing fee to affirm (for the current year) + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_process (unsigned int index, - struct GNUNET_OS_Process **processp); - +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_fees (const char *label, + const char *config_filename, + const char *wire_fee, + const char *closing_fee); -/** - * Offer coin private key. - * - * @param index index number to associate with offered coin priv. - * @param coin_priv coin private key to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_coin_priv ( - unsigned int index, - const struct TALER_CoinSpendPrivateKeyP *coin_priv); /** - * Obtain a coin private key from a @a cmd. + * Sign global fee structure. * - * @param cmd command to extract trait from. - * @param index index of the coin priv to obtain. - * @param[out] coin_priv set to the private key of the coin. - * @return #GNUNET_OK on success. + * @param label command label. + * @param config_filename configuration filename. + * @param history_fee the history fee to charge (for the current year) + * @param account_fee the account fee to charge (for the current year) + * @param purse_fee the purse fee to charge (for the current year) + * @param purse_timeout when do purses time out + * @param history_expiration when does an account history expire + * @param num_purses number of (free) active purses per account + * @return the command */ -int -TALER_TESTING_get_trait_coin_priv ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_CoinSpendPrivateKeyP **coin_priv); +struct TALER_TESTING_Command +TALER_TESTING_cmd_exec_offline_sign_global_fees ( + const char *label, + const char *config_filename, + const char *history_fee, + const char *account_fee, + const char *purse_fee, + struct GNUNET_TIME_Relative purse_timeout, + struct GNUNET_TIME_Relative history_expiration, + unsigned int num_purses); /** - * Offer blinding key. + * Revoke an exchange denomination key. * - * @param index index number to associate to the offered key. - * @param blinding_key blinding key to offer. - * @return the trait. + * @param label command label. + * @param expected_response_code expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @param denom_ref reference to a command that identifies + * a denomination key (i.e. because it was used to + * withdraw a coin). + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_blinding_key ( - unsigned int index, - const struct TALER_DenominationBlindingKeyP *blinding_key); +struct TALER_TESTING_Command +TALER_TESTING_cmd_revoke_denom_key ( + const char *label, + unsigned int expected_response_code, + bool bad_sig, + const char *denom_ref); /** - * Obtain a blinding key from a @a cmd. + * Revoke an exchange online signing key. * - * @param cmd command to extract trait from - * @param index which coin to pick if @a cmd has multiple on offer. - * @param[out] blinding_key set to the offered blinding key. - * @return #GNUNET_OK on success. + * @param label command label. + * @param expected_response_code expected HTTP status from exchange + * @param bad_sig should we use a bogus signature? + * @param signkey_ref reference to a command that identifies + * a signing key (i.e. because it was used to + * sign a deposit confirmation). + * @return the command */ -int -TALER_TESTING_get_trait_blinding_key ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_DenominationBlindingKeyP **blinding_key); +struct TALER_TESTING_Command +TALER_TESTING_cmd_revoke_sign_key ( + const char *label, + unsigned int expected_response_code, + bool bad_sig, + const char *signkey_ref); /** - * Make a trait for a denomination public key. + * Create a request for a wallet's KYC UUID. * - * @param index index number to associate to the offered denom pub. - * @param denom_pub denom pub to offer with this trait. - * @return the trait. + * @param label command label. + * @param reserve_reference command with reserve private key to use (or NULL to create a fresh reserve key). + * @param threshold_balance balance amount to pass to the exchange + * @param expected_response_code expected HTTP status + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_denom_pub ( - unsigned int index, - const struct TALER_EXCHANGE_DenomPublicKey *dpk); +struct TALER_TESTING_Command +TALER_TESTING_cmd_wallet_kyc_get (const char *label, + const char *reserve_reference, + const char *threshold_balance, + unsigned int expected_response_code); /** - * Obtain a denomination public key from a @a cmd. + * Create a request for an account's KYC status. * - * @param cmd command to extract trait from - * @param index index number of the denom to obtain. - * @param[out] denom_pub set to the offered denom pub. - * @return #GNUNET_OK on success. + * @param label command label. + * @param payment_target_reference command with a payment target to query + * @param expected_response_code expected HTTP status + * @return the command */ -int -TALER_TESTING_get_trait_denom_pub ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_EXCHANGE_DenomPublicKey **dpk); +struct TALER_TESTING_Command +TALER_TESTING_cmd_check_kyc_get (const char *label, + const char *payment_target_reference, + unsigned int expected_response_code); /** - * Obtain a denomination signature from a @a cmd. + * Create a KYC proof request. Only useful in conjunction with the OAuth2.0 + * logic, as it generates an OAuth2.0-specific request. * - * @param cmd command to extract the denom sig from. - * @param index index number associated with the denom sig. - * @param[out] denom_sig set to the offered signature. - * @return #GNUNET_OK on success. + * @param label command label. + * @param payment_target_reference command with a payment target to query + * @param logic_section name of the KYC provider section + * in the exchange configuration for this proof + * @param code OAuth 2.0 code to use + * @param expected_response_code expected HTTP status + * @return the command */ -int -TALER_TESTING_get_trait_denom_sig ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_DenominationSignature **dpk); +struct TALER_TESTING_Command +TALER_TESTING_cmd_proof_kyc_oauth2 ( + const char *label, + const char *payment_target_reference, + const char *logic_section, + const char *code, + unsigned int expected_response_code); /** - * Offer denom sig. + * Starts a fake OAuth 2.0 service on @a port for testing + * KYC processes which also provides a @a birthdate in a response * - * @param index index number to associate to the signature on - * offer. - * @param denom_sig the denom sig on offer. - * @return the trait. + * @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_Trait -TALER_TESTING_make_trait_denom_sig ( - unsigned int index, - const struct TALER_DenominationSignature *sig); - +struct TALER_TESTING_Command +TALER_TESTING_cmd_oauth_with_birthdate (const char *label, + const char *birthdate, + uint16_t port); /** - * Offer number trait, 64-bit version. + * Starts a fake OAuth 2.0 service on @a port for testing + * KYC processes. * - * @param index the number's index number. - * @param n number to offer. + * @param label command label + * @param port the TCP port to listen on */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_uint64 (unsigned int index, - const uint64_t *n); +#define TALER_TESTING_cmd_oauth(label, port) \ + TALER_TESTING_cmd_oauth_with_birthdate ((label), NULL, (port)) -/** - * Obtain a "number" value from @a cmd, 64-bit version. - * - * @param cmd command to extract the number from. - * @param index the number's index number. - * @param[out] n set to the number coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_uint64 (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const uint64_t **n); +/* ****************** P2P payment commands ****************** */ /** - * Offer a number. + * Creates a purse with deposits. * - * @param index the number's index number. - * @param n the number to offer. - * @return #GNUNET_OK on success. + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param contract_terms contract, JSON string + * @param upload_contract should we upload the contract + * @param purse_expiration how long until the purse expires + * @param ... NULL-terminated list of references to coins to be deposited + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_uint (unsigned int index, - const unsigned int *i); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_create_with_deposit ( + const char *label, + unsigned int expected_http_status, + const char *contract_terms, + bool upload_contract, + struct GNUNET_TIME_Relative purse_expiration, + ...); /** - * Obtain a number from @a cmd. + * Deletes a purse. * - * @param cmd command to extract the number from. - * @param index the number's index number. - * @param[out] n set to the number coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_uint (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const unsigned int **n); - - -/** - * Opaque handle to fresh coins generated during refresh. - * Details are internal to the refresh logic. + * @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_FreshCoinData; +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_delete ( + const char *label, + unsigned int expected_http_status, + const char *purse_cmd); /** - * Offer a _array_ of fresh coins. + * Retrieve contract (also checks that the contract matches + * the upload command). * - * @param index which array of fresh coins to offer, - * if there are multiple on offer. Typically passed as - * zero. - * @param fresh_coins the array of fresh coins to offer - * @return the trait, + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param for_merge true if for merge, false if for deposit + * @param contract_ref reference to a command providing us with the contract private key + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_fresh_coins ( - unsigned int index, - const struct TALER_TESTING_FreshCoinData *fresh_coins); +struct TALER_TESTING_Command +TALER_TESTING_cmd_contract_get ( + const char *label, + unsigned int expected_http_status, + bool for_merge, + const char *contract_ref); /** - * Get a array of fresh coins. + * Retrieve purse state by merge private key. * - * @param cmd command to extract the fresh coin from. - * @param index which array to pick if @a cmd has multiple - * on offer. - * @param[out] fresh_coins will point to the offered array. - * @return #GNUNET_OK on success. + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param merge_ref reference to a command providing us with the merge private key + * @param reserve_ref reference to a command providing us with a reserve private key; if NULL, we create a fresh reserve + * @return the command */ -int -TALER_TESTING_get_trait_fresh_coins ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_TESTING_FreshCoinData **fresh_coins); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_merge ( + const char *label, + unsigned int expected_http_status, + const char *merge_ref, + const char *reserve_ref); /** - * Obtain contract terms from @a cmd. + * Retrieve purse state. * - * @param cmd command to extract the contract terms from. - * @param index contract terms index number. - * @param[out] contract_terms where to write the contract - * terms. - * @return #GNUNET_OK on success. + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param purse_ref reference to a command providing us with the purse private key + * @param expected_balance how much should be in the purse + * @param wait_for_merge true to wait for a merge event, otherwise wait for a deposit event + * @param timeout how long to wait + * @return the command */ -int -TALER_TESTING_get_trait_contract_terms (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const json_t **contract_terms); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_poll ( + const char *label, + unsigned int expected_http_status, + const char *purse_ref, + const char *expected_balance, + bool wait_for_merge, + struct GNUNET_TIME_Relative timeout); /** - * Offer contract terms. + * Wait for the poll command to complete. * - * @param index contract terms index number. - * @param contract_terms contract terms to offer. - * @return the trait. + * @param label command label + * @param timeout how long to wait at most + * @param poll_reference which poll command to wait for + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_contract_terms (unsigned int index, - const json_t *contract_terms); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_poll_finish (const char *label, + struct GNUNET_TIME_Relative timeout, + const char *poll_reference); /** - * Obtain wire details from @a cmd. + * Creates a purse with reserve. * - * @param cmd command to extract the wire details from. - * @param index index number associate with the wire details - * on offer; usually zero, as one command sticks to - * one bank account. - * @param[out] wire_details where to write the wire details. - * @return #GNUNET_OK on success. + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param contract_terms contract, JSON string + * @param upload_contract should we upload the contract + * @param pay_purse_fee should we pay a fee to create the purse + * @param expiration when should the purse expire + * @param reserve_ref reference to reserve key, or NULL to create a new reserve + * @return the command */ -int -TALER_TESTING_get_trait_wire_details (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const json_t **wire_details); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_create_with_reserve ( + const char *label, + unsigned int expected_http_status, + const char *contract_terms, + bool upload_contract, + bool pay_purse_fee, + struct GNUNET_TIME_Relative expiration, + const char *reserve_ref); /** - * Offer wire details in a trait. + * Deposit coins into a purse. * - * @param index index number associate with the wire details - * on offer; usually zero, as one command sticks to - * one bank account. - * @param wire_details wire details to offer. - * - * @return the trait. + * @param label command label + * @param expected_http_status what HTTP status do we expect to get returned from the exchange + * @param min_age age restriction of the purse + * @param purse_ref reference to the purse + * @param ... NULL-terminated list of references to coins to be deposited + * @return the command */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_wire_details (unsigned int index, - const json_t *wire_details); +struct TALER_TESTING_Command +TALER_TESTING_cmd_purse_deposit_coins ( + const char *label, + unsigned int expected_http_status, + uint8_t min_age, + const char *purse_ref, + ...); /** - * Obtain serialized exchange keys from @a cmd. + * Setup AML officer. * - * @param cmd command to extract the keys from. - * @param index index number associate with the keys on offer. - * @param[out] keys where to write the serialized keys. - * @return #GNUNET_OK on success. + * @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 */ -int -TALER_TESTING_get_trait_exchange_keys (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const json_t **keys); +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); /** - * Offer serialized keys in a trait. + * Make AML decision. * - * @param index index number associate with the serial keys - * on offer. - * @param keys serialized keys to offer. - * @return the trait. + * @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_Trait -TALER_TESTING_make_trait_exchange_keys (unsigned int index, - const json_t *keys); +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); /** - * Obtain a private key from a "merchant". Used e.g. to obtain - * a merchant's priv to sign a /track request. + * Fetch AML decision. * - * @param cmd command that is offering the key. - * @param index (typically zero) which key to return if there - * are multiple on offer. - * @param[out] priv set to the key coming from @a cmd. - * @return #GNUNET_OK on success. + * @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 */ -int -TALER_TESTING_get_trait_merchant_priv ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_MerchantPrivateKeyP **priv); +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); /** - * Offer private key of a merchant, typically done when CMD_1 needs it to - * sign a request. + * Fetch AML decisions. * - * @param index (typically zero) which key to return if there are - * multiple on offer. - * @param priv which object should be offered. - * @return the trait. + * @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_Trait -TALER_TESTING_make_trait_merchant_priv ( - unsigned int index, - const struct TALER_MerchantPrivateKeyP *priv); - +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); -/** - * Obtain a public key from a "merchant". Used e.g. to obtain - * a merchant's public key to use backend's API. - * - * @param cmd command offering the key. - * @param index (typically zero) which key to return if there - * are multiple on offer. - * @param[out] pub set to the key coming from @a cmd. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_merchant_pub ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_MerchantPublicKeyP **pub); +/* ****************** convenience functions ************** */ /** - * Offer public key. + * Get exchange URL from interpreter. Convenience function. * - * @param index (typically zero) which key to return if there - * are multiple on offer. NOTE: if one key is offered, it - * is mandatory to set this as zero. - * @param pub which object should be returned. - * @return the trait. + * @param is interpreter state. + * @return the exchange URL, or NULL on error */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_merchant_pub ( - unsigned int index, - const struct TALER_MerchantPublicKeyP *pub); +const char * +TALER_TESTING_get_exchange_url ( + struct TALER_TESTING_Interpreter *is); /** - * Obtain a string from @a cmd. + * Get exchange keys from interpreter. Convenience function. * - * @param cmd command to extract the subject from. - * @param index index number associated with the transfer - * subject to offer. - * @param[out] s where to write the offered - * string. - * @return #GNUNET_OK on success. + * @param is interpreter state. + * @return the exchange keys, or NULL on error */ -int -TALER_TESTING_get_trait_string ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const char **s); +struct TALER_EXCHANGE_Keys * +TALER_TESTING_get_keys ( + struct TALER_TESTING_Interpreter *is); -/** - * Offer string subject. - * - * @param index index number associated with the transfer - * subject being offered. - * @param s string to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_string (unsigned int index, - const char *s); +/* *** Generic trait logic for implementing traits ********* */ /** - * Obtain a WTID value from @a cmd. - * - * @param cmd command to extract trait from - * @param index which WTID to pick if @a cmd has multiple on - * offer - * @param[out] wtid set to the wanted WTID. - * @return #GNUNET_OK on success + * Opaque handle to fresh coins generated during refresh. + * Details are internal to the refresh logic. */ -int -TALER_TESTING_get_trait_wtid ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_WireTransferIdentifierRawP **wtid); +struct TALER_TESTING_FreshCoinData; /** - * Offer a WTID. - * - * @param index associate the WTID with this index. - * @param wtid pointer to the WTID to offer. - * @return the trait. + * A trait. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_wtid ( - unsigned int index, - const struct TALER_WireTransferIdentifierRawP *wtid); - - -/** - * Different types of URLs that appear in traits. - */ -enum TALER_TESTING_URL_Type { /** - * Category of last resort. Should not be used. - */ - TALER_TESTING_UT_UNDEFINED = 0, - - /** - * HTTP base URL of an exchange (API), as for example - * given in wire transfers subjects made by the aggregator. + * Index number associated with the trait. This gives the + * possibility to have _multiple_ traits on offer under the + * same name. */ - TALER_TESTING_UT_EXCHANGE_BASE_URL = 1, + unsigned int index; /** - * HTTP URL of the exchange's bank account at the bank. + * Trait type, for example "reserve-pub" or "coin-priv". */ - TALER_TESTING_UT_EXCHANGE_BANK_ACCOUNT_URL = 2 -}; - - -/** - * Offer HTTP url in a trait. - * - * @param index which url is to be picked, - * in case multiple are offered. - * @param url the url to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_url (enum TALER_TESTING_URL_Type index, - const char *url); - - -/** - * Obtain a HTTP url from @a cmd. - * - * @param cmd command to extract the url from. - * @param index which url is to be picked, in case - * multiple are offered. - * @param[out] url where to write the url. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_url (const struct TALER_TESTING_Command *cmd, - enum TALER_TESTING_URL_Type index, - const char **url); - + const char *trait_name; -/** - * Used as the "index" in payto traits, to identify what kind of - * payto URL we are returning. - */ -enum TALER_TESTING_PaytoType -{ - /** - * We don't know / not credit or debit. - */ - TALER_TESTING_PT_NEUTRAL, /** - * Credit side of a transaction. - */ - TALER_TESTING_PT_CREDIT, - /** - * Debit side of a transaction. + * Pointer to the piece of data to offer. */ - TALER_TESTING_PT_DEBIT + const void *ptr; }; /** - * Offer a payto uri in a trait. - * - * @param pt which url is to be picked, - * in case multiple are offered. - * @param payto_uri the uri to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_payto (enum TALER_TESTING_PaytoType pt, - const char *payto_uri); - - -/** - * Obtain a PAYTO url from @a cmd. - * - * @param cmd command to extract the url from. - * @param pt which url is to be picked, in case - * multiple are offered. - * @param[out] url where to write the url. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_payto (const struct TALER_TESTING_Command *cmd, - enum TALER_TESTING_PaytoType pt, - const char **url); - - -/** - * Obtain a order id from @a cmd. - * - * @param cmd command to extract the order id from. - * @param index which order id is to be picked, in case - * multiple are offered. - * @param[out] order_id where to write the order id. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_order_id (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const char **order_id); - - -/** - * Offer order id in a trait. - * - * @param index which order id is to be offered, - * in case multiple are offered. - * @param order_id the order id to offer. - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_order_id (unsigned int index, - const char *order_id); - - -/** - * Obtain an amount from a @a cmd. - * - * @param cmd command to extract the amount from. - * @param index which amount to pick if @a cmd has multiple - * on offer - * @param[out] amount set to the amount. - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_get_trait_amount_obj (const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct TALER_Amount **amount); - - -/** - * Offer amount. - * - * @param index which amount to offer, in case there are - * multiple available. - * @param amount the amount to offer. - * - * @return the trait. + * "end" trait. Because traits are offered into arrays, + * this type of trait is used to mark the end of such arrays; + * useful when iterating over those. */ struct TALER_TESTING_Trait -TALER_TESTING_make_trait_amount_obj (unsigned int index, - const struct TALER_Amount *amount); +TALER_TESTING_trait_end (void); /** - * Offer a command in a trait. - * - * @param index always zero. Commands offering this - * kind of traits do not need this index. For - * example, a "meta" CMD returns always the - * CMD currently being executed. - * @param cmd wire details to offer. + * Extract a trait. * - * @return the trait. + * @param traits the array of all the traits. + * @param[out] ret where to store the result. + * @param trait type of the trait to extract. + * @param index index number of the trait to extract. + * @return #GNUNET_OK when the trait is found. */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_cmd (unsigned int index, - const struct TALER_TESTING_Command *cmd); +enum GNUNET_GenericReturnValue +TALER_TESTING_get_trait (const struct TALER_TESTING_Trait *traits, + const void **ret, + const char *trait, + unsigned int index); -/** - * Obtain a command from @a cmd. - * - * @param cmd command to extract the command from. - * @param index always zero. Commands offering this - * kind of traits do not need this index. For - * example, a "meta" CMD returns always the - * CMD currently being executed. - * @param[out] _cmd where to write the wire details. - * @return #GNUNET_OK on success. - */ -int -TALER_TESTING_get_trait_cmd (const struct TALER_TESTING_Command *cmd, - unsigned int index, - struct TALER_TESTING_Command **_cmd); +/* ****** Specific traits supported by this component ******* */ /** - * Obtain a absolute time from @a cmd. - * - * @param cmd command to extract trait from - * @param index which time stamp to pick if - * @a cmd has multiple on offer. - * @param[out] time set to the wanted WTID. - * @return #GNUNET_OK on success - */ -int -TALER_TESTING_get_trait_absolute_time ( - const struct TALER_TESTING_Command *cmd, - unsigned int index, - const struct GNUNET_TIME_Absolute **time); + * Create headers for a trait with name @a name for + * statically allocated data of type @a type. + */ +#define TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + TALER_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + type **ret); \ + struct TALER_TESTING_Trait \ + TALER_TESTING_make_trait_ ## name ( \ + type * value); + + +/** + * Create C implementation for a trait with name @a name for statically + * allocated data of type @a type. + */ +#define TALER_TESTING_MAKE_IMPL_SIMPLE_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + TALER_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + type **ret) \ + { \ + if (NULL == cmd->traits) return GNUNET_SYSERR; \ + return cmd->traits (cmd->cls, \ + (const void **) ret, \ + TALER_S (name), \ + 0); \ + } \ + struct TALER_TESTING_Trait \ + TALER_TESTING_make_trait_ ## name ( \ + type * value) \ + { \ + struct TALER_TESTING_Trait ret = { \ + .trait_name = TALER_S (name), \ + .ptr = (const void *) value \ + }; \ + return ret; \ + } + + +/** + * Create headers for a trait with name @a name for + * statically allocated data of type @a type. + */ +#define TALER_TESTING_MAKE_DECL_INDEXED_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + TALER_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + unsigned int index, \ + type **ret); \ + struct TALER_TESTING_Trait \ + TALER_TESTING_make_trait_ ## name ( \ + unsigned int index, \ + type * value); + + +/** + * Create C implementation for a trait with name @a name for statically + * allocated data of type @a type. + */ +#define TALER_TESTING_MAKE_IMPL_INDEXED_TRAIT(name,type) \ + enum GNUNET_GenericReturnValue \ + TALER_TESTING_get_trait_ ## name ( \ + const struct TALER_TESTING_Command *cmd, \ + unsigned int index, \ + type **ret) \ + { \ + if (NULL == cmd->traits) return GNUNET_SYSERR; \ + return cmd->traits (cmd->cls, \ + (const void **) ret, \ + TALER_S (name), \ + index); \ + } \ + struct TALER_TESTING_Trait \ + TALER_TESTING_make_trait_ ## name ( \ + unsigned int index, \ + type * value) \ + { \ + struct TALER_TESTING_Trait ret = { \ + .index = index, \ + .trait_name = TALER_S (name), \ + .ptr = (const void *) value \ + }; \ + return ret; \ + } + + +/** + * Call #op on all simple 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) \ + op (merge_pub, const struct TALER_PurseMergePublicKeyP) \ + op (contract_priv, const struct TALER_ContractDiffiePrivateP) \ + op (reserve_priv, const struct TALER_ReservePrivateKeyP) \ + op (reserve_sig, const struct TALER_ReserveSignatureP) \ + op (h_payto, const struct TALER_PaytoHashP) \ + op (planchet_secret, const struct TALER_PlanchetMasterSecretP) \ + op (refresh_secret, const struct TALER_RefreshMasterSecretP) \ + op (reserve_pub, const struct TALER_ReservePublicKeyP) \ + op (merchant_priv, const struct TALER_MerchantPrivateKeyP) \ + op (merchant_pub, const struct TALER_MerchantPublicKeyP) \ + op (merchant_sig, const struct TALER_MerchantSignatureP) \ + op (wtid, const struct TALER_WireTransferIdentifierRawP) \ + op (bank_auth_data, const struct TALER_BANK_AuthenticationData) \ + op (contract_terms, const json_t) \ + op (wire_details, const json_t) \ + op (exchange_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 (array_length, const unsigned int) \ + 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 (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) \ + op (reserve_history, const struct TALER_EXCHANGE_ReserveHistoryEntry) \ + op (coin_history, const struct TALER_EXCHANGE_CoinHistoryEntry) \ + op (planchet_secrets, const struct TALER_PlanchetMasterSecretP) \ + op (exchange_wd_value, const struct TALER_ExchangeWithdrawValues) \ + op (coin_priv, const struct TALER_CoinSpendPrivateKeyP) \ + op (coin_pub, const struct TALER_CoinSpendPublicKeyP) \ + op (coin_sig, const struct TALER_CoinSpendSignatureP) \ + op (absolute_time, const struct GNUNET_TIME_Absolute) \ + op (timestamp, const struct GNUNET_TIME_Timestamp) \ + op (wire_deadline, const struct GNUNET_TIME_Timestamp) \ + op (refund_deadline, const struct GNUNET_TIME_Timestamp) \ + op (exchange_pub, const struct TALER_ExchangePublicKeyP) \ + op (exchange_sig, const struct TALER_ExchangeSignatureP) \ + op (blinding_key, const union GNUNET_CRYPTO_BlindingSecretP) \ + op (h_blinded_coin, const struct TALER_BlindedCoinHashP) + +TALER_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) + +TALER_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT) -/** - * Offer a absolute time. - * - * @param index associate the object with this index - * @param time which object should be returned - * @return the trait. - */ -struct TALER_TESTING_Trait -TALER_TESTING_make_trait_absolute_time ( - unsigned int index, - const struct GNUNET_TIME_Absolute *time); - #endif diff --git a/src/include/taler_twister_testing_lib.h b/src/include/taler_twister_testing_lib.h index fb0c352df..cdafab04b 100644 --- a/src/include/taler_twister_testing_lib.h +++ b/src/include/taler_twister_testing_lib.h @@ -26,7 +26,7 @@ #ifndef TALER_TWISTER_TESTING_LIB_H #define TALER_TWISTER_TESTING_LIB_H -#include <taler/taler_testing_lib.h> +#include "taler_testing_lib.h" #define TWISTER_FAIL() \ do {GNUNET_break (0); return NULL; } while (0) @@ -100,6 +100,23 @@ TALER_TESTING_cmd_modify_object_ul (const char *label, /** + * Create a "modify header" CMD. This command instructs + * the twister to modify a header in the next HTTP response. + * + * @param label command label + * @param config_filename configuration filename. + * @param path path identifying where to modify. + * @param value value to set the header to. + * @return the command + */ +struct TALER_TESTING_Command +TALER_TESTING_cmd_modify_header_dl (const char *label, + const char *config_filename, + const char *path, + const char *value); + + +/** * Create a "malform response" CMD. This command makes * the next response randomly malformed (by truncating it). * diff --git a/src/include/taler_util.h b/src/include/taler_util.h index c7bf9c02a..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-2020 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,17 +16,29 @@ /** * @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" #include "taler_crypto_lib.h" /** + * Version of the Taler API, in hex. + * Thus 0.8.4-1 = 0x00080401. + */ +#define TALER_API_VERSION 0x00090401 + +/** * Stringify operator. * * @param a some expression to stringify. Must NOT be a macro. @@ -73,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). @@ -119,18 +147,19 @@ TALER_b2s (const void *buf, * @param obj address of object to convert * @return string representing the binary obj buffer */ -#define TALER_B2S(obj) TALER_b2s (obj, sizeof (*obj)) +#define TALER_B2S(obj) TALER_b2s ((obj), sizeof (*(obj))) /** * Obtain denomination amount from configuration file. * + * @param cfg configuration to extract data from * @param section section of the configuration to access * @param option option of the configuration to access * @param[out] denom set to the amount found in configuration * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ -int +enum GNUNET_GenericReturnValue TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, @@ -138,6 +167,39 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg, /** + * Obtain denomination fee structure of a + * denomination from configuration file. All + * fee options must start with "fee_" and have + * names typical for the respective fees. + * + * @param cfg configuration to extract data from + * @param currency expected currency + * @param section section of the configuration to access + * @param[out] fees set to the denomination fees + * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + */ +enum GNUNET_GenericReturnValue +TALER_config_get_denom_fees (const struct GNUNET_CONFIGURATION_Handle *cfg, + const char *currency, + const char *section, + struct TALER_DenomFeeSet *fees); + + +/** + * Check that all denominations in @a fees use + * @a currency + * + * @param currency desired currency + * @param fees fee set to check + * @return #GNUNET_OK on success + */ +enum GNUNET_GenericReturnValue +TALER_denom_fee_check_currency ( + const char *currency, + const struct TALER_DenomFeeSet *fees); + + +/** * Load our currency from the @a cfg (in section [taler] * the option "CURRENCY"). * @@ -145,12 +207,107 @@ TALER_config_get_amount (const struct GNUNET_CONFIGURATION_Handle *cfg, * @param[out] currency where to write the result * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure */ -int +enum GNUNET_GenericReturnValue TALER_config_get_currency (const struct GNUNET_CONFIGURATION_Handle *cfg, char **currency); /** + * 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 @@ -175,6 +332,23 @@ TALER_project_data_default (void); /** + * Initialize libtalerutil. + */ +void +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 @@ -185,6 +359,44 @@ TALER_urlencode (const char *s); /** + * Test if all characters in @a url are valid for + * a URL. + * + * @param url URL to sanity-check + * @return true if @a url only contains valid characters + */ +bool +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 + * + * @param language_pattern a language preferences string + * like "fr-CH, fr;q=0.9, en;q=0.8, *;q=0.1" + * @param lang the 2-digit language to match + * @return q-weight given for @a lang in @a language_pattern, 1.0 if no weights are given; + * 0 if @a lang is not in @a language_pattern + */ +double +TALER_language_matches (const char *language_pattern, + const char *lang); + + +/** * Find out if an MHD connection is using HTTPS (either * directly or via proxy). * @@ -193,7 +405,7 @@ TALER_urlencode (const char *s); * #GNUNET_NO if the MHD connection is using http, * #GNUNET_SYSERR if the connection type couldn't be determined */ -int +enum GNUNET_GenericReturnValue TALER_mhd_is_https (struct MHD_Connection *connection); @@ -204,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 @@ -288,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 @@ -298,4 +525,305 @@ char * TALER_xtalerbank_account_from_payto (const char *payto); +/** + * Obtain the receiver name from a payto URL. + * + * @param payto an x-taler-bank payto URL + * @return only the receiver name from the @a payto URL, NULL if not an x-taler-bank payto URL + */ +char * +TALER_payto_get_receiver_name (const char *payto); + + +/** + * Extract the subject value from the URI parameters. + * + * @param payto_uri the URL to parse + * @return NULL if the subject parameter is not found. + * The caller should free the returned value. + */ +char * +TALER_payto_get_subject (const char *payto_uri); + + +/** + * Check that a payto:// URI is well-formed. + * + * @param payto_uri the URL to check + * @return NULL on success, otherwise an error + * message to be freed by the caller! + */ +char * +TALER_payto_validate (const char *payto_uri); + + +/** + * Create payto://-URI for a given exchange base URL + * and a @a reserve_pub. + * + * @param exchange_url the base URL of the exchange + * @param reserve_pub the public key of the reserve + * @return payto://-URI for the reserve (without receiver-name!) + */ +char * +TALER_reserve_make_payto (const char *exchange_url, + const struct TALER_ReservePublicKeyP *reserve_pub); + + +/** + * Check that an IBAN number is well-formed. + * + * Validates given IBAN according to the European Banking Standards. See: + * http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf + * + * @param iban the IBAN to check + * @return NULL on success, otherwise an error + * message to be freed by the caller! + */ +char * +TALER_iban_validate (const char *iban); + + +/** + * Possible values for a binary filter. + */ +enum TALER_EXCHANGE_YesNoAll +{ + /** + * If condition is yes. + */ + TALER_EXCHANGE_YNA_YES = 1, + + /** + * If condition is no. + */ + TALER_EXCHANGE_YNA_NO = 2, + + /** + * Condition disabled. + */ + TALER_EXCHANGE_YNA_ALL = 3 +}; + + +/** + * Convert query argument to @a yna value. + * + * @param connection connection to take query argument from + * @param arg argument to try for + * @param default_val value to assign if the argument is not present + * @param[out] yna value to set + * @return true on success, false if the parameter was malformed + */ +bool +TALER_arg_to_yna (struct MHD_Connection *connection, + const char *arg, + enum TALER_EXCHANGE_YesNoAll default_val, + enum TALER_EXCHANGE_YesNoAll *yna); + + +/** + * Convert YNA value to a string. + * + * @param yna value to convert + * @return string representation ("yes"/"no"/"all"). + */ +const char * +TALER_yna_to_string (enum TALER_EXCHANGE_YesNoAll yna); + + +#ifdef __APPLE__ +/** + * Returns the first occurrence of `c` in `s`, or returns the null-byte + * terminating the string if it does not occur. + * + * @param s the string to search in + * @param c the character to search for + * @return char* the first occurrence of `c` in `s` + */ +char *strchrnul (const char *s, int c); + +#endif + +/** + * @brief Parses a date information into days after 1970-01-01 (or 0) + * + * The input MUST be of the form + * + * 1) YYYY-MM-DD, representing a valid date + * 2) YYYY-MM-00, representing a valid month in a particular year + * 3) YYYY-00-00, representing a valid year. + * + * In the cases 2) and 3) the out parameter is set to the beginning of the + * time, f.e. 1950-00-00 == 1950-01-01 and 1888-03-00 == 1888-03-01 + * + * The output will set to the number of days after 1970-01-01 or 0, if the input + * represents a date belonging to the largest allowed age group. + * + * @param in Input string representation of the date + * @param mask Age mask + * @param[out] out Where to write the result + * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise + */ +enum GNUNET_GenericReturnValue +TALER_parse_coarse_date ( + const char *in, + const struct TALER_AgeMask *mask, + uint32_t *out); + + +/** + * @brief Parses a string as a list of age groups. + * + * The string must consist of a colon-separated list of increasing integers + * between 0 and 31. Each entry represents the beginning of a new age group. + * F.e. the string + * + * "8:10:12:14:16:18:21" + * + * represents the following list of eight age groups: + * + * | Group | Ages | + * | -----:|:------------- | + * | 0 | 0, 1, ..., 7 | + * | 1 | 8, 9 | + * | 2 | 10, 11 | + * | 3 | 12, 13 | + * | 4 | 14, 15 | + * | 5 | 16, 17 | + * | 6 | 18, 19, 20 | + * | 7 | 21, ... | + * + * which is then encoded as a bit mask with the corresponding bits set: + * + * 31 24 16 8 0 + * | | | | | + * oooooooo oo1oo1o1 o1o1o1o1 ooooooo1 + * + * @param groups String representation of age groups + * @param[out] mask Mask representation for age restriction. + * @return Error, if age groups were invalid, OK otherwise. + */ +enum GNUNET_GenericReturnValue +TALER_parse_age_group_string ( + const char *groups, + struct TALER_AgeMask *mask); + + +/** + * @brief Encodes the age mask into a string, like "8:10:12:14:16:18:21" + * + * NOTE: This function uses a static buffer. It is not safe to call this + * function concurrently. + * + * @param mask Age mask + * @return String representation of the age mask. + * Can be used as value in the TALER config. + */ +const char * +TALER_age_mask_to_string ( + const struct TALER_AgeMask *mask); + + +/** + * @brief returns the age group of a given age for a given age mask + * + * @param mask Age mask + * @param age The given age + * @return age group + */ +uint8_t +TALER_get_age_group ( + const struct TALER_AgeMask *mask, + uint8_t age); + + +/** + * @brief Parses a JSON object { "age_groups": "a:b:...y:z" }. + * + * @param root is the json object + * @param[out] mask on success, will contain the age mask + * @return #GNUNET_OK on success and #GNUNET_SYSERR on failure. + */ +enum GNUNET_GenericReturnValue +TALER_JSON_parse_age_groups (const json_t *root, + struct TALER_AgeMask *mask); + + +/** + * @brief Return the lowest age in the corresponding group for a given age + * according the given age mask. + * + * @param mask age mask + * @param age age to check + * @return lowest age in corresponding age group + */ +uint8_t +TALER_get_lowest_age ( + const struct TALER_AgeMask *mask, + uint8_t age); + + +/** + * @brief Get the lowest age for the largest age group + * + * @param mask the age mask + * @return lowest age for the largest age group + */ +#define TALER_adult_age(mask) \ + sizeof((mask)->bits) * 8 - __builtin_clz ((mask)->bits) - 1 + +/** + * Handle to an external process that will assist + * with some JSON-to-JSON conversion. + */ +struct TALER_JSON_ExternalConversion; + +/** + * Type of a callback that receives a JSON @a result. + * + * @param cls closure + * @param status_type how did the process die + * @param code termination status code from the process + * @param result some JSON result, NULL if we failed to get an JSON output + */ +typedef void +(*TALER_JSON_JsonCallback) (void *cls, + enum GNUNET_OS_ProcessStatusType status_type, + unsigned long code, + const json_t *result); + + +/** + * Launch some external helper @a binary to convert some @a input + * and eventually call @a cb with the result. + * + * @param input JSON to serialize and pass to the helper process + * @param cb function to call on the result + * @param cb_cls closure for @a cb + * @param binary name of the binary to execute + * @param ... NULL-terminated list of arguments for the @a binary, + * usually starting with again the name of the binary + * @return handle to cancel the operation (and kill the helper) + */ +struct TALER_JSON_ExternalConversion * +TALER_JSON_external_conversion_start (const json_t *input, + TALER_JSON_JsonCallback cb, + void *cb_cls, + const char *binary, + ...); + +/** + * Abort external conversion, killing the process and preventing + * the callback from being called. Must not be called after the + * callback was invoked. + * + * @param[in] ec external conversion handle to cancel + */ +void +TALER_JSON_external_conversion_stop ( + struct TALER_JSON_ExternalConversion *ec); + +#undef __TALER_UTIL_LIB_H_INSIDE__ + #endif |