donau

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

commit 4732a631de54c23b7e81be64b7a9b66cd497c5a4
parent 9ea74128d8f25d758de8d9319176a33cfda0b222
Author: Christian Grothoff <christian@grothoff.org>
Date:   Sat, 10 Oct 2026 17:32:25 +0200

implement v2/vLimitConflict

Diffstat:
Msrc/donau/donau-httpd_get-config.h | 11+++++------
Msrc/donau/donau-httpd_post-batch-issue-CHARITY_ID.c | 3+--
Msrc/lib/donau_api_batch_issue_receipts.c | 3++-
Msrc/lib/donau_api_handle.c | 4++--
Msrc/testing/test_donau_api.c | 18++++++++++++++++++
Msrc/testing/testing_api_cmd_issue_receipts.c | 11+++++++++--
6 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/src/donau/donau-httpd_get-config.h b/src/donau/donau-httpd_get-config.h @@ -41,12 +41,11 @@ * * Returned via both /config and /keys endpoints. */ -/* Revision bumped from 0 to 1: POST /batch-submit now answers 409 - DONAU_DONOR_IDENTIFIER_NONCE_REUSE for receipts it cannot store, - where it used to answer 201 Created and drop them. `current' is - unchanged: no request or response schema changed, and a client that - never reuses a nonce sees no difference. */ -#define DONAU_PROTOCOL_VERSION "1:1:1" +/* v2: POST /batch-issue answers an exceeded yearly donation limit with + 409 instead of 400 (same error code), so that clients can tell it + apart from a malformed request. Clients that dispatch on the error + code see no difference, hence `age' is incremented as well. */ +#define DONAU_PROTOCOL_VERSION "2:0:2" /** diff --git a/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c b/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c @@ -572,14 +572,13 @@ start: } if (! smaller_than_max_per_year) { - GNUNET_break_op (0); free_bkps (num_bkps, bkps); json_decref (blind_signatures); for (unsigned int i = 0; i<num_bkps; i++) GNUNET_CRYPTO_blinded_sig_decref (du_sigs[i].blinded_sig); return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, + MHD_HTTP_CONFLICT, TALER_EC_DONAU_EXCEEDING_DONATION_LIMIT, NULL); } diff --git a/src/lib/donau_api_batch_issue_receipts.c b/src/lib/donau_api_batch_issue_receipts.c @@ -266,7 +266,8 @@ handle_batch_issue_finished (void *cls, biresp.hr.hint = TALER_JSON_get_error_hint (j); break; case MHD_HTTP_CONFLICT: - // Donation limit is not sufficient + // wrong year for the donation unit, or donation limit is not + // sufficient (the latter was a 400 before protocol v2) biresp.hr.ec = TALER_JSON_get_error_code (j); biresp.hr.hint = TALER_JSON_get_error_hint (j); break; diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c @@ -37,12 +37,12 @@ * Which version of the Donau protocol is implemented * by this library? Used to determine compatibility. */ -#define DONAU_PROTOCOL_CURRENT 1 +#define DONAU_PROTOCOL_CURRENT 2 /** * How many versions are we backwards compatible with? */ -#define DONAU_PROTOCOL_AGE 1 +#define DONAU_PROTOCOL_AGE 2 /** * Set to 1 for extra debug logging. diff --git a/src/testing/test_donau_api.c b/src/testing/test_donau_api.c @@ -112,6 +112,24 @@ run (void *cls, "1234", // salt for tax id hash "EUR:5", /* Amount to be issued*/ MHD_HTTP_OK), + /* EUR:5 + EUR:11 exceeds the yearly limit of EUR:15 */ + TALER_TESTING_cmd_issue_receipts ("issue-receipts-over-limit", + "patch-charity", + uses_cs, + GNUNET_TIME_get_current_year (), + "7560001010000", // tax id + "1234", // salt for tax id hash + "EUR:11", /* Amount to be issued*/ + MHD_HTTP_CONFLICT), + /* the refused request did not use up any of the limit */ + TALER_TESTING_cmd_issue_receipts ("issue-receipts-up-to-limit", + "patch-charity", + uses_cs, + GNUNET_TIME_get_current_year (), + "7560001010000", // tax id + "1234", // salt for tax id hash + "EUR:10", /* Amount to be issued*/ + MHD_HTTP_OK), TALER_TESTING_cmd_submit_receipts ("submit-receipts", "issue-receipts", // cmd trait reference GNUNET_TIME_get_current_year (), diff --git a/src/testing/testing_api_cmd_issue_receipts.c b/src/testing/testing_api_cmd_issue_receipts.c @@ -192,6 +192,11 @@ issue_receipts_status_cb (struct StatusState *ss, TALER_TESTING_interpreter_fail (ss->is); return; } + if (MHD_HTTP_OK != biresp->hr.http_status) + { + TALER_TESTING_interpreter_next (ss->is); + return; + } { struct DONAU_BlindedDonationUnitSignature *blinded_sigs = biresp->details.ok.blinded_sigs; @@ -566,9 +571,11 @@ cleanup (void *cls, GNUNET_free (ss->blinding_secrets); if (NULL != ss->receipts) { + /* receipts are only signed if the Donau answered 200 */ for (unsigned int i = 0; i < ss->num_bkp; i++) - GNUNET_CRYPTO_unblinded_sig_decref ( - ss->receipts[i].donation_unit_sig.unblinded_sig); + if (NULL != ss->receipts[i].donation_unit_sig.unblinded_sig) + GNUNET_CRYPTO_unblinded_sig_decref ( + ss->receipts[i].donation_unit_sig.unblinded_sig); GNUNET_free (ss->receipts); } if (NULL != ss->bkps)