donau

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

commit ed9e169024d696e4a9c96ec800359ec47232f66f
parent 74388fd3718dc67a7fbf712f6983d71443685b7f
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  7 Aug 2026 00:34:17 +0200

distinguish better with unknown charity on inserting receipt

Diffstat:
Msrc/donau/donau-httpd_post-batch-issue-CHARITY_ID.c | 18+++++++++++++++++-
Msrc/donaudb/do_insert_receipt_issued.c | 6+++++-
Msrc/donaudb/do_insert_receipt_issued.sql | 14++++++++++++++
Msrc/donaudb/test_donaudb.c | 8++++++--
Msrc/include/donau-database/do_insert_receipt_issued.h | 8++++++--
5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c b/src/donau/donau-httpd_post-batch-issue-CHARITY_ID.c @@ -462,6 +462,7 @@ start: enum TALER_ErrorCode batch_sign_ec; enum GNUNET_DB_QueryStatus qs_insert_ir; bool smaller_than_max_per_year = false; + bool charity_unknown = false; for (size_t i = 0; i < num_bkps; i++) { @@ -501,7 +502,8 @@ start: (uint64_t) charity_id, &h_receipts, &receipts_sum, - &smaller_than_max_per_year); + &smaller_than_max_per_year, + &charity_unknown); if (GNUNET_DB_STATUS_SOFT_ERROR != qs_insert_ir) break; } @@ -554,6 +556,20 @@ start: GNUNET_CRYPTO_blinded_sig_decref (du_sigs[i].blinded_sig); goto start; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (charity_unknown) + { + /* The charity was there when we checked at the top of this handler; + a concurrent DELETE /charities/$ID removed it since. */ + 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_NOT_FOUND, + TALER_EC_DONAU_CHARITY_NOT_FOUND, + NULL); + } if (! smaller_than_max_per_year) { GNUNET_break_op (0); diff --git a/src/donaudb/do_insert_receipt_issued.c b/src/donaudb/do_insert_receipt_issued.c @@ -38,7 +38,8 @@ DONAUDB_do_insert_receipt_issued ( uint64_t charity_id, const struct DONAU_DonationReceiptHashP *h_receipt, const struct TALER_Amount *amount_receipts_request, - bool *smaller_than_max_per_year) + bool *smaller_than_max_per_year, + bool *charity_unknown) { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_uint64 (&charity_id), @@ -54,6 +55,8 @@ DONAUDB_do_insert_receipt_issued ( struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_bool ("smaller_than_max_per_year", smaller_than_max_per_year), + GNUNET_PQ_result_spec_bool ("charity_unknown", + charity_unknown), GNUNET_PQ_result_spec_end }; @@ -62,6 +65,7 @@ DONAUDB_do_insert_receipt_issued ( "do_insert_receipt_issued", "SELECT " " out_smaller_than_max_per_year AS smaller_than_max_per_year" + ",out_charity_unknown AS charity_unknown" " FROM do_insert_issued_receipts" "($1,$2,$3,$4,$5);"); diff --git a/src/donaudb/do_insert_receipt_issued.sql b/src/donaudb/do_insert_receipt_issued.sql @@ -22,6 +22,7 @@ CREATE FUNCTION do_insert_issued_receipts ( ,IN in_amount taler_amount -- total amount of the requested receipts ,IN in_year INT4 ,OUT out_smaller_than_max_per_year BOOLEAN + ,OUT out_charity_unknown BOOLEAN ) LANGUAGE plpgsql AS $$ @@ -33,6 +34,9 @@ DECLARE my_year INT4; rolled_over BOOLEAN DEFAULT FALSE; BEGIN + out_charity_unknown = FALSE; + out_smaller_than_max_per_year = FALSE; + -- Get charity values SELECT (chari.receipts_to_date).val @@ -54,6 +58,16 @@ BEGIN -- installed best-effort and DONAUDB_start_read_committed() exists). FOR UPDATE OF chari; + IF NOT FOUND + THEN + -- Without this arm every local stays NULL, every comparison below is + -- NULL (i.e. false), and the function falls through to the final ELSE + -- and answers FALSE -- which the handler reports as "annual limit + -- exceeded" for a charity that does not exist. + out_charity_unknown = TRUE; + RETURN; + END IF; + IF (my_year > in_year) THEN -- server travelled back in time? wild, but diff --git a/src/donaudb/test_donaudb.c b/src/donaudb/test_donaudb.c @@ -191,6 +191,7 @@ issue_receipt (uint64_t charity_id, struct DONAU_BlindedDonationUnitSignature du_sigs[1]; struct DONAU_DonationReceiptHashP h_receipt; struct TALER_Amount amt; + bool charity_unknown; enum GNUNET_DB_QueryStatus qs; RND_BLK (&h_receipt); @@ -205,7 +206,8 @@ issue_receipt (uint64_t charity_id, charity_id, &h_receipt, &amt, - under_limit); + under_limit, + &charity_unknown); GNUNET_CRYPTO_blinded_sig_decref (du_sigs[0].blinded_sig); return qs; } @@ -442,6 +444,7 @@ run (void *cls) struct DONAU_DonationReceiptHashP h_receipt; struct TALER_Amount amount_receipts; bool smaller_than_max_per_year; + bool charity_unknown; struct TALER_DenominationPrivateKey denom_priv; struct TALER_DenominationPublicKey denom_pub; struct DONAU_DonationUnitPublicKey du_pub; @@ -646,7 +649,8 @@ run (void *cls) charity_id, &h_receipt, &amount_receipts, - &smaller_than_max_per_year)); + &smaller_than_max_per_year, + &charity_unknown)); // FIXME // FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != diff --git a/src/include/donau-database/do_insert_receipt_issued.h b/src/include/donau-database/do_insert_receipt_issued.h @@ -34,7 +34,10 @@ * @param charity_id identifier of the charity * @param h_receipt hash of the donation receipt * @param amount_receipts_request donation amount - * @param smaller_than_max_per_year new receipts to day smaller than the max? + * @param[out] smaller_than_max_per_year new receipts to day smaller than the max? + * @param[out] charity_unknown set to true if there is no charity with + * @a charity_id; in that case nothing was written and + * @a smaller_than_max_per_year is meaningless * @return transaction status code */ enum GNUNET_DB_QueryStatus @@ -46,6 +49,7 @@ DONAUDB_do_insert_receipt_issued ( uint64_t charity_id, const struct DONAU_DonationReceiptHashP *h_receipt, const struct TALER_Amount *amount_receipts_request, - bool *smaller_than_max_per_year); + bool *smaller_than_max_per_year, + bool *charity_unknown); #endif