donau

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

commit 0b52377dd9c9d17d0293ef5a0fc40ed267680956
parent 27b5cdbf3906061465c5cea6664cbd107f0174dd
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Tue, 22 Jul 2025 17:00:01 +0200

adding new c-api calls for merchant + update of the json pack/unpack

Diffstat:
Msrc/include/donau_service.h | 29+++++++++++++++++++++++++++++
Msrc/json/donau_json.c | 6++++++
Msrc/json/json_pack.c | 8++++++--
Msrc/lib/donau_api_handle.c | 120++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 157 insertions(+), 6 deletions(-)

diff --git a/src/include/donau_service.h b/src/include/donau_service.h @@ -426,6 +426,35 @@ DONAU_get_donation_unit_key_by_hash ( /** + * Obtain the donation amount for the given array of #DONAU_BlindedUniqueDonorIdentifierKeyPair + * + * @param keys the donau's key set + * @param bkps array of blinded unique donor identifiers + * @param num_bkps length of the @a bkps array + * @param year year of the donation + */ +const struct TALER_Amount * +DONAU_get_donation_amount_from_bkps ( + const struct DONAU_Keys *keys, + const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, + const size_t num_bkps, + const uint64_t year); + + +/** + * Get confirmation that the given array of the #DONAU_BlindedUniqueDonorIdentifierKeyPair + * does not contain duplicates. + * + * @return #GNUNET_OK if the @a bkps array does not contain duplicates + */ +const bool +DONAU_check_bkps_duplication ( + const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, + const size_t num_bkps + ); + + +/** * Obtain meta data about an donau (online) signing * key. * diff --git a/src/json/donau_json.c b/src/json/donau_json.c @@ -94,6 +94,9 @@ parse_donation_unit_pub (void *cls, GNUNET_JSON_spec_rsa_public_key ( "rsa_public_key", &bsign_pub->details.rsa_public_key), + GNUNET_JSON_spec_fixed_auto ( + "pub_key_hash", + &bsign_pub->pub_key_hash), GNUNET_JSON_spec_end () }; @@ -116,6 +119,9 @@ parse_donation_unit_pub (void *cls, GNUNET_JSON_spec_fixed ("cs_public_key", &bsign_pub->details.cs_public_key, sizeof (bsign_pub->details.cs_public_key)), + GNUNET_JSON_spec_fixed_auto ( + "pub_key_hash", + &bsign_pub->pub_key_hash), GNUNET_JSON_spec_end () }; diff --git a/src/json/json_pack.c b/src/json/json_pack.c @@ -49,7 +49,9 @@ DONAU_JSON_pack_donation_unit_pub ( GNUNET_JSON_pack_string ("cipher", "RSA"), GNUNET_JSON_pack_rsa_public_key ("rsa_public_key", - bsp->details.rsa_public_key)); + bsp->details.rsa_public_key), + GNUNET_JSON_pack_data_auto ("pub_key_hash", + &bsp->pub_key_hash)); return ps; case GNUNET_CRYPTO_BSA_CS: ps.object @@ -58,7 +60,9 @@ DONAU_JSON_pack_donation_unit_pub ( "CS"), GNUNET_JSON_pack_data_varsize ("cs_public_key", &bsp->details.cs_public_key, - sizeof (bsp->details.cs_public_key))); + sizeof (bsp->details.cs_public_key)), + GNUNET_JSON_pack_data_auto ("pub_key_hash", + &bsp->pub_key_hash)); return ps; } GNUNET_assert (0); diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c @@ -70,7 +70,7 @@ * how long do we assume the reply to be valid at least? */ #define MINIMUM_EXPIRATION GNUNET_TIME_relative_multiply ( \ - GNUNET_TIME_UNIT_MINUTES, 2) + GNUNET_TIME_UNIT_MINUTES, 2) /** @@ -120,9 +120,9 @@ struct DONAU_GetKeysHandle #define EXITIF(cond) \ - do { \ - if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ - } while (0) + do { \ + if (cond) { GNUNET_break (0); goto EXITIF_exit; } \ + } while (0) /** * Parse a donau's signing key encoded in JSON. @@ -541,6 +541,118 @@ DONAU_get_donation_unit_key_by_hash ( } +const struct TALER_Amount * +DONAU_get_donation_amount_from_bkps ( + const struct DONAU_Keys *keys, + const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, + const size_t num_bkps, + const uint64_t year) +{ + struct TALER_Amount *sum; + + /* Sanity-checks */ + if ( (NULL == keys) || + (NULL == bkps) || + (0 == num_bkps) ) + { + GNUNET_break (0); + return NULL; + } + if (GNUNET_YES == + DONAU_check_bkps_duplication (bkps, + num_bkps)) + { + GNUNET_break (0); + return NULL; + } + + sum = GNUNET_new (struct TALER_Amount); + TALER_amount_set_zero (keys->currency, + sum); + + for (size_t i = 0; i < num_bkps; i++) + { + const struct DONAU_DonationUnitInformation *dui = + DONAU_get_donation_unit_key_by_hash (keys, + &bkps[i].h_donation_unit_pub); + if (NULL == dui) + { + GNUNET_break (0); + GNUNET_free (sum); + return NULL; + } + if (dui->year != year) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Donation sum for year %lu requested, but " + "donation unit is for year %lu\n", + (unsigned long) year, + (unsigned long) dui->year); + GNUNET_free (sum); + return NULL; + } + + switch (TALER_amount_add (sum, + sum, + &dui->value)) + { + case TALER_AAR_RESULT_POSITIVE: + case TALER_AAR_RESULT_ZERO: + /* Zero a bit strange, but let's say that it's fine to some extent */ + break; + + case TALER_AAR_INVALID_NEGATIVE_RESULT: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Accumulation would go negative\n"); + GNUNET_break (0); + GNUNET_free (sum); + return NULL; + + case TALER_AAR_INVALID_RESULT_OVERFLOW: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Accumulation overflow\n"); + GNUNET_break (0); + GNUNET_free (sum); + return NULL; + + case TALER_AAR_INVALID_NORMALIZATION_FAILED: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Normalization failed during add\n"); + GNUNET_break (0); + GNUNET_free (sum); + return NULL; + + case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Currency mismatch during add\n"); + GNUNET_break (0); + GNUNET_free (sum); + return NULL; + } + } + return sum; +} + + +const bool +DONAU_check_bkps_duplication ( + const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, + const size_t num_bkps) +{ + if ( (NULL == bkps) || + (num_bkps < 2) ) + return GNUNET_NO; + + for (size_t i = 0; i < num_bkps - 1; i++) + for (size_t j = i + 1; j < num_bkps; j++) + if (0 == GNUNET_memcmp (&bkps[i].blinded_udi, + &bkps[j].blinded_udi)) + return GNUNET_YES; + + return GNUNET_NO; +} + + struct DONAU_Keys * DONAU_keys_incref (struct DONAU_Keys *keys) {