donau

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

commit b81c7f0a9bc4c1b702e3d50a130f58e69fe4783f
parent babe3d0e224d1bcc60965666753516abf05845ce
Author: Matyja Lukas Adam <lukas.matyja@students.bfh.ch>
Date:   Tue, 23 Apr 2024 16:33:14 +0200

[donaudb] finish insert issued receipts

Diffstat:
Msrc/donau/donau-httpd_batch-issue.c | 30+++++++++---------------------
Msrc/donau/donau-httpd_keys.c | 272++++++++++++++++++++++++++++++++++++++++----------------------------------------
Asrc/donaudb/donau_do_amount_specific.sql | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/donaudb/donau_do_save_issue_receipts_request.sql | 48++++++++++++++++++++++++++++++++++++------------
Msrc/donaudb/pg_insert_issued_receipt.c | 24++++++++++++------------
Msrc/donaudb/pg_insert_issued_receipt.h | 16++++++++--------
Msrc/donaudb/procedures.sql.in | 1+
Msrc/include/donaudb_plugin.h | 6+++---
8 files changed, 297 insertions(+), 192 deletions(-)

diff --git a/src/donau/donau-httpd_batch-issue.c b/src/donau/donau-httpd_batch-issue.c @@ -293,7 +293,7 @@ start: GNUNET_JSON_pack_array_steal ("blind_signatures", blind_signatures)); } - /* calculate new receipts to date and check annual limit */ + /* calculate the sum of all receipts */ struct TALER_Amount receipts_sum; GNUNET_assert (GNUNET_OK == @@ -316,25 +316,7 @@ start: &receipts_sum, &dk->value)); } - struct TALER_Amount new_receipts_to_date; - - TALER_amount_add (&new_receipts_to_date, - &receipts_sum, - &charity_meta.receipts_to_date); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "new_receipts_to_date: %lu.%u, receipts_sum: %lu.%u, charity_max_per_year: %lu.%u\n", - new_receipts_to_date.value, new_receipts_to_date.fraction, - receipts_sum.value, - receipts_sum.fraction, charity_meta.max_per_year.value, - charity_meta.max_per_year.fraction); - // new_receipts_to_date has to be smaller or equal as max_per_year - if (0 < TALER_amount_cmp (&new_receipts_to_date, &charity_meta.max_per_year)) - return TALER_MHD_reply_with_error (rc->connection, - MHD_HTTP_BAD_REQUEST, - TALER_EC_DONAU_EXCEEDING_DONATION_LIMIT, - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "calculated the new receipts to date amount\n"); + // struct TALER_Amount new_receipts_to_date; /* sign budis and send the signatures back */ struct DONAU_BlindedDonationUnitSignature du_sigs[num_bkps]; @@ -359,6 +341,7 @@ start: /* save new receipts to date and save receipts Request (blinded signatures, * charity id, amount, hash over bkps) to make it idempotent*/ enum GNUNET_DB_QueryStatus qs_insert_ir; + bool smaller_than_max_per_year = false; qs_insert_ir = DH_plugin->insert_issued_receipt ( DH_plugin->cls, num_bkps, @@ -366,7 +349,7 @@ start: (uint64_t) charity_id, &h_receipts, &receipts_sum, - &new_receipts_to_date); + &smaller_than_max_per_year); switch (qs_insert_ir) { case GNUNET_DB_STATUS_HARD_ERROR: @@ -381,6 +364,11 @@ start: second_time = true; goto start; case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if (!smaller_than_max_per_year) + return TALER_MHD_reply_with_error (rc->connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_DONAU_EXCEEDING_DONATION_LIMIT, + NULL); break; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, diff --git a/src/donau/donau-httpd_keys.c b/src/donau/donau-httpd_keys.c @@ -1293,142 +1293,142 @@ DH_keys_donation_unit_batch_sign ( const struct DONAU_BkpSignData bkps[num_bkps], struct DONAU_BlindedDonationUnitSignature du_sigs[num_bkps]) { - struct DH_KeyStateHandle *ksh; - struct DH_DonationUnitKey *du; - struct TALER_CRYPTO_RsaSignRequest rsrs[num_bkps]; - struct TALER_CRYPTO_CsSignRequest csrs[num_bkps]; - struct TALER_BlindedDenominationSignature rs[num_bkps]; - struct TALER_BlindedDenominationSignature cs[num_bkps]; - unsigned int rsrs_pos = 0; - unsigned int csrs_pos = 0; - enum TALER_ErrorCode ec; - - ksh = DH_keys_get_state (); - if (NULL == ksh) - // FIXME change error code - return TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING; - for (unsigned int i = 0; i<num_bkps; i++) - { - const struct DONAU_DonationUnitHashP *h_du_pub = - bkps[i].h_donation_unit_pub; - const struct DONAU_BlindedUniqueDonorIdentifier *budi = bkps[i].budi; - - du = GNUNET_CONTAINER_multihashmap_get (du_keys, - &h_du_pub->hash); - if (NULL == du) - // FIXME change error code - return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; - if (budi->blinded_message->cipher != - du->donation_unit_pub.bsign_pub_key->cipher) - return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - switch (du->donation_unit_pub.bsign_pub_key->cipher) - { - case GNUNET_CRYPTO_BSA_RSA: - /* See DONAU_donation_unit_pub_hash: we guarantee that these - hashes are equivalent! */ - rsrs[rsrs_pos].h_rsa - = (const struct TALER_RsaPubHashP *) &du->h_donation_unit_pub; - rsrs[rsrs_pos].msg - = budi->blinded_message->details.rsa_blinded_message.blinded_msg; - rsrs[rsrs_pos].msg_size - = budi->blinded_message->details.rsa_blinded_message.blinded_msg_size; - rsrs_pos++; - break; - case GNUNET_CRYPTO_BSA_CS: - /* See DONAU_donation_unit_pub_hash: we guarantee that these - hashes are equivalent! */ - csrs[csrs_pos].h_cs - = (const struct TALER_CsPubHashP *) &du->h_donation_unit_pub; - csrs[csrs_pos].blinded_planchet - = &budi->blinded_message->details.cs_blinded_message; - csrs_pos++; - break; - default: - return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; - } - } - - if ( (0 != csrs_pos) && - (0 != rsrs_pos) ) - { - memset (rs, - 0, - sizeof (rs)); - memset (cs, - 0, - sizeof (cs)); - } - ec = TALER_EC_NONE; - if (0 != csrs_pos) - { - ec = TALER_CRYPTO_helper_cs_batch_sign ( - csdh, - csrs_pos, - csrs, - false, // for_melt - cs); - if (TALER_EC_NONE != ec) - { - for (unsigned int i = 0; i<csrs_pos; i++) - { - if (NULL != cs[i].blinded_sig) - { - GNUNET_CRYPTO_blinded_sig_decref (cs[i].blinded_sig); - cs[i].blinded_sig = NULL; - } - } - return ec; - } - // TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_CS] += csrs_pos; - } - if (0 != rsrs_pos) - { - ec = TALER_CRYPTO_helper_rsa_batch_sign ( - rsadh, - rsrs_pos, - rsrs, - rs); - if (TALER_EC_NONE != ec) - { - for (unsigned int i = 0; i<csrs_pos; i++) - { - if (NULL != cs[i].blinded_sig) - { - GNUNET_CRYPTO_blinded_sig_decref (cs[i].blinded_sig); - cs[i].blinded_sig = NULL; - } - } - for (unsigned int i = 0; i<rsrs_pos; i++) - { - if (NULL != rs[i].blinded_sig) - { - GNUNET_CRYPTO_blinded_sig_decref (rs[i].blinded_sig); - rs[i].blinded_sig = NULL; - } - } - return ec; - } - // TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_RSA] += rsrs_pos; - } - - rsrs_pos = 0; - csrs_pos = 0; - for (unsigned int i = 0; i<num_bkps; i++) - { - const struct DONAU_BlindedUniqueDonorIdentifier *budi = bkps[i].budi; - - switch (budi->blinded_message->cipher) - { - case GNUNET_CRYPTO_BSA_RSA: - du_sigs[i].blinded_sig = rs[rsrs_pos++].blinded_sig; - break; - case GNUNET_CRYPTO_BSA_CS: - du_sigs[i].blinded_sig = cs[csrs_pos++].blinded_sig; - break; - default: - GNUNET_assert (0); - } - } + // struct DH_KeyStateHandle *ksh; + // struct DH_DonationUnitKey *du; + // struct TALER_CRYPTO_RsaSignRequest rsrs[num_bkps]; + // struct TALER_CRYPTO_CsSignRequest csrs[num_bkps]; + // struct TALER_BlindedDenominationSignature rs[num_bkps]; + // struct TALER_BlindedDenominationSignature cs[num_bkps]; + // unsigned int rsrs_pos = 0; + // unsigned int csrs_pos = 0; + // enum TALER_ErrorCode ec; + + // ksh = DH_keys_get_state (); + // if (NULL == ksh) + // // FIXME change error code + // return TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING; + // for (unsigned int i = 0; i<num_bkps; i++) + // { + // const struct DONAU_DonationUnitHashP *h_du_pub = + // bkps[i].h_donation_unit_pub; + // const struct DONAU_BlindedUniqueDonorIdentifier *budi = bkps[i].budi; + + // du = GNUNET_CONTAINER_multihashmap_get (du_keys, + // &h_du_pub->hash); + // if (NULL == du) + // // FIXME change error code + // return TALER_EC_EXCHANGE_GENERIC_DENOMINATION_KEY_UNKNOWN; + // if (budi->blinded_message->cipher != + // du->donation_unit_pub.bsign_pub_key->cipher) + // return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + // switch (du->donation_unit_pub.bsign_pub_key->cipher) + // { + // case GNUNET_CRYPTO_BSA_RSA: + // /* See DONAU_donation_unit_pub_hash: we guarantee that these + // hashes are equivalent! */ + // rsrs[rsrs_pos].h_rsa + // = (const struct TALER_RsaPubHashP *) &du->h_donation_unit_pub; + // rsrs[rsrs_pos].msg + // = budi->blinded_message->details.rsa_blinded_message.blinded_msg; + // rsrs[rsrs_pos].msg_size + // = budi->blinded_message->details.rsa_blinded_message.blinded_msg_size; + // rsrs_pos++; + // break; + // case GNUNET_CRYPTO_BSA_CS: + // /* See DONAU_donation_unit_pub_hash: we guarantee that these + // hashes are equivalent! */ + // csrs[csrs_pos].h_cs + // = (const struct TALER_CsPubHashP *) &du->h_donation_unit_pub; + // csrs[csrs_pos].blinded_planchet + // = &budi->blinded_message->details.cs_blinded_message; + // csrs_pos++; + // break; + // default: + // return TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE; + // } + // } + + // if ( (0 != csrs_pos) && + // (0 != rsrs_pos) ) + // { + // memset (rs, + // 0, + // sizeof (rs)); + // memset (cs, + // 0, + // sizeof (cs)); + // } + // ec = TALER_EC_NONE; + // if (0 != csrs_pos) + // { + // ec = TALER_CRYPTO_helper_cs_batch_sign ( + // csdh, + // csrs_pos, + // csrs, + // false, // for_melt + // cs); + // if (TALER_EC_NONE != ec) + // { + // for (unsigned int i = 0; i<csrs_pos; i++) + // { + // if (NULL != cs[i].blinded_sig) + // { + // GNUNET_CRYPTO_blinded_sig_decref (cs[i].blinded_sig); + // cs[i].blinded_sig = NULL; + // } + // } + // return ec; + // } + // // TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_CS] += csrs_pos; + // } + // if (0 != rsrs_pos) + // { + // ec = TALER_CRYPTO_helper_rsa_batch_sign ( + // rsadh, + // rsrs_pos, + // rsrs, + // rs); + // if (TALER_EC_NONE != ec) + // { + // for (unsigned int i = 0; i<csrs_pos; i++) + // { + // if (NULL != cs[i].blinded_sig) + // { + // GNUNET_CRYPTO_blinded_sig_decref (cs[i].blinded_sig); + // cs[i].blinded_sig = NULL; + // } + // } + // for (unsigned int i = 0; i<rsrs_pos; i++) + // { + // if (NULL != rs[i].blinded_sig) + // { + // GNUNET_CRYPTO_blinded_sig_decref (rs[i].blinded_sig); + // rs[i].blinded_sig = NULL; + // } + // } + // return ec; + // } + // // TEH_METRICS_num_signatures[TEH_MT_SIGNATURE_RSA] += rsrs_pos; + // } + + // rsrs_pos = 0; + // csrs_pos = 0; + // for (unsigned int i = 0; i<num_bkps; i++) + // { + // const struct DONAU_BlindedUniqueDonorIdentifier *budi = bkps[i].budi; + + // switch (budi->blinded_message->cipher) + // { + // case GNUNET_CRYPTO_BSA_RSA: + // du_sigs[i].blinded_sig = rs[rsrs_pos++].blinded_sig; + // break; + // case GNUNET_CRYPTO_BSA_CS: + // du_sigs[i].blinded_sig = cs[csrs_pos++].blinded_sig; + // break; + // default: + // GNUNET_assert (0); + // } + // } return TALER_EC_NONE; } diff --git a/src/donaudb/donau_do_amount_specific.sql b/src/donaudb/donau_do_amount_specific.sql @@ -0,0 +1,92 @@ +-- +-- This file is part of TALER +-- Copyright (C) 2014--2022 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 +-- Foundation; either version 3, or (at your option) any later version. +-- +-- TALER is distributed in the hope that it will be useful, but WITHOUT ANY +-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +-- A PARTICULAR PURPOSE. See the GNU General Public License for more details. +-- +-- You should have received a copy of the GNU General Public License along with +-- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +-- + +-------------------------------------------------------------- +-- Taler amounts and helper functions +------------------------------------------------------------- + +CREATE OR REPLACE FUNCTION amount_normalize( + IN amount taler_amount + ,OUT normalized taler_amount +) +LANGUAGE plpgsql +AS $$ +BEGIN + normalized.val = amount.val + amount.frac / 100000000; + normalized.frac = amount.frac % 100000000; +END $$; + +COMMENT ON FUNCTION amount_normalize + IS 'Returns the normalized amount by adding to the .val the value of (.frac / 100000000) and removing the modulus 100000000 from .frac.'; + +CREATE OR REPLACE FUNCTION amount_add( + IN a taler_amount + ,IN b taler_amount + ,OUT sum taler_amount +) +LANGUAGE plpgsql +AS $$ +BEGIN + sum = (a.val + b.val, a.frac + b.frac); + SELECT * FROM amount_normalize(sum) INTO sum; + + IF (sum.val > (1<<52)) + THEN + RAISE EXCEPTION 'addition overflow'; + END IF; +END $$; + +COMMENT ON FUNCTION amount_add + IS 'Returns the normalized sum of two amounts. It raises an exception when the resulting .val is larger than 2^52'; + +CREATE OR REPLACE FUNCTION amount_left_minus_right( + IN l taler_amount + ,IN r taler_amount + ,OUT diff taler_amount + ,OUT ok BOOLEAN +) +LANGUAGE plpgsql +AS $$ +BEGIN + +IF (l.val > r.val) +THEN + ok = TRUE; + IF (l.frac >= r.frac) + THEN + diff.val = l.val - r.val; + diff.frac = l.frac - r.frac; + ELSE + diff.val = l.val - r.val - 1; + diff.frac = l.frac + 100000000 - r.frac; + END IF; +ELSE + IF (l.val = r.val) AND (l.frac >= r.frac) + THEN + diff.val = 0; + diff.frac = l.frac - r.frac; + ok = TRUE; + ELSE + diff = (-1, -1); + ok = FALSE; + END IF; +END IF; + +RETURN; +END $$; + +COMMENT ON FUNCTION amount_left_minus_right + IS 'Subtracts the right amount from the left and returns the difference and TRUE, if the left amount is larger than the right, or an invalid amount and FALSE otherwise.'; diff --git a/src/donaudb/donau_do_save_issue_receipts_request.sql b/src/donaudb/donau_do_save_issue_receipts_request.sql @@ -14,25 +14,49 @@ -- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> -- -CREATE OR REPLACE FUNCTION transaction_save_issue_receipts_request( - IN in_charity_id BIGINT -- charity id which made the issue receitps request +CREATE OR REPLACE FUNCTION transaction_save_issue_receipts_request ( + IN in_charity_id BIGINT -- charity id which made the issue receitps request --,IN in_blinded_sig BYTEA[] -- blinded signatures ,IN in_receipt_hash BYTEA -- hash over all budi key pairs (primary key) ,IN in_amount taler_amount -- total amount of the requested receipts - ,IN in_new_total_amount taler_amount -- new total amount of a charity - ,OUT out_receipt_id BIGINT + ,OUT out_smaller_than_max_per_year BOOLEAN ) LANGUAGE plpgsql AS $$ +DECLARE + new_receipts_to_date taler_amount; + may_per_year taler_amount; + tmp taler_amount; BEGIN --- Update table charities -UPDATE charities SET receipts_to_date = in_new_total_amount; --- Insert into the table receipts_issued -INSERT INTO receipts_issued (/*blinded_sig,*/ charity_id, receipt_hash, amount) -VALUES (/*in_blinded_sig,*/ in_charity_id, in_receipt_hash, in_amount); --RETURNING receipt_id INTO out_receipt_id; --- Get the receipts id --- SELECT receipt_id INTO out_receipt_id SELECT WHERE receipt_hash=in_receipts_hash FROM receipts_issued ; --- Commit the transaction if everything is successful + -- Get charity values + SELECT + (chari.receipts_to_date).val + ,(chari.receipts_to_date).frac + ,(chari.max_per_year).val + ,(chari.max_per_year).frac + INTO + new_receipts_to_date.val + ,new_receipts_to_date.frac + ,may_per_year.val + ,may_per_year.frac + FROM charities chari + WHERE charity_id=in_charity_id; + -- calculate sum of the recent amount of receipts and the issued amount + SELECT * FROM amount_add(new_receipts_to_date, in_amount) INTO new_receipts_to_date; + -- check if the new receipts to date is below or equal the limit for the charity + IF (may_per_year.val > new_receipts_to_date.val) + OR (may_per_year.val = new_receipts_to_date.val) + AND (may_per_year.frac >= new_receipts_to_date.frac) + THEN + out_smaller_than_max_per_year=TRUE; + UPDATE charities + SET receipts_to_date=in_amount + WHERE charity_id=in_charity_id; + INSERT INTO receipts_issued (/*blinded_sig,*/ charity_id, receipt_hash, amount) + VALUES (/*in_blinded_sig,*/ in_charity_id, in_receipt_hash, in_amount); + ELSE + out_smaller_than_max_per_year=FALSE; + END IF; END $$; COMMIT; diff --git a/src/donaudb/pg_insert_issued_receipt.c b/src/donaudb/pg_insert_issued_receipt.c @@ -31,19 +31,18 @@ enum GNUNET_DB_QueryStatus DH_PG_insert_issued_receipt ( - void *cls, - const size_t num_blinded_sig, - const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], - const uint64_t charity_id, - const struct DONAU_DonationReceiptHashP *h_receipt, - const struct TALER_Amount *amount_receipts_request, - const struct TALER_Amount *charity_new_amount) + void *cls, + const size_t num_blinded_sig, + const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], + const uint64_t charity_id, + const struct DONAU_DonationReceiptHashP *h_receipt, + const struct TALER_Amount *amount_receipts_request, + bool *smaller_than_max_per_year) { struct PostgresClosure *pc = cls; - uint64_t *receipt_id = 0; struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_uint64 ("receipt_id", receipt_id), + GNUNET_PQ_result_spec_bool ("smaller_than_max_per_year", smaller_than_max_per_year), GNUNET_PQ_result_spec_end }; @@ -54,7 +53,6 @@ DH_PG_insert_issued_receipt ( GNUNET_PQ_query_param_auto_from_type (&h_receipt->hash), TALER_PQ_query_param_amount (pc->conn, amount_receipts_request), - TALER_PQ_query_param_amount (pc->conn, charity_new_amount), GNUNET_PQ_query_param_end }; @@ -63,13 +61,15 @@ DH_PG_insert_issued_receipt ( PREPARE (pc, "insert_issued_receipts_request", "SELECT " - " out_receipt_id AS receipt_id" + " out_smaller_than_max_per_year AS smaller_than_max_per_year" " FROM transaction_save_issue_receipts_request" - "($1,$2,$3,$4);"); + "($1,$2,$3);"); qs = GNUNET_PQ_eval_prepared_singleton_select (pc->conn, "insert_issued_receipts_request", params, rs); GNUNET_PQ_cleanup_query_params_closures (params); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Is the new receipts_to_day smaller than the max_per_year (1 = true): %d\n", (*smaller_than_max_per_year)); return qs; } diff --git a/src/donaudb/pg_insert_issued_receipt.h b/src/donaudb/pg_insert_issued_receipt.h @@ -34,18 +34,18 @@ * @param charity_id identifier of the charity * @param h_receipt hash of the donation receipt * @param amount_receipts_request donation amount - * @param charity_new_amount new current receipts amount of the charity + * @param smaller_than_max_per_year new receipts to day smaller than the max? * @return transaction status code */ enum GNUNET_DB_QueryStatus DH_PG_insert_issued_receipt ( - void *cls, - const size_t num_blinded_sig, - const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], - const uint64_t charity_id, - const struct DONAU_DonationReceiptHashP *h_receipt, - const struct TALER_Amount *amount_receipts_request, - const struct TALER_Amount *charity_new_amount + void *cls, + const size_t num_blinded_sig, + const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], + const uint64_t charity_id, + const struct DONAU_DonationReceiptHashP *h_receipt, + const struct TALER_Amount *amount_receipts_request, + bool *smaller_than_max_per_year ); #endif diff --git a/src/donaudb/procedures.sql.in b/src/donaudb/procedures.sql.in @@ -19,6 +19,7 @@ BEGIN; SET search_path TO donau; #include "donau_do_gc.sql" +#include "donau_do_amount_specific.sql" #include "donau_do_save_issue_receipts_request.sql" COMMIT; diff --git a/src/include/donaudb_plugin.h b/src/include/donaudb_plugin.h @@ -502,18 +502,18 @@ struct DONAUDB_Plugin * @param charity_id identifier of the charity * @param h_receipt hash of the donation receipt * @param amount_receipts_request donation amount - * @param charity_new_amount new current receipts amount of the charity + * @param smaller_than_max_per_year new receipts to day smaller than the max? * @return transaction status code */ enum GNUNET_DB_QueryStatus (*insert_issued_receipt)( void *cls, const size_t num_blinded_sig, - const struct DONAU_BlindedDonationUnitSignature *signatures, + const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], const uint64_t charity_id, const struct DONAU_DonationReceiptHashP *h_receipt, const struct TALER_Amount *amount_receipts_request, - const struct TALER_Amount *charity_new_amount); + bool *smaller_than_max_per_year); /** * Insert submitted donation receipt from the donor.