donau

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

commit 7aa9f1928e285e28b1653db07d5b7a3bfafd423e
parent 960ddaf6e693504769d3930002868644b9e6de4f
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
Date:   Wed,  3 Apr 2024 10:38:34 +0200

[testing][donau] work on issue receipts

Diffstat:
Msrc/donau/donau-httpd.c | 14+++++++-------
Msrc/donau/donau-httpd_post-batch-issue.c | 18++++++++++++++----
Msrc/include/donau_json_lib.h | 13+++++++++++++
Msrc/include/donau_testing_lib.h | 22++++++++++++----------
Msrc/json/donau_json.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib/donau_api_batch_issue_receipts.c | 106++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/testing/test_donau_api.c | 9+++++----
Msrc/testing/testing_api_cmd_issue_receipts.c | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------
8 files changed, 215 insertions(+), 106 deletions(-)

diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c @@ -498,13 +498,13 @@ handle_mhd_request (void *cls, .nargs_is_upper_bound = true }, /* POST batch issue receipts */ - // { - // .url = "batch-issue", - // .method = MHD_HTTP_METHOD_POST, - // .handler.post = &DH_handler_issue_receipts_post, - // .nargs = 1, - // .nargs_is_upper_bound = true - // }, + { + .url = "batch-issue", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &DH_handler_issue_receipts_post, + .nargs = 1, + .nargs_is_upper_bound = true + }, /** etc diff --git a/src/donau/donau-httpd_post-batch-issue.c b/src/donau/donau-httpd_post-batch-issue.c @@ -259,10 +259,20 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, for (size_t i = 0; i < num_bkp; i++) { struct GNUNET_HashCode temp_hash; - GNUNET_CRYPTO_hash (irc.bkp, - sizeof (irc.bkp[0].blinded_udi) * num_bkp, + GNUNET_CRYPTO_hash (&irc.bkp[i].blinded_udi, + sizeof (irc.bkp[0].blinded_udi), &temp_hash); GNUNET_CRYPTO_hash_xor (&h_receipts.hash, &temp_hash, &h_receipts.hash); + GNUNET_CRYPTO_hash_xor (&h_receipts.hash, + &irc.bkp[i].h_donation_unit_pub.hash, + &h_receipts.hash); + } + { + struct GNUNET_HashCode sig_hash; + GNUNET_CRYPTO_hash (&irc.charity_sig, + sizeof (struct DONAU_CharitySignatureP), + &sig_hash); + GNUNET_CRYPTO_hash_xor (&h_receipts.hash, &sig_hash, &h_receipts.hash); } start: qs_check_receipts = DH_plugin->lookup_issued_receipts (DH_plugin->cls, @@ -293,7 +303,7 @@ start: blind_signatures)); } /* calculate new receipts to date and check annual limit */ - struct TALER_Amount receipts_sum; + struct TALER_Amount receipts_sum = {0}; for (size_t i = 0; i < num_bkp; i++) { MHD_RESULT mret; @@ -308,7 +318,7 @@ start: TALER_EC_GENERIC_PARAMETER_MALFORMED, "budikeypairs"); } - struct TALER_Amount new_receipts_to_date; + struct TALER_Amount new_receipts_to_date = {0}; TALER_amount_add (&new_receipts_to_date, &receipts_sum, &charity_meta.receipts_to_date); // new_receipts_to_date has to be smaller or equal as max_per_year diff --git a/src/include/donau_json_lib.h b/src/include/donau_json_lib.h @@ -115,4 +115,17 @@ DONAU_JSON_pack_blinded_donation_unit_sig ( const char *name, const struct DONAU_BlindedDonationUnitSignature *sig); +/** + * Generate packer instruction for a JSON field of type + * blinded udi. + * + * @param name name of the field to add to the object + * @param blinded_udi blinded unique donation identifier + * @return json pack specification + */ +struct GNUNET_JSON_PackSpec +DONAU_JSON_pack_blinded_donation_identifier ( + const char *name, + const struct DONAU_BlindedUniqueDonationIdentifier *blinded_udi); + #endif diff --git a/src/include/donau_testing_lib.h b/src/include/donau_testing_lib.h @@ -118,14 +118,16 @@ TALER_TESTING_cmd_charities_get (const char *label, * @param label the command label. * @param charity_reference reference for traits * @param year current year (mostly) + * @param num_bkps number of budi key pairs * @param expected_response_code expected HTTP response code. * @return the command. */ struct TALER_TESTING_Command TALER_TESTING_cmd_issue_receipts (const char *label, - const char *charity_reference, - const uint64_t year, - unsigned int expected_response_code); + const char *charity_reference, + const uint64_t year, + const size_t num_bkp, + unsigned int expected_response_code); /** * Convenience function to run a test. @@ -165,19 +167,19 @@ TALER_TESTING_get_donau_url ( * Call #op on all simple traits. */ #define DONAU_TESTING_SIMPLE_TRAITS(op) \ - op (charity_priv, const struct DONAU_CharityPrivateKeyP) \ - op (charity_pub, const struct DONAU_CharityPublicKeyP) \ - op (charity_id, const unsigned long long) \ - op (donau_url, const char) \ - op (donau_keys, struct DONAU_Keys) + op (charity_priv, const struct DONAU_CharityPrivateKeyP) \ + op (charity_pub, const struct DONAU_CharityPublicKeyP) \ + op (charity_id, const unsigned long long) \ + op (donau_url, const char) \ + op (donau_keys, struct DONAU_Keys) /** * Call #op on all indexed traits. */ #define DONAU_TESTING_INDEXED_TRAITS(op) \ - op (donation_unit_pub, const struct DONAU_DonationUnitInformation) \ - op (donau_pub, const struct TALER_ExchangePublicKeyP) + op (donation_unit_pub, const struct DONAU_DonationUnitInformation) \ + op (donau_pub, const struct TALER_ExchangePublicKeyP) DONAU_TESTING_SIMPLE_TRAITS (TALER_TESTING_MAKE_DECL_SIMPLE_TRAIT) DONAU_TESTING_INDEXED_TRAITS (TALER_TESTING_MAKE_DECL_INDEXED_TRAIT) diff --git a/src/json/donau_json.c b/src/json/donau_json.c @@ -397,4 +397,50 @@ DONAU_JSON_pack_blinded_donation_unit_sig ( } +struct GNUNET_JSON_PackSpec +DONAU_JSON_pack_blinded_donation_identifier ( + const char *name, + const struct DONAU_BlindedUniqueDonationIdentifier *blinded_udi) +{ + const struct GNUNET_CRYPTO_BlindedMessage *bm; + struct GNUNET_JSON_PackSpec ps = { + .field_name = name, + }; + + if (NULL == blinded_udi) + return ps; + bm = blinded_udi->blinded_message; + switch (bm->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_data_varsize ( + "rsa_blinded_identifier", + bm->details.rsa_blinded_message.blinded_msg, + bm->details.rsa_blinded_message.blinded_msg_size)); + return ps; + case GNUNET_CRYPTO_BSA_CS: + ps.object = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("cipher", + "CS"), + GNUNET_JSON_pack_data_auto ( + "cs_nonce", + &bm->details.cs_blinded_message.nonce), + GNUNET_JSON_pack_data_auto ( + "cs_blinded_c0", + &bm->details.cs_blinded_message.c[0]), + GNUNET_JSON_pack_data_auto ( + "cs_blinded_c1", + &bm->details.cs_blinded_message.c[1])); + return ps; + } + GNUNET_assert (0); + return ps; +} + + /* end of json/donau_json.c */ \ No newline at end of file diff --git a/src/lib/donau_api_batch_issue_receipts.c b/src/lib/donau_api_batch_issue_receipts.c @@ -83,38 +83,36 @@ struct DONAU_BatchIssueReceiptHandle */ json_t * issue_receipt_body_to_json (const unsigned int num_bkp, - const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp[static num_bkp], - const uint64_t year, - const struct DONAU_CharitySignatureP *charity_sig) + const struct + DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp[ + static num_bkp], + const uint64_t year, + const struct DONAU_CharitySignatureP *charity_sig) { - json_t *budikeypairs; + json_t *budikeypairs = json_array (); + GNUNET_assert (NULL != budikeypairs); - budikeypairs = json_array (); - GNUNET_assert (NULL != budikeypairs); - - for (unsigned int i = 0; i < num_bkp; i++) - { - json_t *budikeypair; - - budikeypair = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_data_auto ("h_du_pub", - &bkp[i]->h_donation_unit_pub), - GNUNET_JSON_pack_data_auto ("blinded_udi", - &bkp[i]->blinded_udi)); - GNUNET_assert (NULL != budikeypair); - GNUNET_assert (0 == - json_array_append_new (budikeypairs, - budikeypair)); - } - return GNUNET_JSON_PACK ( - GNUNET_JSON_pack_array_steal ("budikeypairs", - budikeypairs), - GNUNET_JSON_pack_data_auto ("charity_sig", - &charity_sig->eddsa_sig), - GNUNET_JSON_pack_uint64 ("year", - year)); + for (size_t i = 0; i < num_bkp; i++) + { + json_t *budikeypair = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_data_auto ("h_du_pub", + &bkp[i]->h_donation_unit_pub)); +// DONAU_JSON_pack_blinded_donation_identifier ("blinded_udi", +// &bkp[i]->blinded_udi)); + GNUNET_assert (0 == + json_array_append_new (budikeypairs, + budikeypair)); + } + return GNUNET_JSON_PACK ( + GNUNET_JSON_pack_array_steal ("budikeypairs", + budikeypairs), + GNUNET_JSON_pack_data_auto ("charity_sig", + &charity_sig->eddsa_sig), + GNUNET_JSON_pack_uint64 ("year", + year)); } + /** * Function called when we're done processing the * HTTP POST /batch-issue/$CHARITY_ID request. @@ -172,7 +170,7 @@ handle_batch_issue_finished (void *cls, if (NULL != birh->cb) { birh->cb (birh->cb_cls, - &biresp); + &biresp); birh->cb = NULL; } DONAU_charity_issue_receipt_cancel (birh); @@ -181,15 +179,16 @@ handle_batch_issue_finished (void *cls, struct DONAU_BatchIssueReceiptHandle * DONAU_charity_issue_receipt ( - struct GNUNET_CURL_Context *ctx, - const char *url, - const struct DONAU_CharityPrivateKeyP *charity_priv, - const uint64_t charity_id, - const uint64_t year, - const unsigned int num_bkp, - const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp[static num_bkp], - DONAU_BatchIssueReceiptsCallback cb, - void *cb_cls) + struct GNUNET_CURL_Context *ctx, + const char *url, + const struct DONAU_CharityPrivateKeyP *charity_priv, + const uint64_t charity_id, + const uint64_t year, + const unsigned int num_bkp, + const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp[static + num_bkp], + DONAU_BatchIssueReceiptsCallback cb, + void *cb_cls) { struct DONAU_BatchIssueReceiptHandle *birh; birh = GNUNET_new (struct DONAU_BatchIssueReceiptHandle); @@ -197,7 +196,8 @@ DONAU_charity_issue_receipt ( json_t *body; // make signature over budi-key-pair - DONAU_charity_budi_key_pair_sign(num_bkp, bkp, charity_priv, &birh->charity_sig); + DONAU_charity_budi_key_pair_sign (num_bkp, bkp, charity_priv, + &birh->charity_sig); TALER_LOG_DEBUG ("Connecting to the donau (%s)\n", url); @@ -207,24 +207,24 @@ DONAU_charity_issue_receipt ( birh->ctx = ctx; char arg_str[sizeof (charity_id) * 2 + 32]; GNUNET_snprintf (arg_str, - sizeof (arg_str), - "batch-issue/%llu", - (unsigned long long) - charity_id); + sizeof (arg_str), + "batch-issue/%llu", + (unsigned long long) + charity_id); birh->url = TALER_url_join (url, - arg_str, - NULL); + arg_str, + NULL); if (NULL == birh->url) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Could not construct request URL.\n"); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not construct request URL.\n"); GNUNET_free (birh); return NULL; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "issue receipts with URL `%s'.\n", + "issue_receipts_with_URL `%s'.\n", birh->url); - body = issue_receipt_body_to_json(num_bkp, bkp, year, &birh->charity_sig); + body = issue_receipt_body_to_json (num_bkp, bkp, year, &birh->charity_sig); eh = DONAU_curl_easy_get_ (birh->url); if ( (NULL == eh) || (GNUNET_OK != @@ -241,10 +241,10 @@ DONAU_charity_issue_receipt ( } json_decref (body); birh->job = GNUNET_CURL_job_add2 (ctx, - eh, - birh->post_ctx.headers, - &handle_batch_issue_finished, - birh); + eh, + birh->post_ctx.headers, + &handle_batch_issue_finished, + birh); return birh; } diff --git a/src/testing/test_donau_api.c b/src/testing/test_donau_api.c @@ -91,10 +91,11 @@ run (void *cls, TALER_TESTING_cmd_charities_get ("get-charities", &bearer, MHD_HTTP_OK), -// TALER_TESTING_cmd_issue_receipts ("issue-receipts", -// "post-charity", -// 2024, -// MHD_HTTP_CREATED), + TALER_TESTING_cmd_issue_receipts ("issue-receipts", + "post-charity", + 2024, + 3, // number of budi key pairs + MHD_HTTP_CREATED), TALER_TESTING_cmd_charity_delete ("delete-charity", "post-charity", // cmd trait reference &bearer, diff --git a/src/testing/testing_api_cmd_issue_receipts.c b/src/testing/testing_api_cmd_issue_receipts.c @@ -71,12 +71,12 @@ struct StatusState /** * number of budi key pair. */ - uint64_t num_bkp; + size_t num_bkp; /** * budi key pair array */ - const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp; + struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkps; }; @@ -90,7 +90,7 @@ struct StatusState */ static void issue_receipts_status_cb (void *cls, - const struct DONAU_BatchIssueResponse *biresp) + const struct DONAU_BatchIssueResponse *biresp) { struct StatusState *ss = cls; @@ -108,8 +108,8 @@ issue_receipts_status_cb (void *cls, TALER_TESTING_interpreter_fail (ss->is); return; } - //if (ss->expected_response_code == biresp->hr.http_status) - //ss->charity_id = (unsigned long long) biresp->details.ok.charity_id; + // if (ss->expected_response_code == biresp->hr.http_status) + // ss->charity_id = (unsigned long long) biresp->details.ok.charity_id; TALER_TESTING_interpreter_next (ss->is); } @@ -129,36 +129,61 @@ status_run (void *cls, struct StatusState *ss = cls; ss->is = is; - /* Get charity id from trait */ + /* Get charity id and the charity private key from trait */ { - const struct TALER_TESTING_Command *charity_post_cmd; - const unsigned long long *charity_id; - - charity_post_cmd = TALER_TESTING_interpreter_lookup_command (is, - ss->charity_reference); - - if (GNUNET_OK != - TALER_TESTING_get_trait_charity_id (charity_post_cmd, - &charity_id)) - { - GNUNET_break (0); - TALER_TESTING_interpreter_fail (is); - return; - } - ss->charity_id = (uint64_t) *(charity_id); + const struct TALER_TESTING_Command *charity_post_cmd; + const unsigned long long *charity_id; + const struct DONAU_CharityPrivateKeyP *charity_priv; + + charity_post_cmd = TALER_TESTING_interpreter_lookup_command (is, + ss-> + charity_reference); + + if (GNUNET_OK != + TALER_TESTING_get_trait_charity_id (charity_post_cmd, &charity_id) || + GNUNET_OK != TALER_TESTING_get_trait_charity_priv (charity_post_cmd, + &charity_priv)) + { + GNUNET_break (0); + TALER_TESTING_interpreter_fail (is); + return; + } + ss->charity_id = (uint64_t) *(charity_id); + ss->charity_priv = *(charity_priv); } // TODO: build bkps with traits from /keys request, use the public sign key from the // DONAU to verify the signatures + ss->bkps + = GNUNET_new_array (ss->num_bkp, + struct DONAU_BlindedUniqueDonationIdentifierKeyPair); + for (size_t cnt = 0; cnt < ss->num_bkp; cnt++) + { + struct GNUNET_CRYPTO_RsaBlindedMessage *rp; + struct DONAU_BlindedUniqueDonationIdentifier *bp; + bp = &ss->bkps[cnt].blinded_udi; + bp->blinded_message = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage); + bp->blinded_message->cipher = GNUNET_CRYPTO_BSA_RSA; + bp->blinded_message->rc = 1; + rp = &bp->blinded_message->details.rsa_blinded_message; + rp->blinded_msg_size = 1 + (size_t) GNUNET_CRYPTO_random_u64 ( + GNUNET_CRYPTO_QUALITY_WEAK, + (1024 / 8) - 1); // 1024 is the RSA key size + rp->blinded_msg = GNUNET_malloc (rp->blinded_msg_size); + GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, + rp->blinded_msg, + rp->blinded_msg_size); + } + const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkps = ss->bkps; ss->birh = DONAU_charity_issue_receipt ( TALER_TESTING_interpreter_get_context (is), TALER_TESTING_get_donau_url (is), &ss->charity_priv, ss->charity_id, ss->year, - ss->num_bkp, - &ss->bkp, + ss->num_bkp, + &bkps, &issue_receipts_status_cb, ss); @@ -174,7 +199,7 @@ status_run (void *cls, */ static void cleanup (void *cls, - const struct TALER_TESTING_Command *cmd) + const struct TALER_TESTING_Command *cmd) { struct StatusState *ss = cls; @@ -186,16 +211,26 @@ cleanup (void *cls, DONAU_charity_issue_receipt_cancel (ss->birh); ss->birh = NULL; } +// if (NULL != revealed_coins) +// { +// for (unsigned int cnt = 0; cnt < MELT_NEW_COINS; cnt++) +// { +// TALER_blinded_denom_sig_free (&revealed_coins[cnt].coin_sig); +// TALER_blinded_planchet_free (&revealed_coins[cnt].blinded_planchet); +// } +// GNUNET_free (revealed_coins); +// revealed_coins = NULL; +// } GNUNET_free (ss); } - struct TALER_TESTING_Command TALER_TESTING_cmd_issue_receipts (const char *label, - const char *charity_reference, - const uint64_t year, - unsigned int expected_response_code) + const char *charity_reference, + const uint64_t year, + const size_t num_bkp, + unsigned int expected_response_code) { struct StatusState *ss; @@ -204,6 +239,8 @@ TALER_TESTING_cmd_issue_receipts (const char *label, ss->year = year; ss->charity_reference = charity_reference; ss->expected_response_code = expected_response_code; + ss->num_bkp = num_bkp; + { struct TALER_TESTING_Command cmd = { .cls = ss,