donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit 99f8abcc556159faffab39f6dfe62c70df279aba
parent f6147b01989563435ea723da76aabca9a3a69959
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
Date:   Tue,  2 Apr 2024 11:58:16 +0200

[json][pq] some functions for issue receipts

Diffstat:
Msrc/donau/Makefile.am | 4++--
Msrc/donau/donau-httpd_keys.c | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/donau/donau-httpd_keys.h | 32+++++++++++++++++++++++++++++++-
Msrc/donau/donau-httpd_post-batch-issue.c | 30++++++++++++++++--------------
Msrc/include/donau_json_lib.h | 11++++++-----
Msrc/json/donau_json.c | 210++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/json/json_helper.c | 2+-
Msrc/json/json_pack.c | 1+
Msrc/pq/pq_query_helper.c | 399+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 705 insertions(+), 36 deletions(-)

diff --git a/src/donau/Makefile.am b/src/donau/Makefile.am @@ -48,8 +48,8 @@ donau_httpd_SOURCES = \ donau-httpd_get-charity.c donau-httpd_post-charity.c \ donau-httpd_get-history.c \ donau-httpd_post-submit-receipts.c donau_httpd_submit-receipts.h \ - donau-httpd_terms.c donau-httpd_terms.h - #donau-httpd_post-batch-issue.c donau_httpd_batch-issue.h + donau-httpd_terms.c donau-httpd_terms.h \ + donau-httpd_post-batch-issue.c donau_httpd_batch-issue.h # Testcases diff --git a/src/donau/donau-httpd_keys.c b/src/donau/donau-httpd_keys.c @@ -1787,4 +1787,56 @@ DH_RESPONSE_reply_not_modified (struct MHD_Connection *connection, } +struct DH_DonationUnitKey * +DH_keys_donation_unit_by_hash ( + const struct DONAU_DonationUnitHashP *h_du_pub, + struct MHD_Connection *conn, + MHD_RESULT *mret) +{ + struct DH_KeyStateHandle *ksh; + + ksh = DH_keys_get_state (); + if (NULL == ksh) + { + *mret = TALER_MHD_reply_with_error (conn, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, + NULL); + return NULL; + } + return DH_keys_donation_unit_by_hash_from_state (ksh, + h_du_pub, + conn, + mret); +} + + +struct DH_DonationUnitKey * +DH_keys_donation_unit_by_hash_from_state ( + const struct DH_KeyStateHandle *ksh, + const struct DONAU_DonationUnitHashP *h_du_pub, + struct MHD_Connection *conn, + MHD_RESULT *mret) +{ + struct DH_DonationUnitKey *dk; + + dk = GNUNET_CONTAINER_multihashmap_get (ksh->donation_unit_map, + &h_du_pub->hash); + if (NULL == dk) + { + if (NULL == conn) + return NULL; + // FIXME: server error or not found? + // *mret = TEH_RESPONSE_reply_unknown_denom_pub_hash (conn, + // h_denom_pub); + *mret = TALER_MHD_reply_with_error (conn, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_DONAU_GENERIC_KEYS_MISSING, + NULL); + return NULL; + } + return dk; +} + + /* end of donau-httpd_keys.c */ diff --git a/src/donau/donau-httpd_keys.h b/src/donau/donau-httpd_keys.h @@ -32,6 +32,18 @@ /** + * Snapshot of the (coin and signing) keys (including private keys) of + * the exchange. There can be multiple instances of this struct, as it is + * reference counted and only destroyed once the last user is done + * with it. The current instance is acquired using + * #TEH_KS_acquire(). Using this function increases the + * reference count. The contents of this structure (except for the + * reference counter) should be considered READ-ONLY until it is + * ultimately destroyed (as there can be many concurrent users). + */ +struct DH_KeyStateHandle; + +/** * @brief All information about a donation unit key (which is used to * sign donation receipts into existence). */ @@ -174,7 +186,6 @@ DH_handler_keys (struct DH_RequestContext *rc, const char *const args[]); -// TODO: Implement /** * Look up the issue for a donation unit public key. Note that the result * must only be used in this thread and only until another key or @@ -192,6 +203,25 @@ DH_keys_donation_unit_by_hash ( struct MHD_Connection *conn, MHD_RESULT *mret); +/** + * Look up the issue for a donation unit public key using a given @a ksh. This allows + * requesting multiple donation units with the same @a ksh which thus will + * remain valid until the next call to #TEH_keys_donation_unit_by_hash() or + * #DH_keys_get_state() or #DH_keys_donau_sign(). + * + * @param ksh key state state to look in + * @param h_du_pub hash of donation unit public key + * @param[in,out] conn connection used to return status message if NULL is returned + * @param[out] mret set to the MHD status if NULL is returned + * @return the donation unit key issue, + * or NULL if @a h_du_pub could not be found + */ +struct DH_DonationUnitKey * +DH_keys_donation_unit_by_hash_from_state ( + const struct DH_KeyStateHandle *ksh, + const struct DONAU_DonationUnitHashP *h_du_pub, + struct MHD_Connection *conn, + MHD_RESULT *mret); /** * Initialize keys subsystem. diff --git a/src/donau/donau-httpd_post-batch-issue.c b/src/donau/donau-httpd_post-batch-issue.c @@ -47,6 +47,11 @@ struct IssueReceiptsContext }; /** + * insert failure because of a bad issued receipt lookup? Try another time... + */ +bool second_time = false; + +/** * Parse a bkp encoded in JSON. * * @param[out] bkp where to return the result @@ -61,8 +66,8 @@ parse_json_bkp (struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("h_du_pub", &bkp->h_donation_unit_pub), - DONAU_JSON_spec_blinded_udi ("blinded_udi", - &bkp->blinded_udi), + DONAU_JSON_spec_blinded_donation_identifier ("blinded_udi", + &bkp->blinded_udi), GNUNET_JSON_spec_end () }; @@ -82,19 +87,18 @@ parse_json_bkp (struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, /** * Parse signatures to JSON. * - * @param[out] sign_arr_obj JSON object - * @param signatures * @param num_sig number of signatures + * @param signatures + * @param[out] j_signatures JSON object * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if we could not parse * is malformed. */ void -signatures_to_JSON (const unsigned int num_sig, +signatures_to_JSON (const size_t num_sig, struct DONAU_BlindedDonationUnitSignature*signatures, json_t *j_signatures) { - int i = 0; - while (i < num_sig) + for (size_t i = 0; i < num_sig; i++) { struct DONAU_BlindedDonationUnitSignature*signature = &signatures[i]; GNUNET_assert ( @@ -103,7 +107,6 @@ signatures_to_JSON (const unsigned int num_sig, GNUNET_JSON_PACK ( DONAU_JSON_pack_blinded_donation_unit_sig ("blinded_signatures", signature)))); - i++; } } @@ -171,7 +174,7 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, if (0 != num_bkp) { json_t *bkp_obj; - unsigned int index; + size_t index; struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp = GNUNET_new_array @@ -251,8 +254,9 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, struct DONAUDB_IssuedReceiptsMetaData check_receipts_meta; struct DONAU_DonationReceiptHashP h_receipts = {0}; json_t *blind_signatures = json_array (); + GNUNET_assert (NULL != blind_signatures); - for (int i = 0; i < num_bkp; i++) + for (size_t i = 0; i < num_bkp; i++) { struct GNUNET_HashCode temp_hash; GNUNET_CRYPTO_hash (irc.bkp, @@ -290,7 +294,7 @@ start: } /* calculate new receipts to date and check annual limit */ struct TALER_Amount receipts_sum; - for (int i = 0; i < num_bkp; i++) + for (size_t i = 0; i < num_bkp; i++) { MHD_RESULT mret; struct DH_DonationUnitKey *dk; @@ -319,8 +323,7 @@ start: /* sign budis and send the signatures back */ struct DONAU_BlindedDonationUnitSignature *du_sigs = {0}; { - int i = 0; - while (i < num_bkp) + for (size_t i = 0; i < num_bkp; i++) { // TODO: get donation unit private key const struct DONAU_DonationUnitPrivateKey du_priv; @@ -337,7 +340,6 @@ start: NULL); } - i++; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "made blind signatures!"); diff --git a/src/include/donau_json_lib.h b/src/include/donau_json_lib.h @@ -59,7 +59,7 @@ DONAU_JSON_spec_donation_unit_group (const char *field, const char *currency, struct DONAU_DonationUnitGroup *group); -// TODO: Implement (like exchange TALER_JSON_spec_blinded_planchet method) + /** * Generate line in parser specification for a * blinded unique identifier. @@ -69,9 +69,11 @@ DONAU_JSON_spec_donation_unit_group (const char *field, * @return corresponding field spec */ struct GNUNET_JSON_Specification -DONAU_JSON_spec_blinded_udi (const char *field, - struct DONAU_BlindedUniqueDonationIdentifier * - blinded_udi); +DONAU_JSON_spec_blinded_donation_identifier (const char *field, + struct + DONAU_BlindedUniqueDonationIdentifier + * + blinded_udi); /** @@ -99,7 +101,6 @@ DONAU_JSON_pack_donation_unit_pub ( const char *name, const struct DONAU_DonationUnitPublicKey *pk); -// TODO: implement /** * Generate packer instruction for a JSON field of type * blinded donation unit signature (that needs to be diff --git a/src/json/donau_json.c b/src/json/donau_json.c @@ -24,7 +24,7 @@ #include <taler/taler_json_lib.h> #include <unistr.h> #include "donau_json_lib.h" -# + /** * Parse given JSON object partially into a donation unit public key. @@ -38,8 +38,8 @@ */ static enum GNUNET_GenericReturnValue parse_donation_unit_pub_cipher (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) + json_t *root, + struct GNUNET_JSON_Specification *spec) { struct DONAU_DonationUnitPublicKey *donation_unit_pub = spec->ptr; enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher = @@ -105,6 +105,7 @@ parse_donation_unit_pub_cipher (void *cls, return GNUNET_SYSERR; } + /** * Cleanup data left from parsing donation unit public key. * @@ -113,7 +114,7 @@ parse_donation_unit_pub_cipher (void *cls, */ static void clean_donation_unit_pub (void *cls, - struct GNUNET_JSON_Specification *spec) + struct GNUNET_JSON_Specification *spec) { struct DONAU_DonationUnitPublicKey *donation_unit_pub = spec->ptr; @@ -121,9 +122,12 @@ clean_donation_unit_pub (void *cls, DONAU_donation_unit_pub_free (donation_unit_pub); } + struct GNUNET_JSON_Specification DONAU_JSON_spec_donation_unit_pub_cipher (const char *field, - enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher, + enum + GNUNET_CRYPTO_BlindSignatureAlgorithm + cipher, struct DONAU_DonationUnitPublicKey *pk) { struct GNUNET_JSON_Specification ret = { @@ -137,6 +141,7 @@ DONAU_JSON_spec_donation_unit_pub_cipher (const char *field, return ret; } + /** * Convert string value to numeric cipher value. * @@ -147,18 +152,19 @@ static enum GNUNET_CRYPTO_BlindSignatureAlgorithm string_to_cipher (const char *cipher_s) { if (0 == strcasecmp (cipher_s, - "RSA")) + "RSA")) return GNUNET_CRYPTO_BSA_RSA; if (0 == strcasecmp (cipher_s, - "CS")) + "CS")) return GNUNET_CRYPTO_BSA_CS; return GNUNET_CRYPTO_BSA_INVALID; } + static enum GNUNET_GenericReturnValue parse_donation_unit_group (void *cls, - json_t *root, - struct GNUNET_JSON_Specification *spec) + json_t *root, + struct GNUNET_JSON_Specification *spec) { struct DONAU_DonationUnitGroup *group = spec->ptr; const char *cipher; @@ -199,10 +205,11 @@ parse_donation_unit_group (void *cls, return GNUNET_OK; } + struct GNUNET_JSON_Specification DONAU_JSON_spec_donation_unit_group (const char *name, - const char *currency, - struct DONAU_DonationUnitGroup *group) + const char *currency, + struct DONAU_DonationUnitGroup *group) { struct GNUNET_JSON_Specification ret = { .cls = (void *) currency, @@ -213,4 +220,181 @@ DONAU_JSON_spec_donation_unit_group (const char *name, }; return ret; -} -\ No newline at end of file +} + + +/** + * Parse given JSON object to blinded planchet. + * + * @param cls closure, NULL + * @param root the json object representing data + * @param[out] spec where to write the data + * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error + */ +static enum GNUNET_GenericReturnValue +parse_blinded_planchet (void *cls, + json_t *root, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr; + struct GNUNET_CRYPTO_BlindedMessage *blinded_message; + const char *cipher; + struct GNUNET_JSON_Specification dspec[] = { + GNUNET_JSON_spec_string ("cipher", + &cipher), + GNUNET_JSON_spec_end () + }; + const char *emsg; + unsigned int eline; + + (void) cls; + if (GNUNET_OK != + GNUNET_JSON_parse (root, + dspec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + return GNUNET_SYSERR; + } + blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage); + blinded_message->rc = 1; + blinded_message->cipher = string_to_cipher (cipher); + switch (blinded_message->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + break; + case GNUNET_CRYPTO_BSA_RSA: + { + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_varsize ( + "rsa_blinded_planchet", + &blinded_message->details.rsa_blinded_message.blinded_msg, + &blinded_message->details.rsa_blinded_message.blinded_msg_size), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + ispec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + GNUNET_free (blinded_message); + return GNUNET_SYSERR; + } + blinded_planchet->blinded_message = blinded_message; + return GNUNET_OK; + } + case GNUNET_CRYPTO_BSA_CS: + { + struct GNUNET_JSON_Specification ispec[] = { + GNUNET_JSON_spec_fixed_auto ( + "cs_nonce", + &blinded_message->details.cs_blinded_message.nonce), + GNUNET_JSON_spec_fixed_auto ( + "cs_blinded_c0", + &blinded_message->details.cs_blinded_message.c[0]), + GNUNET_JSON_spec_fixed_auto ( + "cs_blinded_c1", + &blinded_message->details.cs_blinded_message.c[1]), + GNUNET_JSON_spec_end () + }; + + if (GNUNET_OK != + GNUNET_JSON_parse (root, + ispec, + &emsg, + &eline)) + { + GNUNET_break_op (0); + GNUNET_free (blinded_message); + return GNUNET_SYSERR; + } + blinded_planchet->blinded_message = blinded_message; + return GNUNET_OK; + } + } + GNUNET_break_op (0); + GNUNET_free (blinded_message); + return GNUNET_SYSERR; +} + + +/** + * Cleanup data left from parsing blinded planchet. + * + * @param cls closure, NULL + * @param[out] spec where to free the data + */ +static void +clean_blinded_planchet (void *cls, + struct GNUNET_JSON_Specification *spec) +{ + struct TALER_BlindedPlanchet *blinded_planchet = spec->ptr; + + (void) cls; + TALER_blinded_planchet_free (blinded_planchet); +} + + +struct GNUNET_JSON_Specification +DONAU_JSON_spec_blinded_donation_identifier (const char *field, + struct + DONAU_BlindedUniqueDonationIdentifier + * + blinded_udi) +{ + struct GNUNET_JSON_Specification ret = { + .parser = &parse_blinded_planchet, + .cleaner = &clean_blinded_planchet, + .field = field, + .ptr = blinded_udi + }; + + blinded_udi->blinded_message = NULL; + return ret; +} + + +struct GNUNET_JSON_PackSpec +DONAU_JSON_pack_blinded_donation_unit_sig ( + const char *name, + const struct DONAU_BlindedDonationUnitSignature *sig) +{ + const struct GNUNET_CRYPTO_BlindedSignature *bs; + struct GNUNET_JSON_PackSpec ps = { + .field_name = name, + }; + + if (NULL == sig) + return ps; + bs = sig->blinded_sig; + switch (bs->cipher) + { + case GNUNET_CRYPTO_BSA_INVALID: + break; + case GNUNET_CRYPTO_BSA_RSA: + ps.object = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("cipher", + "RSA"), + GNUNET_JSON_pack_rsa_signature ("blinded_rsa_signature", + bs->details.blinded_rsa_signature)); + return ps; + case GNUNET_CRYPTO_BSA_CS: + ps.object = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("cipher", + "CS"), + GNUNET_JSON_pack_uint64 ("b", + bs->details.blinded_cs_answer.b), + GNUNET_JSON_pack_data_auto ("s", + &bs->details.blinded_cs_answer.s_scalar)); + return ps; + } + GNUNET_assert (0); + return ps; +} + + +/* end of json/donau_json.c */ +\ No newline at end of file diff --git a/src/json/json_helper.c b/src/json/json_helper.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2024 Taler Systems SA + Copyright (C) 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 diff --git a/src/json/json_pack.c b/src/json/json_pack.c @@ -17,6 +17,7 @@ * @file json/json_pack.c * @brief helper functions for JSON object packing * @author Christian Grothoff + * @author Lukas Matyja */ #include <taler/platform.h> #include <gnunet/gnunet_util_lib.h> diff --git a/src/pq/pq_query_helper.c b/src/pq/pq_query_helper.c @@ -122,4 +122,403 @@ DONAU_PQ_query_param_donation_unit_pub ( } +// FIXME: +// /** +// * Function to generate a typ specific query parameter and corresponding closure +// * +// * @param num Number of elements in @a elements +// * @param continuous If true, @a elements is an continuous array of data +// * @param elements Array of @a num elements, either continuous or pointers +// * @param sizes Array of @a num sizes, one per element, may be NULL +// * @param same_size If not 0, all elements in @a elements have this size +// * @param typ Supported internal type of each element in @a elements +// * @param oid Oid of the type to be used in Postgres +// * @param[in,out] db our database handle for looking up OIDs +// * @return Query parameter +// */ +// static struct GNUNET_PQ_QueryParam +// query_param_array_generic ( +// unsigned int num, +// bool continuous, +// const void *elements, +// const size_t *sizes, +// size_t same_size, +// enum TALER_PQ_ArrayType typ, +// Oid oid, +// struct GNUNET_PQ_Context *db) +// { +// struct qconv_array_cls *meta = GNUNET_new (struct qconv_array_cls); + +// meta->typ = typ; +// meta->oid = oid; +// meta->sizes = sizes; +// meta->same_size = same_size; +// meta->continuous = continuous; +// meta->db = db; + +// { +// struct GNUNET_PQ_QueryParam res = { +// .conv = qconv_array, +// .conv_cls = meta, +// .conv_cls_cleanup = qconv_array_cls_cleanup, +// .data = elements, +// .size = num, +// .num_params = 1, +// }; + +// return res; +// } +// } + +// struct GNUNET_PQ_QueryParam +// DONAU_PQ_query_param_array_blinded_donation_unit_sig ( +// size_t num, +// const struct DONAU_BlindedDonationUnitSignature *du_sigs, +// struct GNUNET_PQ_Context *db) +// { +// Oid oid; + +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "bytea", +// &oid)); +// return query_param_array_generic (num, +// true, +// du_sigs, +// NULL, +// 0, +// TALER_PQ_array_of_blinded_denom_sig, +// oid, +// NULL); +// } + +// /** +// * Extract data from a Postgres database @a result as array of a specific type +// * from row @a row. The type information and optionally additional +// * out-parameters are given in @a cls which is of type array_result_cls. +// * +// * @param cls closure of type array_result_cls +// * @param result where to extract data from +// * @param row row to extract data from +// * @param fname name (or prefix) of the fields to extract from +// * @param[in,out] dst_size where to store size of result, may be NULL +// * @param[out] dst where to store the result +// * @return +// * #GNUNET_YES if all results could be extracted +// * #GNUNET_SYSERR if a result was invalid (non-existing field or NULL) +// */ +// static enum GNUNET_GenericReturnValue +// extract_array_generic ( +// void *cls, +// PGresult *result, +// int row, +// const char *fname, +// size_t *dst_size, +// void *dst) +// { +// const struct ArrayResultCls *info = cls; +// int data_sz; +// char *data; +// void *out = NULL; +// struct GNUNET_PQ_ArrayHeader_P header; +// int col_num; + +// GNUNET_assert (NULL != dst); +// *((void **) dst) = NULL; + +// #define FAIL_IF(cond) \ +// do { \ +// if ((cond)) \ +// { \ +// GNUNET_break (! (cond)); \ +// goto FAIL; \ +// } \ +// } while (0) + +// col_num = PQfnumber (result, fname); +// FAIL_IF (0 > col_num); + +// data_sz = PQgetlength (result, row, col_num); +// FAIL_IF (0 > data_sz); +// FAIL_IF (sizeof(header) > (size_t) data_sz); + +// data = PQgetvalue (result, row, col_num); +// FAIL_IF (NULL == data); + +// { +// struct GNUNET_PQ_ArrayHeader_P *h = +// (struct GNUNET_PQ_ArrayHeader_P *) data; + +// header.ndim = ntohl (h->ndim); +// header.has_null = ntohl (h->has_null); +// header.oid = ntohl (h->oid); +// header.dim = ntohl (h->dim); +// header.lbound = ntohl (h->lbound); + +// FAIL_IF (1 != header.ndim); +// FAIL_IF (INT_MAX <= header.dim); +// FAIL_IF (0 != header.has_null); +// FAIL_IF (1 != header.lbound); +// FAIL_IF (info->oid != header.oid); +// } + +// if (NULL != info->num) +// *info->num = header.dim; + +// { +// char *in = data + sizeof(header); + +// switch (info->typ) +// { +// case TALER_PQ_array_of_amount: +// { +// struct TALER_Amount *amounts; +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_Amount) * (header.dim); + +// amounts = GNUNET_new_array (header.dim, +// struct TALER_Amount); +// *((void **) dst) = amounts; + +// for (uint32_t i = 0; i < header.dim; i++) +// { +// struct TALER_PQ_AmountP ap; +// struct TALER_Amount *amount = &amounts[i]; +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// in += sizeof(val); + +// /* total size for this array-entry */ +// FAIL_IF (sizeof(ap) != sz); + +// GNUNET_memcpy (&ap, +// in, +// sz); +// FAIL_IF (2 != ntohl (ap.cnt)); + +// amount->value = GNUNET_ntohll (ap.v); +// amount->fraction = ntohl (ap.f); +// GNUNET_memcpy (amount->currency, +// info->currency, +// TALER_CURRENCY_LEN); + +// in += sizeof(struct TALER_PQ_AmountP); +// } +// return GNUNET_OK; +// } +// case TALER_PQ_array_of_denom_hash: +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_DenominationHashP) * (header.dim); +// out = GNUNET_new_array (header.dim, +// struct TALER_DenominationHashP); +// *((void **) dst) = out; +// for (uint32_t i = 0; i < header.dim; i++) +// { +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sz != sizeof(struct TALER_DenominationHashP)); +// in += sizeof(uint32_t); +// *(struct TALER_DenominationHashP *) out = +// *(struct TALER_DenominationHashP *) in; +// in += sz; +// out += sz; +// } +// return GNUNET_OK; + +// case TALER_PQ_array_of_hash_code: +// if (NULL != dst_size) +// *dst_size = sizeof(struct GNUNET_HashCode) * (header.dim); +// out = GNUNET_new_array (header.dim, +// struct GNUNET_HashCode); +// *((void **) dst) = out; +// for (uint32_t i = 0; i < header.dim; i++) +// { +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sz != sizeof(struct GNUNET_HashCode)); +// in += sizeof(uint32_t); +// *(struct GNUNET_HashCode *) out = +// *(struct GNUNET_HashCode *) in; +// in += sz; +// out += sz; +// } +// return GNUNET_OK; + +// case TALER_PQ_array_of_blinded_coin_hash: +// if (NULL != dst_size) +// *dst_size = sizeof(struct TALER_BlindedCoinHashP) * (header.dim); +// out = GNUNET_new_array (header.dim, +// struct TALER_BlindedCoinHashP); +// *((void **) dst) = out; +// for (uint32_t i = 0; i < header.dim; i++) +// { +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sz != sizeof(struct TALER_BlindedCoinHashP)); +// in += sizeof(uint32_t); +// *(struct TALER_BlindedCoinHashP *) out = +// *(struct TALER_BlindedCoinHashP *) in; +// in += sz; +// out += sz; +// } +// return GNUNET_OK; + +// case TALER_PQ_array_of_blinded_denom_sig: +// { +// struct TALER_BlindedDenominationSignature *denom_sigs; +// if (0 == header.dim) +// { +// if (NULL != dst_size) +// *dst_size = 0; +// break; +// } + +// denom_sigs = GNUNET_new_array (header.dim, +// struct TALER_BlindedDenominationSignature); +// *((void **) dst) = denom_sigs; + +// /* copy data */ +// for (uint32_t i = 0; i < header.dim; i++) +// { +// struct TALER_BlindedDenominationSignature *denom_sig = &denom_sigs[i]; +// struct GNUNET_CRYPTO_BlindedSignature *bs; +// uint32_t be[2]; +// uint32_t val; +// size_t sz; + +// GNUNET_memcpy (&val, +// in, +// sizeof(val)); +// sz = ntohl (val); +// FAIL_IF (sizeof(be) > sz); + +// in += sizeof(val); +// GNUNET_memcpy (&be, +// in, +// sizeof(be)); +// FAIL_IF (0x01 != ntohl (be[1])); /* magic marker: blinded */ + +// in += sizeof(be); +// sz -= sizeof(be); +// bs = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature); +// bs->cipher = ntohl (be[0]); +// bs->rc = 1; +// switch (bs->cipher) +// { +// case GNUNET_CRYPTO_BSA_RSA: +// bs->details.blinded_rsa_signature +// = GNUNET_CRYPTO_rsa_signature_decode (in, +// sz); +// if (NULL == bs->details.blinded_rsa_signature) +// { +// GNUNET_free (bs); +// FAIL_IF (true); +// } +// break; +// case GNUNET_CRYPTO_BSA_CS: +// if (sizeof(bs->details.blinded_cs_answer) != sz) +// { +// GNUNET_free (bs); +// FAIL_IF (true); +// } +// GNUNET_memcpy (&bs->details.blinded_cs_answer, +// in, +// sz); +// break; +// default: +// GNUNET_free (bs); +// FAIL_IF (true); +// } +// denom_sig->blinded_sig = bs; +// in += sz; +// } +// return GNUNET_OK; +// } +// default: +// FAIL_IF (true); +// } +// } +// FAIL: +// GNUNET_free (*(void **) dst); +// return GNUNET_SYSERR; +// #undef FAIL_IF +// } + + +// /** +// * Cleanup of the data and closure of an array spec. +// */ +// static void +// array_cleanup (void *cls, +// void *rd) +// { +// struct ArrayResultCls *info = cls; +// void **dst = rd; + +// if ((0 == info->same_size) && +// (NULL != info->sizes)) +// GNUNET_free (*(info->sizes)); + +// /* Clean up signatures, if applicable */ +// if (TALER_PQ_array_of_blinded_denom_sig == info->typ) +// { +// struct TALER_BlindedDenominationSignature *denom_sigs = *dst; +// GNUNET_assert (NULL != info->num); +// for (size_t i = 0; i < *info->num; i++) +// GNUNET_free (denom_sigs[i].blinded_sig); +// } + +// GNUNET_free (cls); +// GNUNET_free (*dst); +// *dst = NULL; +// } + + +// struct GNUNET_PQ_ResultSpec +// DONAU_PQ_result_spec_array_blinded_donation_unit_sig ( +// struct GNUNET_PQ_Context *db, +// const char *name, +// size_t *num, +// struct DONAU_BlindedDonationUnitSignature **du_sigs) +// { +// struct ArrayResultCls *info = GNUNET_new (struct ArrayResultCls); + +// info->num = num; +// info->typ = TALER_PQ_array_of_blinded_denom_sig; +// GNUNET_assert (GNUNET_OK == +// GNUNET_PQ_get_oid_by_name (db, +// "bytea", +// &info->oid)); + +// struct GNUNET_PQ_ResultSpec res = { +// .conv = extract_array_generic, +// .cleaner = array_cleanup, +// .dst = (void *) du_sigs, +// .fname = name, +// .cls = info +// }; +// return res; + +// } + /* end of pq/pq_query_helper.c */