[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-donau] branch master updated: cleanup
From: |
gnunet |
Subject: |
[taler-donau] branch master updated: cleanup |
Date: |
Tue, 02 Jan 2024 15:29:52 +0100 |
This is an automated email from the git hooks/post-receive script.
johannes-casaburi pushed a commit to branch master
in repository donau.
The following commit(s) were added to refs/heads/master by this push:
new 93ff6fd cleanup
93ff6fd is described below
commit 93ff6fdeb348db00218a8540441afa627ef61b96
Author: Casaburi Johannes <johannes.casaburi@students.bfh.ch>
AuthorDate: Tue Jan 2 15:29:13 2024 +0100
cleanup
---
src/donau/Makefile.am | 4 +-
src/donau/donau-httpd.c | 2 +-
src/donau/donau-httpd.h | 10 +-
src/donau/donau-httpd_batch-issue_receipts.c | 930 ---------------
src/donau/donau-httpd_batch-issue_receipts.h | 48 -
src/donau/donau-httpd_charities_close.c | 448 -------
src/donau/donau-httpd_charities_close.h | 41 -
src/donau/donau-httpd_common_submit_receipts.c | 267 -----
src/donau/donau-httpd_common_submit_receipts.h | 130 ---
src/donau/donau-httpd_config.c | 5 +-
src/donau/donau-httpd_db.c | 55 -
src/donau/donau-httpd_issue_receipts.c | 700 -----------
src/donau/donau-httpd_issue_receipts.h | 47 -
src/donau/donau-httpd_keys.c | 1478 +-----------------------
src/donau/donau-httpd_responses.c | 560 ---------
src/donau/donau-httpd_responses.h | 201 ----
src/donau/donau-httpd_submit_receipts_get.c | 519 ---------
src/donau/donau-httpd_submit_receipts_get.h | 50 -
src/donau/donau-httpd_terms.c | 81 --
src/donau/donau-httpd_terms.h | 65 --
src/donaudb/pg_add_donation_unit_key.h | 3 +-
src/lib/donau_api_batch_issue_receipts.c | 456 --------
src/lib/donau_api_batch_issue_receipts2.c | 555 ---------
src/lib/donau_api_batch_submit_receipts.c | 779 -------------
src/lib/donau_api_handle.c | 51 -
src/lib/donau_api_issue_receipts.c | 99 --
src/testing/testing_api_misc.c | 2 -
27 files changed, 7 insertions(+), 7579 deletions(-)
diff --git a/src/donau/Makefile.am b/src/donau/Makefile.am
index 7dda663..59f07c0 100644
--- a/src/donau/Makefile.am
+++ b/src/donau/Makefile.am
@@ -20,9 +20,7 @@ bin_PROGRAMS = \
donau-httpd
donau_httpd_SOURCES = \
- donau-httpd.c donau-httpd.h \
- donau-httpd_responses.c donau-httpd_responses.h \
- donau-httpd_terms.c donau-httpd_terms.h
+ donau-httpd.c donau-httpd.h
donau_httpd_LDADD = \
$(LIBGCRYPT_LIBS) \
diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c
index da833b2..853af83 100644
--- a/src/donau/donau-httpd.c
+++ b/src/donau/donau-httpd.c
@@ -29,11 +29,11 @@
#include <limits.h>
#include "taler/taler_templating_lib.h"
#include "taler/taler_mhd_lib.h"
-#include "donau-httpd_terms.h"
#include "donaudb_lib.h"
#include "donaudb_plugin.h"
#include <gnunet/gnunet_mhd_compat.h>
#include "donau_util.h"
+#include "donau-httpd.h"
/**
* Backlog for listen operation on unix domain sockets.
diff --git a/src/donau/donau-httpd.h b/src/donau/donau-httpd.h
index 269c4b4..e6b1bd1 100644
--- a/src/donau/donau-httpd.h
+++ b/src/donau/donau-httpd.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software
@@ -14,7 +14,7 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
- * @file taler-donau-httpd.h
+ * @file donau-httpd.h
* @brief Global declarations for the donau
* @author Florian Dold
* @author Benedikt Mueller
@@ -69,12 +69,6 @@ extern int DH_check_invariants_flag;
*/
extern bool DH_suicide;
-/**
- * Master public key (according to the
- * configuration in the donau directory).
- */
-extern struct TALER_MasterPublicKeyP DH_master_public_key;
-
/**
* Key used to encrypt KYC attribute data in our database.
*/
diff --git a/src/donau/donau-httpd_batch-issue_receipts.c
b/src/donau/donau-httpd_batch-issue_receipts.c
deleted file mode 100644
index 27a4658..0000000
--- a/src/donau/donau-httpd_batch-issue_receipts.c
+++ /dev/null
@@ -1,930 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General
- Public License along with TALER; see the file COPYING. If not,
- see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file donau-httpd_batch-issue_receipts.c
- * @brief Handle /reserves/$RESERVE_PUB/batch-withdraw requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include "taler-donau-httpd.h"
-#include "taler/taler_json_lib.h"
-#include "taler_kyclogic_lib.h"
-#include "taler/taler_mhd_lib.h"
-#include "taler-donau-httpd_batch-withdraw.h"
-#include "taler-donau-httpd_responses.h"
-#include "taler-donau-httpd_keys.h"
-#include <taler/taler_util.h>
-
-
-/**
- * Information per planchet in the batch.
- */
-struct PlanchetContext
-{
-
- /**
- * Hash of the (blinded) message to be signed by the Donau.
- */
- struct TALER_BlindedCoinHashP h_coin_envelope;
-
- /**
- * Value of the coin being donaud (matching the denomination key)
- * plus the transaction fee. We include this in what is being
- * signed so that we can verify a reserve's remaining total balance
- * without needing to access the respective denomination key
- * information each time.
- */
- struct TALER_Amount amount_with_fee;
-
- /**
- * Blinded planchet.
- */
- struct TALER_BlindedPlanchet blinded_planchet;
-
- /**
- * Set to the resulting signed coin data to be returned to the client.
- */
- struct DONAUDB_CollectableBlindcoin collectable;
-
-};
-
-/**
- * Context for #batch_withdraw_transaction.
- */
-struct BatchWithdrawContext
-{
-
- /**
- * Public key of the reserv.
- */
- const struct TALER_ReservePublicKeyP *reserve_pub;
-
- /**
- * request context
- */
- const struct DH_RequestContext *rc;
-
- /**
- * KYC status of the reserve used for the operation.
- */
- struct DONAUDB_KycStatus kyc;
-
- /**
- * Array of @e planchets_length planchets we are processing.
- */
- struct PlanchetContext *planchets;
-
- /**
- * Hash of the payto-URI representing the reserve
- * from which we are withdrawing.
- */
- struct TALER_PaytoHashP h_payto;
-
- /**
- * Current time for the DB transaction.
- */
- struct GNUNET_TIME_Timestamp now;
-
- /**
- * Total amount from all coins with fees.
- */
- struct TALER_Amount batch_total;
-
- /**
- * Length of the @e planchets array.
- */
- unsigned int planchets_length;
-
- /**
- * AML decision, #TALER_AML_NORMAL if we may proceed.
- */
- enum TALER_AmlDecisionState aml_decision;
-
-};
-
-
-/**
- * Function called to iterate over KYC-relevant
- * transaction amounts for a particular time range.
- * Called within a database transaction, so must
- * not start a new one.
- *
- * @param cls closure, identifies the event type and
- * account to iterate over events for
- * @param limit maximum time-range for which events
- * should be fetched (timestamp in the past)
- * @param cb function to call on each event found,
- * events must be returned in reverse chronological
- * order
- * @param cb_cls closure for @a cb
- */
-static void
-batch_withdraw_amount_cb (void *cls,
- struct GNUNET_TIME_Absolute limit,
- DONAUDB_KycAmountCallback cb,
- void *cb_cls)
-{
- struct BatchWithdrawContext *wc = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- if (GNUNET_OK !=
- cb (cb_cls,
- &wc->batch_total,
- wc->now.abs_time))
- return;
- qs = DH_plugin->select_withdraw_amounts_for_kyc_check (
- DH_plugin->cls,
- &wc->h_payto,
- limit,
- cb,
- cb_cls);
- GNUNET_break (qs >= 0);
-}
-
-
-/**
- * Function called on each @a amount that was found to
- * be relevant for the AML check as it was merged into
- * the reserve.
- *
- * @param cls `struct TALER_Amount *` to total up the amounts
- * @param amount encountered transaction amount
- * @param date when was the amount encountered
- * @return #GNUNET_OK to continue to iterate,
- * #GNUNET_NO to abort iteration
- * #GNUNET_SYSERR on internal error (also abort itaration)
- */
-static enum GNUNET_GenericReturnValue
-aml_amount_cb (
- void *cls,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute date)
-{
- struct TALER_Amount *total = cls;
-
- GNUNET_assert (0 <=
- TALER_amount_add (total,
- total,
- amount));
- return GNUNET_OK;
-}
-
-
-/**
- * Generates our final (successful) response.
- *
- * @param rc request context
- * @param wc operation context
- * @return MHD queue status
- */
-static MHD_RESULT
-generate_reply_success (const struct DH_RequestContext *rc,
- const struct BatchWithdrawContext *wc)
-{
- json_t *sigs;
-
- if (! wc->kyc.ok)
- {
- /* KYC required */
- return DH_RESPONSE_reply_kyc_required (rc->connection,
- &wc->h_payto,
- &wc->kyc);
- }
- if (TALER_AML_NORMAL != wc->aml_decision)
- return DH_RESPONSE_reply_aml_blocked (rc->connection,
- wc->aml_decision);
-
- sigs = json_array ();
- GNUNET_assert (NULL != sigs);
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
-
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- sigs,
- GNUNET_JSON_PACK (
- TALER_JSON_pack_blinded_denom_sig (
- "ev_sig",
- &pc->collectable.sig))));
- }
- DH_METRICS_batch_withdraw_num_coins += wc->planchets_length;
- return TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_array_steal ("ev_sigs",
- sigs));
-}
-
-
-/**
- * Check if the @a wc is replayed and we already have an
- * answer. If so, replay the existing answer and return the
- * HTTP response.
- *
- * @param wc parsed request data
- * @param[out] mret HTTP status, set if we return true
- * @return true if the request is idempotent with an existing request
- * false if we did not find the request in the DB and did not set @a mret
- */
-static bool
-check_request_idempotent (const struct BatchWithdrawContext *wc,
- MHD_RESULT *mret)
-{
- const struct DH_RequestContext *rc = wc->rc;
-
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
- enum GNUNET_DB_QueryStatus qs;
-
- qs = DH_plugin->get_withdraw_info (DH_plugin->cls,
- &pc->h_coin_envelope,
- &pc->collectable);
- if (0 > qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mret = TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "get_withdraw_info");
- return true; /* well, kind-of */
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- return false;
- }
- /* generate idempotent reply */
- DH_METRICS_num_requests[DH_MT_REQUEST_IDEMPOTENT_BATCH_WITHDRAW]++;
- *mret = generate_reply_success (rc,
- wc);
- return true;
-}
-
-
-/**
- * Function implementing withdraw transaction. Runs the
- * transaction logic; IF it returns a non-error code, the transaction
- * logic MUST NOT queue a MHD response. IF it returns an hard error,
- * the transaction logic MUST queue a MHD response and set @a mhd_ret.
- * IF it returns the soft error code, the function MAY be called again
- * to retry and MUST not queue a MHD response.
- *
- * Note that "wc->collectable.sig" is set before entering this function as we
- * signed before entering the transaction.
- *
- * @param cls a `struct BatchWithdrawContext *`
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-batch_withdraw_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct BatchWithdrawContext *wc = cls;
- uint64_t ruuid;
- enum GNUNET_DB_QueryStatus qs;
- bool found = false;
- bool balance_ok = false;
- bool age_ok = false;
- uint16_t allowed_maximum_age = 0;
- char *kyc_required;
- struct TALER_PaytoHashP reserve_h_payto;
-
- wc->now = GNUNET_TIME_timestamp_get ();
- /* Do AML check: compute total merged amount and check
- against applicable AML threshold */
- {
- char *reserve_payto;
-
- reserve_payto = TALER_reserve_make_payto (DH_base_url,
- wc->reserve_pub);
- TALER_payto_hash (reserve_payto,
- &reserve_h_payto);
- GNUNET_free (reserve_payto);
- }
- {
- struct TALER_Amount merge_amount;
- struct TALER_Amount threshold;
- struct GNUNET_TIME_Absolute now_minus_one_month;
-
- now_minus_one_month
- = GNUNET_TIME_absolute_subtract (wc->now.abs_time,
- GNUNET_TIME_UNIT_MONTHS);
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (DH_currency,
- &merge_amount));
- qs = DH_plugin->select_merge_amounts_for_kyc_check (DH_plugin->cls,
- &reserve_h_payto,
- now_minus_one_month,
- &aml_amount_cb,
- &merge_amount);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
-
"select_merge_amounts_for_kyc_check");
- return qs;
- }
- qs = DH_plugin->select_aml_threshold (DH_plugin->cls,
- &reserve_h_payto,
- &wc->aml_decision,
- &wc->kyc,
- &threshold);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "select_aml_threshold");
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- threshold = DH_aml_threshold; /* use default */
- wc->aml_decision = TALER_AML_NORMAL;
- }
-
- switch (wc->aml_decision)
- {
- case TALER_AML_NORMAL:
- if (0 >= TALER_amount_cmp (&merge_amount,
- &threshold))
- {
- /* merge_amount <= threshold, continue withdraw below */
- break;
- }
- wc->aml_decision = TALER_AML_PENDING;
- qs = DH_plugin->trigger_aml_process (DH_plugin->cls,
- &reserve_h_payto,
- &merge_amount);
- if (qs <= 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
-
MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_STORE_FAILED,
- "trigger_aml_process");
- return qs;
- }
- return qs;
- case TALER_AML_PENDING:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "AML already pending, doing nothing\n");
- return qs;
- case TALER_AML_FROZEN:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Account frozen, doing nothing\n");
- return qs;
- }
- }
-
- /* Check if the money came from a wire transfer */
- qs = DH_plugin->reserves_get_origin (DH_plugin->cls,
- wc->reserve_pub,
- &wc->h_payto);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "reserves_get_origin");
- return qs;
- }
- /* If no results, reserve was created by merge, in which case no KYC check
- is required as the merge already did that. */
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- qs = TALER_KYCLOGIC_kyc_test_required (
- TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW,
- &wc->h_payto,
- DH_plugin->select_satisfied_kyc_processes,
- DH_plugin->cls,
- &batch_withdraw_amount_cb,
- wc,
- &kyc_required);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "kyc_test_required");
- return qs;
- }
- if (NULL != kyc_required)
- {
- /* insert KYC requirement into DB! */
- wc->kyc.ok = false;
- qs = DH_plugin->insert_kyc_requirement_for_account (
- DH_plugin->cls,
- kyc_required,
- &wc->h_payto,
- wc->reserve_pub,
- &wc->kyc.requirement_row);
- GNUNET_free (kyc_required);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
-
MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_STORE_FAILED,
-
"insert_kyc_requirement_for_account");
- }
- return qs;
- }
- }
- wc->kyc.ok = true;
-
- qs = DH_plugin->do_batch_withdraw (DH_plugin->cls,
- wc->now,
- wc->reserve_pub,
- &wc->batch_total,
- DH_age_restriction_enabled,
- &found,
- &balance_ok,
- &age_ok,
- &allowed_maximum_age,
- &ruuid);
- if (0 > qs)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "update_reserve_batch_withdraw");
- }
- return qs;
- }
- if (! found)
- {
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
-
TALER_EC_DONAU_GENERIC_RESERVE_UNKNOWN,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- if (! age_ok)
- {
- /* We respond with the lowest age in the corresponding age group
- * of the required age */
- uint16_t lowest_age = TALER_get_lowest_age (
- &DH_age_restriction_config.mask,
- allowed_maximum_age);
-
- DH_plugin->rollback (DH_plugin->cls);
- *mhd_ret = DH_RESPONSE_reply_reserve_age_restriction_required (
- connection,
- lowest_age);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- if (! balance_ok)
- {
- DH_plugin->rollback (DH_plugin->cls);
- *mhd_ret = DH_RESPONSE_reply_reserve_insufficient_balance (
- connection,
- TALER_EC_DONAU_WITHDRAW_INSUFFICIENT_FUNDS,
- &wc->batch_total,
- wc->reserve_pub);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- /* Add information about each planchet in the batch */
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
- const struct TALER_BlindedPlanchet *bp = &pc->blinded_planchet;
- const struct TALER_CsNonce *nonce;
- bool denom_unknown = true;
- bool conflict = true;
- bool nonce_reuse = true;
-
- nonce = (TALER_DENOMINATION_CS == bp->cipher)
- ? &bp->details.cs_blinded_planchet.nonce
- : NULL;
- qs = DH_plugin->do_batch_withdraw_insert (DH_plugin->cls,
- nonce,
- &pc->collectable,
- wc->now,
- ruuid,
- &denom_unknown,
- &conflict,
- &nonce_reuse);
- if (0 > qs)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "do_withdraw");
- return qs;
- }
- if (denom_unknown)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
- (conflict) )
- {
- if (! check_request_idempotent (wc,
- mhd_ret))
- {
- /* We do not support *some* of the coins of the request being
- idempotent while others being fresh. */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Idempotent coin in batch, not allowed. Aborting.\n");
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
-
TALER_EC_DONAU_WITHDRAW_BATCH_IDEMPOTENT_PLANCHET,
- NULL);
- }
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (nonce_reuse)
- {
- GNUNET_break_op (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_WITHDRAW_NONCE_REUSE,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- }
- DH_METRICS_num_success[DH_MT_SUCCESS_BATCH_WITHDRAW]++;
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
-}
-
-
-/**
- * The request was parsed successfully. Prepare
- * our side for the main DB transaction.
- *
- * @param rc request details
- * @param wc storage for request processing
- * @return MHD result for the @a rc
- */
-static MHD_RESULT
-prepare_transaction (const struct DH_RequestContext *rc,
- struct BatchWithdrawContext *wc)
-{
- struct DH_CoinSignData csds[wc->planchets_length];
- struct TALER_BlindedDenominationSignature bss[wc->planchets_length];
-
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
-
- csds[i].h_denom_pub = &pc->collectable.denom_pub_hash;
- csds[i].bp = &pc->blinded_planchet;
- }
- {
- enum TALER_ErrorCode ec;
-
- ec = DH_keys_denomination_batch_sign (
- csds,
- wc->planchets_length,
- false,
- bss);
- if (TALER_EC_NONE != ec)
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_ec (rc->connection,
- ec,
- NULL);
- }
- }
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
-
- pc->collectable.sig = bss[i];
- }
-
- /* run transaction */
- {
- MHD_RESULT mhd_ret;
-
- if (GNUNET_OK !=
- DH_DB_run_transaction (rc->connection,
- "run batch withdraw",
- DH_MT_REQUEST_WITHDRAW,
- &mhd_ret,
- &batch_withdraw_transaction,
- wc))
- {
- return mhd_ret;
- }
- }
- /* return final positive response */
- return generate_reply_success (rc,
- wc);
-}
-
-
-/**
- * Continue processing the request @a rc by parsing the
- * @a planchets and then running the transaction.
- *
- * @param rc request details
- * @param wc storage for request processing
- * @param planchets array of planchets to parse
- * @return MHD result for the @a rc
- */
-static MHD_RESULT
-parse_planchets (const struct DH_RequestContext *rc,
- struct BatchWithdrawContext *wc,
- const json_t *planchets)
-{
- struct DH_KeyStateHandle *ksh;
- MHD_RESULT mret;
-
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
- struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &pc->collectable.reserve_sig),
- GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
- &pc->collectable.denom_pub_hash),
- TALER_JSON_spec_blinded_planchet ("coin_ev",
- &pc->blinded_planchet),
- GNUNET_JSON_spec_end ()
- };
-
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (rc->connection,
- json_array_get (planchets,
- i),
- ispec);
- if (GNUNET_OK != res)
- return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
- }
- pc->collectable.reserve_pub = *wc->reserve_pub;
- for (unsigned int k = 0; k<i; k++)
- {
- const struct PlanchetContext *kpc = &wc->planchets[k];
-
- if (0 ==
- TALER_blinded_planchet_cmp (&kpc->blinded_planchet,
- &pc->blinded_planchet))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "duplicate planchet");
- }
- }
- }
-
- ksh = DH_keys_get_state ();
- if (NULL == ksh)
- {
- if (! check_request_idempotent (wc,
- &mret))
- {
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_DONAU_GENERIC_KEYS_MISSING,
- NULL);
- }
- return mret;
- }
- for (unsigned int i = 0; i<wc->planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc->planchets[i];
- struct DH_DenominationKey *dk;
-
- dk = DH_keys_denomination_by_hash_from_state (
- ksh,
- &pc->collectable.denom_pub_hash,
- NULL,
- NULL);
-
- if (NULL == dk)
- {
- if (! check_request_idempotent (wc,
- &mret))
- {
- return DH_RESPONSE_reply_unknown_denom_pub_hash (
- rc->connection,
- &pc->collectable.denom_pub_hash);
- }
- return mret;
- }
- if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
- {
- /* This denomination is past the expiration time for withdraws */
- if (! check_request_idempotent (wc,
- &mret))
- {
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &pc->collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_EXPIRED,
- "WITHDRAW");
- }
- return mret;
- }
- if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
- {
- /* This denomination is not yet valid, no need to check
- for idempotency! */
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &pc->collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
- "WITHDRAW");
- }
- if (dk->recoup_possible)
- {
- /* This denomination has been revoked */
- if (! check_request_idempotent (wc,
- &mret))
- {
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &pc->collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_REVOKED,
- "WITHDRAW");
- }
- return mret;
- }
- if (dk->denom_pub.cipher != pc->blinded_planchet.cipher)
- {
- /* denomination cipher and blinded planchet cipher not the same */
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_GENERIC_CIPHER_MISMATCH,
- NULL);
- }
- if (0 >
- TALER_amount_add (&pc->collectable.amount_with_fee,
- &dk->meta.value,
- &dk->meta.fees.withdraw))
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_DONAU_WITHDRAW_AMOUNT_FEE_OVERFLOW,
- NULL);
- }
- if (0 >
- TALER_amount_add (&wc->batch_total,
- &wc->batch_total,
- &pc->collectable.amount_with_fee))
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_DONAU_WITHDRAW_AMOUNT_FEE_OVERFLOW,
- NULL);
- }
-
- if (GNUNET_OK !=
- TALER_coin_ev_hash (&pc->blinded_planchet,
- &pc->collectable.denom_pub_hash,
- &pc->collectable.h_coin_envelope))
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- NULL);
- }
- DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
- if (GNUNET_OK !=
- TALER_wallet_withdraw_verify (&pc->collectable.denom_pub_hash,
- &pc->collectable.amount_with_fee,
- &pc->collectable.h_coin_envelope,
- &pc->collectable.reserve_pub,
- &pc->collectable.reserve_sig))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_WITHDRAW_RESERVE_SIGNATURE_INVALID,
- NULL);
- }
- }
- /* everything parsed */
- return prepare_transaction (rc,
- wc);
-}
-
-
-MHD_RESULT
-DH_handler_batch_withdraw (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root)
-{
- struct BatchWithdrawContext wc = {
- .reserve_pub = reserve_pub,
- .rc = rc
- };
- const json_t *planchets;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("planchets",
- &planchets),
- GNUNET_JSON_spec_end ()
- };
-
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (DH_currency,
- &wc.batch_total));
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (rc->connection,
- root,
- spec);
- if (GNUNET_OK != res)
- return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
- }
- wc.planchets_length = json_array_size (planchets);
- if (0 == wc.planchets_length)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "planchets");
- }
- if (wc.planchets_length > TALER_MAX_FRESH_COINS)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_GENERIC_PARAMETER_MALFORMED,
- "too many planchets");
- }
- {
- struct PlanchetContext splanchets[wc.planchets_length];
- MHD_RESULT ret;
-
- memset (splanchets,
- 0,
- sizeof (splanchets));
- wc.planchets = splanchets;
- ret = parse_planchets (rc,
- &wc,
- planchets);
- /* Clean up */
- for (unsigned int i = 0; i<wc.planchets_length; i++)
- {
- struct PlanchetContext *pc = &wc.planchets[i];
-
- TALER_blinded_planchet_free (&pc->blinded_planchet);
- TALER_blinded_denom_sig_free (&pc->collectable.sig);
- }
- return ret;
- }
-}
-
-
-/* end of donau-httpd_batch-issue_receipts.c */
diff --git a/src/donau/donau-httpd_batch-issue_receipts.h
b/src/donau/donau-httpd_batch-issue_receipts.h
deleted file mode 100644
index 612e39f..0000000
--- a/src/donau/donau-httpd_batch-issue_receipts.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file donau-httpd_batch-issue_receipts.h
- * @brief Handle /reserve/batch-withdraw requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_BATCH_WITHDRAW_H
-#define DONAU_HTTPD_BATCH_WITHDRAW_H
-
-#include <microhttpd.h>
-#include "taler-donau-httpd.h"
-
-
-/**
- * Handle a "/reserves/$RESERVE_PUB/batch-withdraw" request. Parses the batch
of
- * requested "denom_pub" which specifies the key/value of the coin to be
- * withdrawn, and checks that the signature "reserve_sig" makes this a valid
- * withdrawal request from the specified reserve. If so, the envelope with
- * the blinded coin "coin_ev" is passed down to execute the withdrawal
- * operation.
- *
- * @param rc request context
- * @param root uploaded JSON data
- * @param reserve_pub public key of the reserve
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_batch_withdraw (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root);
-
-#endif
diff --git a/src/donau/donau-httpd_charities_close.c
b/src/donau/donau-httpd_charities_close.c
deleted file mode 100644
index 25381f1..0000000
--- a/src/donau/donau-httpd_charities_close.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- 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 Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_reserves_close.c
- * @brief Handle /reserves/$RESERVE_PUB/close requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include "taler_kyclogic_lib.h"
-#include "taler/taler_mhd_lib.h"
-#include "taler/taler_json_lib.h"
-#include "taler_dbevents.h"
-#include "taler-donau-httpd_keys.h"
-#include "taler-donau-httpd_reserves_close.h"
-#include "taler-donau-httpd_responses.h"
-
-
-/**
- * How far do we allow a client's time to be off when
- * checking the request timestamp?
- */
-#define TIMESTAMP_TOLERANCE \
- GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 15)
-
-
-/**
- * Closure for #reserve_close_transaction.
- */
-struct ReserveCloseContext
-{
- /**
- * Public key of the reserve the inquiry is about.
- */
- const struct TALER_ReservePublicKeyP *reserve_pub;
-
- /**
- * Timestamp of the request.
- */
- struct GNUNET_TIME_Timestamp timestamp;
-
- /**
- * Client signature approving the request.
- */
- struct TALER_ReserveSignatureP reserve_sig;
-
- /**
- * Amount that will be wired (after closing fees).
- */
- struct TALER_Amount wire_amount;
-
- /**
- * Current balance of the reserve.
- */
- struct TALER_Amount balance;
-
- /**
- * Where to wire the funds, may be NULL.
- */
- const char *payto_uri;
-
- /**
- * Hash of the @e payto_uri, if given (otherwise zero).
- */
- struct TALER_PaytoHashP h_payto;
-
- /**
- * KYC status for the request.
- */
- struct DONAUDB_KycStatus kyc;
-
- /**
- * Hash of the payto-URI that was used for the KYC decision.
- */
- struct TALER_PaytoHashP kyc_payto;
-
- /**
- * Query status from the amount_it() helper function.
- */
- enum GNUNET_DB_QueryStatus qs;
-};
-
-
-/**
- * Send reserve close to client.
- *
- * @param connection connection to the client
- * @param rhc reserve close to return
- * @return MHD result code
- */
-static MHD_RESULT
-reply_reserve_close_success (struct MHD_Connection *connection,
- const struct ReserveCloseContext *rhc)
-{
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_OK,
- TALER_JSON_pack_amount ("wire_amount",
- &rhc->wire_amount));
-}
-
-
-/**
- * Function called to iterate over KYC-relevant
- * transaction amounts for a particular time range.
- * Called within a database transaction, so must
- * not start a new one.
- *
- * @param cls closure, identifies the event type and
- * account to iterate over events for
- * @param limit maximum time-range for which events
- * should be fetched (timestamp in the past)
- * @param cb function to call on each event found,
- * events must be returned in reverse chronological
- * order
- * @param cb_cls closure for @a cb
- */
-static void
-amount_it (void *cls,
- struct GNUNET_TIME_Absolute limit,
- DONAUDB_KycAmountCallback cb,
- void *cb_cls)
-{
- struct ReserveCloseContext *rcc = cls;
- enum GNUNET_GenericReturnValue ret;
-
- ret = cb (cb_cls,
- &rcc->balance,
- GNUNET_TIME_absolute_get ());
- GNUNET_break (GNUNET_SYSERR != ret);
- if (GNUNET_OK != ret)
- return;
- rcc->qs
- = DH_plugin->iterate_reserve_close_info (
- DH_plugin->cls,
- &rcc->kyc_payto,
- limit,
- cb,
- cb_cls);
-}
-
-
-/**
- * Function implementing /reserves/$RID/close transaction. Given the public
- * key of a reserve, return the associated transaction close. Runs the
- * transaction logic; IF it returns a non-error code, the transaction logic
- * MUST NOT queue a MHD response. IF it returns an hard error, the
- * transaction logic MUST queue a MHD response and set @a mhd_ret. IF it
- * returns the soft error code, the function MAY be called again to retry and
- * MUST not queue a MHD response.
- *
- * @param cls a `struct ReserveCloseContext *`
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!); unused
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-reserve_close_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct ReserveCloseContext *rcc = cls;
- enum GNUNET_DB_QueryStatus qs;
- char *payto_uri = NULL;
- const struct TALER_WireFeeSet *wf;
-
- qs = DH_plugin->select_reserve_close_info (
- DH_plugin->cls,
- rcc->reserve_pub,
- &rcc->balance,
- &payto_uri);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- GNUNET_break (0);
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "select_reserve_close_info");
- return qs;
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return qs;
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_DONAU_GENERIC_RESERVE_UNKNOWN,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- break;
- }
-
- if ( (NULL == rcc->payto_uri) &&
- (NULL == payto_uri) )
- {
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
-
TALER_EC_DONAU_RESERVES_CLOSE_NO_TARGET_ACCOUNT,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- if ( (NULL != rcc->payto_uri) &&
- ( (NULL == payto_uri) ||
- (0 != strcmp (payto_uri,
- rcc->payto_uri)) ) )
- {
- /* KYC check may be needed: we're not returning
- the money to the account that funded the reserve
- in the first place. */
- char *kyc_needed;
-
- TALER_payto_hash (rcc->payto_uri,
- &rcc->kyc_payto);
- rcc->qs = GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- qs = TALER_KYCLOGIC_kyc_test_required (
- TALER_KYCLOGIC_KYC_TRIGGER_RESERVE_CLOSE,
- &rcc->kyc_payto,
- DH_plugin->select_satisfied_kyc_processes,
- DH_plugin->cls,
- &amount_it,
- rcc,
- &kyc_needed);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
- return qs;
- GNUNET_break (0);
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "iterate_reserve_close_info");
- return qs;
- }
- if (rcc->qs < 0)
- {
- if (GNUNET_DB_STATUS_SOFT_ERROR == rcc->qs)
- return rcc->qs;
- GNUNET_break (0);
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "iterate_reserve_close_info");
- return qs;
- }
- if (NULL != kyc_needed)
- {
- rcc->kyc.ok = false;
- qs = DH_plugin->insert_kyc_requirement_for_account (
- DH_plugin->cls,
- kyc_needed,
- &rcc->kyc_payto,
- rcc->reserve_pub,
- &rcc->kyc.requirement_row);
- GNUNET_free (kyc_needed);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- "insert_kyc_requirement_for_account");
- }
- return qs;
- }
- }
-
- rcc->kyc.ok = true;
- if (NULL == rcc->payto_uri)
- rcc->payto_uri = payto_uri;
-
- {
- char *method;
-
- method = TALER_payto_get_method (rcc->payto_uri);
- wf = DH_wire_fees_by_time (rcc->timestamp,
- method);
- if (NULL == wf)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_DONAU_WIRE_FEES_NOT_CONFIGURED,
- method);
- GNUNET_free (method);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_free (method);
- }
-
- if (0 >
- TALER_amount_subtract (&rcc->wire_amount,
- &rcc->balance,
- &wf->closing))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Client attempted to close reserve with insufficient
balance.\n");
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (DH_currency,
- &rcc->wire_amount));
- *mhd_ret = reply_reserve_close_success (connection,
- rcc);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- qs = DH_plugin->insert_close_request (DH_plugin->cls,
- rcc->reserve_pub,
- payto_uri,
- &rcc->reserve_sig,
- rcc->timestamp,
- &rcc->balance,
- &wf->closing);
- GNUNET_free (payto_uri);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "insert_close_request");
- return qs;
- }
- if (qs <= 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return qs;
- }
- return qs;
-}
-
-
-MHD_RESULT
-DH_handler_reserves_close (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root)
-{
- struct ReserveCloseContext rcc = {
- .payto_uri = NULL,
- .reserve_pub = reserve_pub
- };
- MHD_RESULT mhd_ret;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_timestamp ("request_timestamp",
- &rcc.timestamp),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("payto_uri",
- &rcc.payto_uri),
- NULL),
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &rcc.reserve_sig),
- GNUNET_JSON_spec_end ()
- };
-
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (rc->connection,
- root,
- spec);
- if (GNUNET_SYSERR == res)
- {
- GNUNET_break (0);
- return MHD_NO; /* hard failure */
- }
- if (GNUNET_NO == res)
- {
- GNUNET_break_op (0);
- return MHD_YES; /* failure */
- }
- }
-
- {
- struct GNUNET_TIME_Timestamp now;
-
- now = GNUNET_TIME_timestamp_get ();
- if (! GNUNET_TIME_absolute_approx_eq (now.abs_time,
- rcc.timestamp.abs_time,
- TIMESTAMP_TOLERANCE))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_DONAU_GENERIC_CLOCK_SKEW,
- NULL);
- }
- }
-
- if (NULL != rcc.payto_uri)
- TALER_payto_hash (rcc.payto_uri,
- &rcc.h_payto);
- if (GNUNET_OK !=
- TALER_wallet_reserve_close_verify (rcc.timestamp,
- &rcc.h_payto,
- reserve_pub,
- &rcc.reserve_sig))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_RESERVES_CLOSE_BAD_SIGNATURE,
- NULL);
- }
-
- if (GNUNET_OK !=
- DH_DB_run_transaction (rc->connection,
- "reserve close",
- DH_MT_REQUEST_OTHER,
- &mhd_ret,
- &reserve_close_transaction,
- &rcc))
- {
- return mhd_ret;
- }
- if (! rcc.kyc.ok)
- return DH_RESPONSE_reply_kyc_required (rc->connection,
- &rcc.kyc_payto,
- &rcc.kyc);
-
- return reply_reserve_close_success (rc->connection,
- &rcc);
-}
-
-
-/* end of taler-donau-httpd_reserves_close.c */
diff --git a/src/donau/donau-httpd_charities_close.h
b/src/donau/donau-httpd_charities_close.h
deleted file mode 100644
index 112e397..0000000
--- a/src/donau/donau-httpd_charities_close.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_reserves_close.h
- * @brief Handle /reserves/$RESERVE_PUB/close requests
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_RESERVES_CLOSE_H
-#define DONAU_HTTPD_RESERVES_CLOSE_H
-
-#include <microhttpd.h>
-#include "taler-donau-httpd.h"
-
-
-/**
- * Handle a POST "/reserves/$RID/close" request.
- *
- * @param rc request context
- * @param reserve_pub public key of the reserve
- * @param root uploaded body from the client
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_reserves_close (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root);
-
-#endif
diff --git a/src/donau/donau-httpd_common_submit_receipts.c
b/src/donau/donau-httpd_common_submit_receipts.c
deleted file mode 100644
index 677635d..0000000
--- a/src/donau/donau-httpd_common_submit_receipts.c
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_common_deposit.c
- * @brief shared logic for handling deposited coins
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include "taler-donau-httpd_common_deposit.h"
-#include "taler-donau-httpd.h"
-#include "taler-donau-httpd_keys.h"
-
-
-enum GNUNET_GenericReturnValue
-DH_common_purse_deposit_parse_coin (
- struct MHD_Connection *connection,
- struct DH_PurseDepositedCoin *coin,
- const json_t *jcoin)
-{
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("amount",
- DH_currency,
- &coin->amount),
- GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
- &coin->cpi.denom_pub_hash),
- TALER_JSON_spec_denom_sig ("ub_sig",
- &coin->cpi.denom_sig),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("attest",
- &coin->attest),
- &coin->no_attest),
- GNUNET_JSON_spec_mark_optional (
- TALER_JSON_spec_age_commitment ("age_commitment",
- &coin->age_commitment),
- &coin->cpi.no_age_commitment),
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &coin->coin_sig),
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &coin->cpi.coin_pub),
- GNUNET_JSON_spec_end ()
- };
-
- memset (coin,
- 0,
- sizeof (*coin));
- coin->cpi.no_age_commitment = true;
- coin->no_attest = true;
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (connection,
- jcoin,
- spec);
- if (GNUNET_OK != res)
- return res;
- }
-
- /* check denomination exists and is valid */
- {
- struct DH_DenominationKey *dk;
- MHD_RESULT mret;
-
- dk = DH_keys_denomination_by_hash (&coin->cpi.denom_pub_hash,
- connection,
- &mret);
- if (NULL == dk)
- {
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES == mret) ? GNUNET_NO : GNUNET_SYSERR;
- }
- if (! coin->cpi.no_age_commitment)
- {
- coin->age_commitment.mask = dk->meta.age_mask;
- TALER_age_commitment_hash (&coin->age_commitment,
- &coin->cpi.h_age_commitment);
- }
- if (0 > TALER_amount_cmp (&dk->meta.value,
- &coin->amount))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_GENERIC_AMOUNT_EXCEEDS_DENOMINATION_VALUE,
- NULL))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
- if (GNUNET_TIME_absolute_is_past (dk->meta.expire_deposit.abs_time))
- {
- /* This denomination is past the expiration time for deposits */
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- DH_RESPONSE_reply_expired_denom_pub_hash (
- connection,
- &coin->cpi.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_EXPIRED,
- "PURSE CREATE"))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
- if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
- {
- /* This denomination is not yet valid */
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- DH_RESPONSE_reply_expired_denom_pub_hash (
- connection,
- &coin->cpi.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
- "PURSE CREATE"))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
- if (dk->recoup_possible)
- {
- /* This denomination has been revoked */
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- DH_RESPONSE_reply_expired_denom_pub_hash (
- connection,
- &coin->cpi.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_REVOKED,
- "PURSE CREATE"))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
- if (dk->denom_pub.cipher != coin->cpi.denom_sig.cipher)
- {
- /* denomination cipher and denomination signature cipher not the same */
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_GENERIC_CIPHER_MISMATCH,
- NULL))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
-
- coin->deposit_fee = dk->meta.fees.deposit;
- if (0 < TALER_amount_cmp (&coin->deposit_fee,
- &coin->amount))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_DEPOSIT_NEGATIVE_VALUE_AFTER_FEE,
- NULL);
- }
- GNUNET_assert (0 <=
- TALER_amount_subtract (&coin->amount_minus_fee,
- &coin->amount,
- &coin->deposit_fee));
-
- /* check coin signature */
- switch (dk->denom_pub.cipher)
- {
- case TALER_DENOMINATION_RSA:
- DH_METRICS_num_verifications[DH_MT_SIGNATURE_RSA]++;
- break;
- case TALER_DENOMINATION_CS:
- DH_METRICS_num_verifications[DH_MT_SIGNATURE_CS]++;
- break;
- default:
- break;
- }
- if (GNUNET_YES !=
- TALER_test_coin_valid (&coin->cpi,
- &dk->denom_pub))
- {
- TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
- GNUNET_JSON_parse_free (spec);
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_DENOMINATION_SIGNATURE_INVALID,
- NULL))
- ? GNUNET_NO : GNUNET_SYSERR;
- }
- }
- return GNUNET_OK;
-}
-
-
-enum GNUNET_GenericReturnValue
-DH_common_deposit_check_purse_deposit (
- struct MHD_Connection *connection,
- const struct DH_PurseDepositedCoin *coin,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- uint32_t min_age)
-{
- if (GNUNET_OK !=
- TALER_wallet_purse_deposit_verify (DH_base_url,
- purse_pub,
- &coin->amount,
- &coin->cpi.denom_pub_hash,
- &coin->cpi.h_age_commitment,
- &coin->cpi.coin_pub,
- &coin->coin_sig))
- {
- TALER_LOG_WARNING (
- "Invalid coin signature to deposit into purse\n");
- return (MHD_YES ==
- TALER_MHD_reply_with_error (connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_PURSE_DEPOSIT_COIN_SIGNATURE_INVALID,
- DH_base_url))
- ? GNUNET_NO
- : GNUNET_SYSERR;
- }
-
- if (0 == min_age)
- return GNUNET_OK; /* no need to apply age checks */
-
- /* Check and verify the age restriction. */
- if (coin->no_attest != coin->cpi.no_age_commitment)
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_PURSE_DEPOSIT_COIN_CONFLICTING_ATTEST_VS_AGE_COMMITMENT,
- "mismatch of attest and
age_commitment");
- }
-
- if (coin->cpi.no_age_commitment)
- return GNUNET_OK; /* unrestricted coin */
-
- /* age attestation must be valid */
- if (GNUNET_OK !=
- TALER_age_commitment_verify (&coin->age_commitment,
- min_age,
- &coin->attest))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_PURSE_DEPOSIT_COIN_AGE_ATTESTATION_FAILURE,
- "invalid attest for minimum age");
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Release data structures of @a coin. Note that
- * @a coin itself is NOT freed.
- *
- * @param[in] coin information to release
- */
-void
-DH_common_purse_deposit_free_coin (struct DH_PurseDepositedCoin *coin)
-{
- TALER_denom_sig_free (&coin->cpi.denom_sig);
- if (! coin->cpi.no_age_commitment)
- GNUNET_free (coin->age_commitment.keys); /* Only the keys have been
allocated */
-}
diff --git a/src/donau/donau-httpd_common_submit_receipts.h
b/src/donau/donau-httpd_common_submit_receipts.h
deleted file mode 100644
index e5da955..0000000
--- a/src/donau/donau-httpd_common_submit_receipts.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2022 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_common_deposit.h
- * @brief shared logic for handling deposited coins
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_COMMON_DEPOSIT_H
-#define DONAU_HTTPD_COMMON_DEPOSIT_H
-
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include "taler/taler_json_lib.h"
-#include "taler/taler_mhd_lib.h"
-
-
-/**
- * Information about an individual coin being deposited.
- */
-struct DH_PurseDepositedCoin
-{
- /**
- * Public information about the coin.
- */
- struct TALER_CoinPublicInfo cpi;
-
- /**
- * Signature affirming spending the coin.
- */
- struct TALER_CoinSpendSignatureP coin_sig;
-
- /**
- * Amount to be put into the purse from this coin.
- */
- struct TALER_Amount amount;
-
- /**
- * Deposit fee applicable for this coin.
- */
- struct TALER_Amount deposit_fee;
-
- /**
- * Amount to be put into the purse from this coin.
- */
- struct TALER_Amount amount_minus_fee;
-
- /**
- * Age attestation provided, set if @e no_attest is false.
- */
- struct TALER_AgeAttestation attest;
-
- /**
- * Age commitment provided, set if @e cpi.no_age_commitment is false.
- */
- struct TALER_AgeCommitment age_commitment;
-
- /**
- * ID of the coin in known_coins.
- */
- uint64_t known_coin_id;
-
- /**
- * True if @e attest was not provided.
- */
- bool no_attest;
-
-};
-
-
-/**
- * Parse a coin and check signature of the coin and the denomination
- * signature over the coin.
- *
- * @param[in,out] connection our HTTP connection
- * @param[out] coin coin to initialize
- * @param jcoin coin to parse
- * @return #GNUNET_OK on success, #GNUNET_NO if an error was returned,
- * #GNUNET_SYSERR on failure and no error could be returned
- */
-enum GNUNET_GenericReturnValue
-DH_common_purse_deposit_parse_coin (
- struct MHD_Connection *connection,
- struct DH_PurseDepositedCoin *coin,
- const json_t *jcoin);
-
-
-/**
- * Check that the deposited @a coin is valid for @a purse_pub
- * and has a valid age commitment for @a min_age.
- *
- * @param[in,out] connection our HTTP connection
- * @param coin the coin to evaluate
- * @param purse_pub public key of the purse the coin was deposited into
- * @param min_age minimum age restriction expected for this purse
- * @return #GNUNET_OK on success, #GNUNET_NO if an error was returned,
- * #GNUNET_SYSERR on failure and no error could be returned
- */
-enum GNUNET_GenericReturnValue
-DH_common_deposit_check_purse_deposit (
- struct MHD_Connection *connection,
- const struct DH_PurseDepositedCoin *coin,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- uint32_t min_age);
-
-
-/**
- * Release data structures of @a coin. Note that
- * @a coin itself is NOT freed.
- *
- * @param[in] coin information to release
- */
-void
-DH_common_purse_deposit_free_coin (struct DH_PurseDepositedCoin *coin);
-
-#endif
diff --git a/src/donau/donau-httpd_config.c b/src/donau/donau-httpd_config.c
index 1b78bfa..307d24b 100644
--- a/src/donau/donau-httpd_config.c
+++ b/src/donau/donau-httpd_config.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015-2021 Taler Systems SA
+ Copyright (C) 2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software
@@ -23,7 +23,6 @@
#include "taler_dbevents.h"
#include "taler-donau-httpd_config.h"
#include "taler/taler_json_lib.h"
-#include "taler_kyclogic_lib.h"
#include "taler/taler_mhd_lib.h"
#include <jansson.h>
@@ -37,8 +36,6 @@ DH_handler_config (struct DH_RequestContext *rc,
if (NULL == resp)
{
resp = TALER_MHD_MAKE_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("supported_kyc_requirements",
- TALER_KYCLOGIC_get_satisfiable ()),
GNUNET_JSON_pack_string ("currency",
DH_currency),
GNUNET_JSON_pack_string ("name",
diff --git a/src/donau/donau-httpd_db.c b/src/donau/donau-httpd_db.c
index 24b6dd5..df80caa 100644
--- a/src/donau/donau-httpd_db.c
+++ b/src/donau/donau-httpd_db.c
@@ -29,61 +29,6 @@
#include "taler-donau-httpd_responses.h"
-enum GNUNET_DB_QueryStatus
-DH_make_coin_known (const struct TALER_CoinPublicInfo *coin,
- struct MHD_Connection *connection,
- uint64_t *known_coin_id,
- MHD_RESULT *mhd_ret)
-{
- enum DONAUDB_CoinKnownStatus cks;
- struct TALER_DenominationHashP h_denom_pub;
- struct TALER_AgeCommitmentHash age_hash;
-
- /* make sure coin is 'known' in database */
- cks = DH_plugin->ensure_coin_known (DH_plugin->cls,
- coin,
- known_coin_id,
- &h_denom_pub,
- &age_hash);
- switch (cks)
- {
- case DONAUDB_CKS_ADDED:
- return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
- case DONAUDB_CKS_PRESENT:
- return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
- case DONAUDB_CKS_SOFT_FAIL:
- return GNUNET_DB_STATUS_SOFT_ERROR;
- case DONAUDB_CKS_HARD_FAIL:
- *mhd_ret
- = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_STORE_FAILED,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case DONAUDB_CKS_DENOM_CONFLICT:
- /* FIXME: insufficient_funds != denom conflict! See issue #7267, need new
- * strategy for evidence gathering */
- *mhd_ret = DH_RESPONSE_reply_coin_insufficient_funds (
- connection,
- TALER_EC_DONAU_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY,
- &h_denom_pub,
- &coin->coin_pub);
- return GNUNET_DB_STATUS_HARD_ERROR;
- case DONAUDB_CKS_AGE_CONFLICT:
- /* FIXME: insufficient_funds != Age conflict! See issue #7267, need new
- * strategy for evidence gathering */
- *mhd_ret = DH_RESPONSE_reply_coin_insufficient_funds (
- connection,
- TALER_EC_DONAU_GENERIC_COIN_CONFLICTING_AGE_HASH,
- &h_denom_pub,
- &coin->coin_pub);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- GNUNET_assert (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
-}
-
-
enum GNUNET_GenericReturnValue
DH_DB_run_transaction (struct MHD_Connection *connection,
const char *name,
diff --git a/src/donau/donau-httpd_issue_receipts.c
b/src/donau/donau-httpd_issue_receipts.c
deleted file mode 100644
index 4bb017d..0000000
--- a/src/donau/donau-httpd_issue_receipts.c
+++ /dev/null
@@ -1,700 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General
- Public License along with TALER; see the file COPYING. If not,
- see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_withdraw.c
- * @brief Handle /reserves/$RESERVE_PUB/withdraw requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include "taler-donau-httpd.h"
-#include "taler/taler_json_lib.h"
-#include "taler_kyclogic_lib.h"
-#include "taler/taler_mhd_lib.h"
-#include "taler-donau-httpd_withdraw.h"
-#include "taler-donau-httpd_responses.h"
-#include "taler-donau-httpd_keys.h"
-
-
-/**
- * Context for #withdraw_transaction.
- */
-struct WithdrawContext
-{
-
- /**
- * Hash of the (blinded) message to be signed by the Donau.
- */
- struct TALER_BlindedCoinHashP h_coin_envelope;
-
- /**
- * Blinded planchet.
- */
- struct TALER_BlindedPlanchet blinded_planchet;
-
- /**
- * Set to the resulting signed coin data to be returned to the client.
- */
- struct DONAUDB_CollectableBlindcoin collectable;
-
- /**
- * KYC status for the operation.
- */
- struct DONAUDB_KycStatus kyc;
-
- /**
- * Hash of the payto-URI representing the account
- * from which the money was put into the reserve.
- */
- struct TALER_PaytoHashP h_account_payto;
-
- /**
- * Current time for the DB transaction.
- */
- struct GNUNET_TIME_Timestamp now;
-
- /**
- * AML decision, #TALER_AML_NORMAL if we may proceed.
- */
- enum TALER_AmlDecisionState aml_decision;
-
-};
-
-
-/**
- * Function called to iterate over KYC-relevant
- * transaction amounts for a particular time range.
- * Called within a database transaction, so must
- * not start a new one.
- *
- * @param cls closure, identifies the event type and
- * account to iterate over events for
- * @param limit maximum time-range for which events
- * should be fetched (timestamp in the past)
- * @param cb function to call on each event found,
- * events must be returned in reverse chronological
- * order
- * @param cb_cls closure for @a cb
- */
-static void
-withdraw_amount_cb (void *cls,
- struct GNUNET_TIME_Absolute limit,
- DONAUDB_KycAmountCallback cb,
- void *cb_cls)
-{
- struct WithdrawContext *wc = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Signaling amount %s for KYC check\n",
- TALER_amount2s (&wc->collectable.amount_with_fee));
- if (GNUNET_OK !=
- cb (cb_cls,
- &wc->collectable.amount_with_fee,
- wc->now.abs_time))
- return;
- qs = DH_plugin->select_withdraw_amounts_for_kyc_check (
- DH_plugin->cls,
- &wc->h_account_payto,
- limit,
- cb,
- cb_cls);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Got %d additional transactions for this withdrawal and limit
%llu\n",
- qs,
- (unsigned long long) limit.abs_value_us);
- GNUNET_break (qs >= 0);
-}
-
-
-/**
- * Function called on each @a amount that was found to
- * be relevant for the AML check as it was merged into
- * the reserve.
- *
- * @param cls `struct TALER_Amount *` to total up the amounts
- * @param amount encountered transaction amount
- * @param date when was the amount encountered
- * @return #GNUNET_OK to continue to iterate,
- * #GNUNET_NO to abort iteration
- * #GNUNET_SYSERR on internal error (also abort itaration)
- */
-static enum GNUNET_GenericReturnValue
-aml_amount_cb (
- void *cls,
- const struct TALER_Amount *amount,
- struct GNUNET_TIME_Absolute date)
-{
- struct TALER_Amount *total = cls;
-
- GNUNET_assert (0 <=
- TALER_amount_add (total,
- total,
- amount));
- return GNUNET_OK;
-}
-
-
-/**
- * Function implementing withdraw transaction. Runs the
- * transaction logic; IF it returns a non-error code, the transaction
- * logic MUST NOT queue a MHD response. IF it returns an hard error,
- * the transaction logic MUST queue a MHD response and set @a mhd_ret.
- * IF it returns the soft error code, the function MAY be called again
- * to retry and MUST not queue a MHD response.
- *
- * Note that "wc->collectable.sig" is set before entering this function as we
- * signed before entering the transaction.
- *
- * @param cls a `struct WithdrawContext *`
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-withdraw_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct WithdrawContext *wc = cls;
- enum GNUNET_DB_QueryStatus qs;
- bool found = false;
- bool balance_ok = false;
- bool nonce_ok = false;
- bool age_ok = false;
- uint16_t allowed_maximum_age = 0;
- uint64_t ruuid;
- const struct TALER_CsNonce *nonce;
- const struct TALER_BlindedPlanchet *bp;
- struct TALER_PaytoHashP reserve_h_payto;
-
- wc->now = GNUNET_TIME_timestamp_get ();
- /* Do AML check: compute total merged amount and check
- against applicable AML threshold */
- {
- char *reserve_payto;
-
- reserve_payto = TALER_reserve_make_payto (DH_base_url,
- &wc->collectable.reserve_pub);
- TALER_payto_hash (reserve_payto,
- &reserve_h_payto);
- GNUNET_free (reserve_payto);
- }
- {
- struct TALER_Amount merge_amount;
- struct TALER_Amount threshold;
- struct GNUNET_TIME_Absolute now_minus_one_month;
-
- now_minus_one_month
- = GNUNET_TIME_absolute_subtract (wc->now.abs_time,
- GNUNET_TIME_UNIT_MONTHS);
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (DH_currency,
- &merge_amount));
- qs = DH_plugin->select_merge_amounts_for_kyc_check (DH_plugin->cls,
- &reserve_h_payto,
- now_minus_one_month,
- &aml_amount_cb,
- &merge_amount);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
-
"select_merge_amounts_for_kyc_check");
- return qs;
- }
- qs = DH_plugin->select_aml_threshold (DH_plugin->cls,
- &reserve_h_payto,
- &wc->aml_decision,
- &wc->kyc,
- &threshold);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "select_aml_threshold");
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- threshold = DH_aml_threshold; /* use default */
- wc->aml_decision = TALER_AML_NORMAL;
- }
-
- switch (wc->aml_decision)
- {
- case TALER_AML_NORMAL:
- if (0 >= TALER_amount_cmp (&merge_amount,
- &threshold))
- {
- /* merge_amount <= threshold, continue withdraw below */
- break;
- }
- wc->aml_decision = TALER_AML_PENDING;
- qs = DH_plugin->trigger_aml_process (DH_plugin->cls,
- &reserve_h_payto,
- &merge_amount);
- if (qs <= 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mhd_ret = TALER_MHD_reply_with_error (connection,
-
MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_STORE_FAILED,
- "trigger_aml_process");
- return qs;
- }
- return qs;
- case TALER_AML_PENDING:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "AML already pending, doing nothing\n");
- return qs;
- case TALER_AML_FROZEN:
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Account frozen, doing nothing\n");
- return qs;
- }
- }
-
- /* Check if the money came from a wire transfer */
- qs = DH_plugin->reserves_get_origin (DH_plugin->cls,
- &wc->collectable.reserve_pub,
- &wc->h_account_payto);
- if (qs < 0)
- return qs;
- /* If no results, reserve was created by merge, in which case no KYC check
- is required as the merge already did that. */
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- char *kyc_required;
-
- qs = TALER_KYCLOGIC_kyc_test_required (
- TALER_KYCLOGIC_KYC_TRIGGER_WITHDRAW,
- &wc->h_account_payto,
- DH_plugin->select_satisfied_kyc_processes,
- DH_plugin->cls,
- &withdraw_amount_cb,
- wc,
- &kyc_required);
- if (qs < 0)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "kyc_test_required");
- }
- return qs;
- }
- if (NULL != kyc_required)
- {
- /* insert KYC requirement into DB! */
- wc->kyc.ok = false;
- qs = DH_plugin->insert_kyc_requirement_for_account (
- DH_plugin->cls,
- kyc_required,
- &wc->h_account_payto,
- &wc->collectable.reserve_pub,
- &wc->kyc.requirement_row);
- GNUNET_free (kyc_required);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_DB_STORE_FAILED,
-
"insert_kyc_requirement_for_account");
- }
- return qs;
- }
- }
- wc->kyc.ok = true;
- bp = &wc->blinded_planchet;
- nonce = (TALER_DENOMINATION_CS == bp->cipher)
- ? &bp->details.cs_blinded_planchet.nonce
- : NULL;
- qs = DH_plugin->do_withdraw (DH_plugin->cls,
- nonce,
- &wc->collectable,
- wc->now,
- DH_age_restriction_enabled,
- &found,
- &balance_ok,
- &nonce_ok,
- &age_ok,
- &allowed_maximum_age,
- &ruuid);
- if (0 > qs)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "do_withdraw");
- }
- return qs;
- }
- if (! found)
- {
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
-
TALER_EC_DONAU_GENERIC_RESERVE_UNKNOWN,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (! age_ok)
- {
- /* We respond with the lowest age in the corresponding age group
- * of the required age */
- uint16_t lowest_age = TALER_get_lowest_age (
- &DH_age_restriction_config.mask,
- allowed_maximum_age);
-
- DH_plugin->rollback (DH_plugin->cls);
- *mhd_ret = DH_RESPONSE_reply_reserve_age_restriction_required (
- connection,
- lowest_age);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (! balance_ok)
- {
- DH_plugin->rollback (DH_plugin->cls);
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Balance insufficient for /withdraw\n");
- *mhd_ret = DH_RESPONSE_reply_reserve_insufficient_balance (
- connection,
- TALER_EC_DONAU_WITHDRAW_INSUFFICIENT_FUNDS,
- &wc->collectable.amount_with_fee,
- &wc->collectable.reserve_pub);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (! nonce_ok)
- {
- DH_plugin->rollback (DH_plugin->cls);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_DONAU_WITHDRAW_NONCE_REUSE,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- DH_METRICS_num_success[DH_MT_SUCCESS_WITHDRAW]++;
- return qs;
-}
-
-
-/**
- * Check if the @a rc is replayed and we already have an
- * answer. If so, replay the existing answer and return the
- * HTTP response.
- *
- * @param rc request context
- * @param[in,out] wc parsed request data
- * @param[out] mret HTTP status, set if we return true
- * @return true if the request is idempotent with an existing request
- * false if we did not find the request in the DB and did not set @a mret
- */
-static bool
-check_request_idempotent (struct DH_RequestContext *rc,
- struct WithdrawContext *wc,
- MHD_RESULT *mret)
-{
- enum GNUNET_DB_QueryStatus qs;
-
- qs = DH_plugin->get_withdraw_info (DH_plugin->cls,
- &wc->h_coin_envelope,
- &wc->collectable);
- if (0 > qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- *mret = TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "get_withdraw_info");
- return true; /* well, kind-of */
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- return false;
- /* generate idempotent reply */
- DH_METRICS_num_requests[DH_MT_REQUEST_IDEMPOTENT_WITHDRAW]++;
- *mret = TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_OK,
- TALER_JSON_pack_blinded_denom_sig ("ev_sig",
- &wc->collectable.sig));
- TALER_blinded_denom_sig_free (&wc->collectable.sig);
- return true;
-}
-
-
-MHD_RESULT
-DH_handler_withdraw (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root)
-{
- struct WithdrawContext wc;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &wc.collectable.reserve_sig),
- GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
- &wc.collectable.denom_pub_hash),
- TALER_JSON_spec_blinded_planchet ("coin_ev",
- &wc.blinded_planchet),
- GNUNET_JSON_spec_end ()
- };
- enum TALER_ErrorCode ec;
- struct DH_DenominationKey *dk;
-
- memset (&wc,
- 0,
- sizeof (wc));
- wc.collectable.reserve_pub = *reserve_pub;
- {
- enum GNUNET_GenericReturnValue res;
-
- res = TALER_MHD_parse_json_data (rc->connection,
- root,
- spec);
- if (GNUNET_OK != res)
- return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
- }
- {
- MHD_RESULT mret;
- struct DH_KeyStateHandle *ksh;
-
- ksh = DH_keys_get_state ();
- if (NULL == ksh)
- {
- if (! check_request_idempotent (rc,
- &wc,
- &mret))
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_DONAU_GENERIC_KEYS_MISSING,
- NULL);
- }
- GNUNET_JSON_parse_free (spec);
- return mret;
- }
-
- dk = DH_keys_denomination_by_hash_from_state (
- ksh,
- &wc.collectable.denom_pub_hash,
- NULL,
- NULL);
-
- if (NULL == dk)
- {
- if (! check_request_idempotent (rc,
- &wc,
- &mret))
- {
- GNUNET_JSON_parse_free (spec);
- return DH_RESPONSE_reply_unknown_denom_pub_hash (
- rc->connection,
- &wc.collectable.denom_pub_hash);
- }
- GNUNET_JSON_parse_free (spec);
- return mret;
- }
- if (GNUNET_TIME_absolute_is_past (dk->meta.expire_withdraw.abs_time))
- {
- /* This denomination is past the expiration time for withdraws */
- if (! check_request_idempotent (rc,
- &wc,
- &mret))
- {
- GNUNET_JSON_parse_free (spec);
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &wc.collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_EXPIRED,
- "WITHDRAW");
- }
- GNUNET_JSON_parse_free (spec);
- return mret;
- }
- if (GNUNET_TIME_absolute_is_future (dk->meta.start.abs_time))
- {
- /* This denomination is not yet valid, no need to check
- for idempotency! */
- GNUNET_JSON_parse_free (spec);
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &wc.collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
- "WITHDRAW");
- }
- if (dk->recoup_possible)
- {
- /* This denomination has been revoked */
- if (! check_request_idempotent (rc,
- &wc,
- &mret))
- {
- GNUNET_JSON_parse_free (spec);
- return DH_RESPONSE_reply_expired_denom_pub_hash (
- rc->connection,
- &wc.collectable.denom_pub_hash,
- TALER_EC_DONAU_GENERIC_DENOMINATION_REVOKED,
- "WITHDRAW");
- }
- GNUNET_JSON_parse_free (spec);
- return mret;
- }
- if (dk->denom_pub.cipher != wc.blinded_planchet.cipher)
- {
- /* denomination cipher and blinded planchet cipher not the same */
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_GENERIC_CIPHER_MISMATCH,
- NULL);
- }
- }
-
- if (0 >
- TALER_amount_add (&wc.collectable.amount_with_fee,
- &dk->meta.value,
- &dk->meta.fees.withdraw))
- {
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_DONAU_WITHDRAW_AMOUNT_FEE_OVERFLOW,
- NULL);
- }
-
- if (GNUNET_OK !=
- TALER_coin_ev_hash (&wc.blinded_planchet,
- &wc.collectable.denom_pub_hash,
- &wc.collectable.h_coin_envelope))
- {
- GNUNET_break (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
- NULL);
- }
-
- DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
- if (GNUNET_OK !=
- TALER_wallet_withdraw_verify (&wc.collectable.denom_pub_hash,
- &wc.collectable.amount_with_fee,
- &wc.collectable.h_coin_envelope,
- &wc.collectable.reserve_pub,
- &wc.collectable.reserve_sig))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_WITHDRAW_RESERVE_SIGNATURE_INVALID,
- NULL);
- }
-
- {
- struct DH_CoinSignData csd = {
- .h_denom_pub = &wc.collectable.denom_pub_hash,
- .bp = &wc.blinded_planchet
- };
-
- /* Sign before transaction! */
- ec = DH_keys_denomination_sign (
- &csd,
- false,
- &wc.collectable.sig);
- }
- if (TALER_EC_NONE != ec)
- {
- GNUNET_break (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to sign coin: %d\n",
- ec);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_ec (rc->connection,
- ec,
- NULL);
- }
-
- /* run transaction */
- {
- MHD_RESULT mhd_ret;
-
- if (GNUNET_OK !=
- DH_DB_run_transaction (rc->connection,
- "run withdraw",
- DH_MT_REQUEST_WITHDRAW,
- &mhd_ret,
- &withdraw_transaction,
- &wc))
- {
- /* Even if #withdraw_transaction() failed, it may have created a
signature
- (or we might have done it optimistically above). */
- TALER_blinded_denom_sig_free (&wc.collectable.sig);
- GNUNET_JSON_parse_free (spec);
- return mhd_ret;
- }
- }
-
- /* Clean up and send back final response */
- GNUNET_JSON_parse_free (spec);
-
- if (! wc.kyc.ok)
- return DH_RESPONSE_reply_kyc_required (rc->connection,
- &wc.h_account_payto,
- &wc.kyc);
-
- if (TALER_AML_NORMAL != wc.aml_decision)
- return DH_RESPONSE_reply_aml_blocked (rc->connection,
- wc.aml_decision);
-
- {
- MHD_RESULT ret;
-
- ret = TALER_MHD_REPLY_JSON_PACK (
- rc->connection,
- MHD_HTTP_OK,
- TALER_JSON_pack_blinded_denom_sig ("ev_sig",
- &wc.collectable.sig));
- TALER_blinded_denom_sig_free (&wc.collectable.sig);
- return ret;
- }
-}
-
-
-/* end of taler-donau-httpd_withdraw.c */
diff --git a/src/donau/donau-httpd_issue_receipts.h
b/src/donau/donau-httpd_issue_receipts.h
deleted file mode 100644
index ef7615a..0000000
--- a/src/donau/donau-httpd_issue_receipts.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2021 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_withdraw.h
- * @brief Handle /reserve/withdraw requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_WITHDRAW_H
-#define DONAU_HTTPD_WITHDRAW_H
-
-#include <microhttpd.h>
-#include "taler-donau-httpd.h"
-
-
-/**
- * Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the requested
"denom_pub" which
- * specifies the key/value of the coin to be withdrawn, and checks that the
- * signature "reserve_sig" makes this a valid withdrawal request from the
- * specified reserve. If so, the envelope with the blinded coin "coin_ev" is
- * passed down to execute the withdrawal operation.
- *
- * @param rc request context
- * @param root uploaded JSON data
- * @param reserve_pub public key of the reserve
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_withdraw (struct DH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root);
-
-#endif
diff --git a/src/donau/donau-httpd_keys.c b/src/donau/donau-httpd_keys.c
index 68c4d4c..de51526 100644
--- a/src/donau/donau-httpd_keys.c
+++ b/src/donau/donau-httpd_keys.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2020-2023 Taler Systems SA
+ Copyright (C) 2020-2024 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software
@@ -23,7 +23,6 @@
#include "taler/taler_json_lib.h"
#include "taler/taler_mhd_lib.h"
#include "donau-httpd.h"
-// #include "donau-httpd_config.h"
#include "donau-httpd_keys.h"
#include "donau-httpd_responses.h"
#include "donaudb_plugin.h"
@@ -67,11 +66,6 @@ struct HelperDonationUnit
*/
struct TALER_DenominationHashP h_denom_pub;
- /**
- * Signature over this key from the security module's key.
- */
- struct TALER_SecurityModuleSignatureP sm_sig;
-
/**
* The (full) public key.
*/
@@ -109,16 +103,6 @@ struct HelperDonationUnit
*/
struct HelperSignkey
{
- /**
- * When will the helper start to use this key for signing?
- */
- // struct GNUNET_TIME_Timestamp start_time;
-
- /**
- * For how long will the helper allow signing? 0 if
- * the key was revoked or purged.
- */
- // struct GNUNET_TIME_Relative validity_duration;
/**
* The public key.
@@ -279,23 +263,6 @@ struct DH_KeyStateHandle
*/
uint64_t key_generation;
- /**
- * When did we initiate the key reloading?
- */
- // struct GNUNET_TIME_Timestamp reload_time;
-
- /**
- * What is the period at which we rotate keys
- * (signing or denomination keys)?
- */
- // struct GNUNET_TIME_Relative rekey_frequency;
-
- /**
- * When does our online signing key expire and we
- * thus need to re-generate this response?
- */
- // struct GNUNET_TIME_Timestamp signature_expires;
-
/**
* True if #finish_keys_response() was not yet run and this key state
* is only suitable for the /management/keys API.
@@ -578,212 +545,6 @@ destroy_key_helpers (struct HelperState *hs)
}
-/**
- * Looks up the AGE_RESTRICTED setting for a denomination in the config and
- * returns the age restriction (mask) accordingly.
- *
- * @param section_name Section in the configuration for the particular
- * denomination.
- */
-static struct TALER_AgeMask
-load_age_mask (const char *section_name)
-{
- static const struct TALER_AgeMask null_mask = {0};
- enum GNUNET_GenericReturnValue ret;
-
- if (GNUNET_OK != (GNUNET_CONFIGURATION_have_value (
- DH_cfg,
- section_name,
- "AGE_RESTRICTED")))
- return null_mask;
-
- if (GNUNET_SYSERR ==
- (ret = GNUNET_CONFIGURATION_get_value_yesno (DH_cfg,
- section_name,
- "AGE_RESTRICTED")))
- {
- GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
- section_name,
- "AGE_RESTRICTED",
- "Value must be YES or NO\n");
- return null_mask;
- }
-
- if (GNUNET_OK == ret)
- {
- if (! DH_age_restriction_enabled)
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "age restriction set in section %s, yet, age restriction is
not enabled\n",
- section_name);
- return DH_age_restriction_config.mask;
- }
-
-
- return null_mask;
-}
-
-
-/**
- * Function called with information about available keys for signing. Usually
- * only called once per key upon connect. Also called again in case a key is
- * being revoked, in that case with an @a end_time of zero.
- *
- * @param cls closure with the `struct HelperState *`
- * @param section_name name of the denomination type in the configuration;
- * NULL if the key has been revoked or purged
- * @param start_time when does the key become available for signing;
- * zero if the key has been revoked or purged
- * @param validity_duration how long does the key remain available for signing;
- * zero if the key has been revoked or purged
- * @param h_rsa hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or
purged
- * @param sm_pub public key of the security module, NULL if the key was
revoked or purged
- * @param sm_sig signature from the security module, NULL if the key was
revoked or purged
- * The signature was already verified against @a sm_pub.
- */
-static void
-helper_rsa_cb (
- void *cls,
- const char *section_name,
- struct GNUNET_TIME_Timestamp start_time,
- struct GNUNET_TIME_Relative validity_duration,
- const struct TALER_RsaPubHashP *h_rsa,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_SecurityModulePublicKeyP *sm_pub,
- const struct TALER_SecurityModuleSignatureP *sm_sig)
-{
- struct HelperState *hs = cls;
- struct HelperDonationUnit *hd;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "RSA helper announces key %s for denomination type %s with
validity %s\n",
- GNUNET_h2s (&h_rsa->hash),
- section_name,
- GNUNET_STRINGS_relative_time_to_string (validity_duration,
- GNUNET_NO));
- key_generation++;
- DH_resume_keys_requests (false);
- hd = GNUNET_CONTAINER_multihashmap_get (hs->rsa_keys,
- &h_rsa->hash);
- if (NULL != hd)
- {
- /* should be just an update (revocation!), so update existing entry */
- hd->validity_duration = validity_duration;
- return;
- }
- GNUNET_assert (NULL != sm_pub);
- check_denom_rsa_sm_pub (sm_pub);
- hd = GNUNET_new (struct HelperDonationUnit);
- hd->start_time = start_time;
- hd->validity_duration = validity_duration;
- hd->h_details.h_rsa = *h_rsa;
- hd->sm_sig = *sm_sig;
- GNUNET_assert (TALER_DENOMINATION_RSA == denom_pub->cipher);
- TALER_denom_pub_deep_copy (&hd->denom_pub,
- denom_pub);
- GNUNET_assert (TALER_DENOMINATION_RSA == hd->denom_pub.cipher);
- /* load the age mask for the denomination, if applicable */
- hd->denom_pub.age_mask = load_age_mask (section_name);
- TALER_denom_pub_hash (&hd->denom_pub,
- &hd->h_denom_pub);
- hd->section_name = GNUNET_strdup (section_name);
- GNUNET_assert (
- GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (
- hs->denom_keys,
- &hd->h_denom_pub.hash,
- hd,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- GNUNET_assert (
- GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (
- hs->rsa_keys,
- &hd->h_details.h_rsa.hash,
- hd,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-}
-
-
-/**
- * Function called with information about available CS keys for signing.
Usually
- * only called once per key upon connect. Also called again in case a key is
- * being revoked, in that case with an @a end_time of zero.
- *
- * @param cls closure with the `struct HelperState *`
- * @param section_name name of the denomination type in the configuration;
- * NULL if the key has been revoked or purged
- * @param start_time when does the key become available for signing;
- * zero if the key has been revoked or purged
- * @param validity_duration how long does the key remain available for signing;
- * zero if the key has been revoked or purged
- * @param h_cs hash of the @a denom_pub that is available (or was purged)
- * @param denom_pub the public key itself, NULL if the key was revoked or
purged
- * @param sm_pub public key of the security module, NULL if the key was
revoked or purged
- * @param sm_sig signature from the security module, NULL if the key was
revoked or purged
- * The signature was already verified against @a sm_pub.
- */
-static void
-helper_cs_cb (
- void *cls,
- const char *section_name,
- struct GNUNET_TIME_Timestamp start_time,
- struct GNUNET_TIME_Relative validity_duration,
- const struct TALER_CsPubHashP *h_cs,
- const struct TALER_DenominationPublicKey *denom_pub,
- const struct TALER_SecurityModulePublicKeyP *sm_pub,
- const struct TALER_SecurityModuleSignatureP *sm_sig)
-{
- struct HelperState *hs = cls;
- struct HelperDonationUnit *hd;
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "CS helper announces key %s for denomination type %s with
validity %s\n",
- GNUNET_h2s (&h_cs->hash),
- section_name,
- GNUNET_STRINGS_relative_time_to_string (validity_duration,
- GNUNET_NO));
- key_generation++;
- DH_resume_keys_requests (false);
- hd = GNUNET_CONTAINER_multihashmap_get (hs->cs_keys,
- &h_cs->hash);
- if (NULL != hd)
- {
- /* should be just an update (revocation!), so update existing entry */
- hd->validity_duration = validity_duration;
- return;
- }
- GNUNET_assert (NULL != sm_pub);
- check_denom_cs_sm_pub (sm_pub);
- hd = GNUNET_new (struct HelperDonationUnit);
- hd->start_time = start_time;
- hd->validity_duration = validity_duration;
- hd->h_details.h_cs = *h_cs;
- hd->sm_sig = *sm_sig;
- GNUNET_assert (TALER_DENOMINATION_CS == denom_pub->cipher);
- TALER_denom_pub_deep_copy (&hd->denom_pub,
- denom_pub);
- /* load the age mask for the denomination, if applicable */
- hd->denom_pub.age_mask = load_age_mask (section_name);
- TALER_denom_pub_hash (&hd->denom_pub,
- &hd->h_denom_pub);
- hd->section_name = GNUNET_strdup (section_name);
- GNUNET_assert (
- GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (
- hs->denom_keys,
- &hd->h_denom_pub.hash,
- hd,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- GNUNET_assert (
- GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (
- hs->cs_keys,
- &hd->h_details.h_cs.hash,
- hd,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-}
-
-
/**
* Function called with information about available keys for signing. Usually
* only called once per key upon connect. Also called again in case a key is
@@ -1139,7 +900,6 @@ denomination_info_cb (
* @param cls closure with a `struct DH_KeyStateHandle *`
* @param donau_pub the public key
* @param meta meta data information about the denomination type (expirations)
- * @param master_sig master signature affirming the validity of this
denomination
*/
static void
signkey_info_cb (
@@ -1218,8 +978,6 @@ add_sign_key_cb (void *cls,
sk->meta.expire_sign),
GNUNET_JSON_pack_timestamp ("stamp_end",
sk->meta.expire_legal),
- GNUNET_JSON_pack_data_auto ("master_sig",
- &sk->master_sig),
GNUNET_JSON_pack_data_auto ("key",
&sk->donau_pub))));
return GNUNET_OK;
@@ -1295,899 +1053,6 @@ add_denom_key_cb (void *cls,
}
-/**
- * Add the headers we want to set for every /keys response.
- *
- * @param ksh the key state to use
- * @param wsh wire state to use
- * @param[in,out] response the response to modify
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-setup_general_response_headers (struct DH_KeyStateHandle *ksh,
- struct WireStateHandle *wsh,
- struct MHD_Response *response)
-{
- char dat[128];
-
- TALER_MHD_add_global_headers (response);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_CONTENT_TYPE,
- "application/json"));
- TALER_MHD_get_date_string (ksh->reload_time.abs_time,
- dat);
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_LAST_MODIFIED,
- dat));
- if (! GNUNET_TIME_relative_is_zero (ksh->rekey_frequency))
- {
- struct GNUNET_TIME_Relative r;
- struct GNUNET_TIME_Absolute a;
- struct GNUNET_TIME_Timestamp km;
- struct GNUNET_TIME_Timestamp m;
- struct GNUNET_TIME_Timestamp we;
-
- r = GNUNET_TIME_relative_min (DH_max_keys_caching,
- ksh->rekey_frequency);
- a = GNUNET_TIME_relative_to_absolute (r);
- km = GNUNET_TIME_absolute_to_timestamp (a);
- we = GNUNET_TIME_absolute_to_timestamp (wsh->cache_expiration);
- m = GNUNET_TIME_timestamp_min (we,
- km);
- TALER_MHD_get_date_string (m.abs_time,
- dat);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Setting /keys 'Expires' header to '%s' (rekey frequency is
%s)\n",
- dat,
- GNUNET_TIME_relative2s (ksh->rekey_frequency,
- false));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_EXPIRES,
- dat));
- ksh->signature_expires
- = GNUNET_TIME_timestamp_min (m,
- ksh->signature_expires);
- }
- /* Set cache control headers: our response varies depending on these headers
*/
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_VARY,
- MHD_HTTP_HEADER_ACCEPT_ENCODING));
- /* Information is always public, revalidate after 1 hour */
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (response,
- MHD_HTTP_HEADER_CACHE_CONTROL,
- "public,max-age=3600"));
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with wallet balance thresholds.
- *
- * @param[in,out] cls a `json **` where to put the array of json amounts
discovered
- * @param threshold another threshold amount to add
- */
-static void
-wallet_threshold_cb (void *cls,
- const struct TALER_Amount *threshold)
-{
- json_t **ret = cls;
-
- if (NULL == *ret)
- *ret = json_array ();
- GNUNET_assert (0 ==
- json_array_append_new (*ret,
- TALER_JSON_from_amount (
- threshold)));
-}
-
-
-/**
- * Initialize @a krd using the given values for @a signkeys,
- * @a recoup and @a denoms.
- *
- * @param[in,out] ksh key state handle we build @a krd for
- * @param[in] denom_keys_hash hash over all the denomination keys in @a denoms
- * @param last_cherry_pick_date timestamp to use
- * @param[in,out] signkeys list of sign keys to return
- * @param[in,out] recoup list of revoked keys to return
- * @param[in,out] grouped_denominations list of grouped denominations to return
- * @param h_grouped XOR of all hashes in @a grouped_demoninations
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-create_krd (struct DH_KeyStateHandle *ksh,
- const struct GNUNET_HashCode *denom_keys_hash,
- struct GNUNET_TIME_Timestamp last_cherry_pick_date,
- json_t *signkeys,
- json_t *recoup,
- json_t *grouped_denominations,
- const struct GNUNET_HashCode *h_grouped)
-{
- struct KeysResponseData krd;
- struct DONAU_DonauPublicKeyP donau_pub;
- struct TALER_DonauSignatureP donau_sig;
- struct DONAU_DonauPublicKeyP grouped_donau_pub;
- struct TALER_DonauSignatureP grouped_donau_sig;
- struct WireStateHandle *wsh;
- json_t *keys;
-
- wsh = get_wire_state ();
- if (MHD_HTTP_OK != wsh->http_status)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- GNUNET_assert (! GNUNET_TIME_absolute_is_zero (
- last_cherry_pick_date.abs_time));
- GNUNET_assert (NULL != signkeys);
- GNUNET_assert (NULL != recoup);
- GNUNET_assert (NULL != grouped_denominations);
- GNUNET_assert (NULL != h_grouped);
- GNUNET_assert (NULL != ksh->auditors);
- GNUNET_assert (NULL != DH_currency);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Creating /keys at cherry pick date %s\n",
- GNUNET_TIME_timestamp2s (last_cherry_pick_date));
-
- /* Sign hash over denomination keys */
- {
- enum TALER_ErrorCode ec;
-
- if (TALER_EC_NONE !=
- (ec =
- TALER_donau_online_key_set_sign (
- &DH_keys_donau_sign2_,
- ksh,
- last_cherry_pick_date,
- denom_keys_hash,
- &donau_pub,
- &donau_sig)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Could not create key response data: cannot sign (%s)\n",
- TALER_ErrorCode_get_hint (ec));
- return GNUNET_SYSERR;
- }
- }
-
- /* Sign grouped hash */
- {
- enum TALER_ErrorCode ec;
-
- if (TALER_EC_NONE !=
- (ec =
- TALER_donau_online_key_set_sign (
- &DH_keys_donau_sign2_,
- ksh,
- last_cherry_pick_date,
- h_grouped,
- &grouped_donau_pub,
- &grouped_donau_sig)))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Could not create key response data: cannot sign grouped
hash (%s)\n",
- TALER_ErrorCode_get_hint (ec));
- return GNUNET_SYSERR;
- }
- }
-
- /* both public keys really must be the same */
- GNUNET_assert (0 ==
- memcmp (&grouped_donau_pub,
- &donau_pub,
- sizeof(donau_pub)));
-
- {
- const struct SigningKey *sk;
-
- sk = GNUNET_CONTAINER_multipeermap_get (
- ksh->signkey_map,
- (const struct GNUNET_PeerIdentity *) &donau_pub);
- ksh->signature_expires = GNUNET_TIME_timestamp_min (sk->meta.expire_sign,
-
ksh->signature_expires);
- }
-
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Build /keys data with %u wire accounts\n",
- (unsigned int) json_array_size (
- json_object_get (wsh->json_reply,
- "accounts")));
-
- keys = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("version",
- DONAU_PROTOCOL_VERSION),
- GNUNET_JSON_pack_string ("base_url",
- DH_base_url),
- GNUNET_JSON_pack_string ("currency",
- DH_currency),
- GNUNET_JSON_pack_uint64 ("currency_fraction_digits",
- DH_currency_fraction_digits),
- GNUNET_JSON_pack_string ("asset_type",
- asset_type),
- GNUNET_JSON_pack_bool ("rewards_allowed",
- GNUNET_YES ==
- DH_enable_rewards),
- GNUNET_JSON_pack_data_auto ("master_public_key",
- &DH_master_public_key),
- GNUNET_JSON_pack_time_rel ("reserve_closing_delay",
- DH_reserve_closing_delay),
- GNUNET_JSON_pack_array_incref ("signkeys",
- signkeys),
- GNUNET_JSON_pack_array_incref ("recoup",
- recoup),
- GNUNET_JSON_pack_array_incref ("wads",
- json_object_get (wsh->json_reply,
- "wads")),
- GNUNET_JSON_pack_array_incref ("accounts",
- json_object_get (wsh->json_reply,
- "accounts")),
- GNUNET_JSON_pack_array_incref ("denominations",
- grouped_denominations),
- GNUNET_JSON_pack_timestamp ("list_issue_date",
- last_cherry_pick_date),
- GNUNET_JSON_pack_data_auto ("eddsa_pub",
- &donau_pub),
- GNUNET_JSON_pack_data_auto ("eddsa_sig",
- &donau_sig),
- GNUNET_JSON_pack_data_auto ("denominations_sig",
- &grouped_donau_sig));
- GNUNET_assert (NULL != keys);
-
- {
- char *keys_json;
- void *keys_jsonz;
- size_t keys_jsonz_size;
- int comp;
- char etag[sizeof (struct GNUNET_HashCode) * 2];
-
- /* Convert /keys response to UTF8-String */
- keys_json = json_dumps (keys,
- JSON_INDENT (2));
- json_decref (keys);
- GNUNET_assert (NULL != keys_json);
-
- /* Keep copy for later compression... */
- keys_jsonz = GNUNET_strdup (keys_json);
- keys_jsonz_size = strlen (keys_json);
-
- /* hash to compute etag */
- {
- struct GNUNET_HashCode ehash;
- char *end;
-
- GNUNET_CRYPTO_hash (keys_jsonz,
- keys_jsonz_size,
- &ehash);
- end = GNUNET_STRINGS_data_to_string (&ehash,
- sizeof (ehash),
- etag,
- sizeof (etag));
- *end = '\0';
- }
-
- /* Create uncompressed response */
- krd.response_uncompressed
- = MHD_create_response_from_buffer (keys_jsonz_size,
- keys_json,
- MHD_RESPMEM_MUST_FREE);
- GNUNET_assert (NULL != krd.response_uncompressed);
- GNUNET_assert (GNUNET_OK ==
- setup_general_response_headers (ksh,
- wsh,
- krd.response_uncompressed));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (krd.response_uncompressed,
- MHD_HTTP_HEADER_ETAG,
- etag));
- /* Also compute compressed version of /keys response */
- comp = TALER_MHD_body_compress (&keys_jsonz,
- &keys_jsonz_size);
- krd.response_compressed
- = MHD_create_response_from_buffer (keys_jsonz_size,
- keys_jsonz,
- MHD_RESPMEM_MUST_FREE);
- GNUNET_assert (NULL != krd.response_compressed);
- /* If the response is actually compressed, set the
- respective header. */
- GNUNET_assert ( (MHD_YES != comp) ||
- (MHD_YES ==
- MHD_add_response_header (krd.response_compressed,
- MHD_HTTP_HEADER_CONTENT_ENCODING,
- "deflate")) );
- GNUNET_assert (GNUNET_OK ==
- setup_general_response_headers (ksh,
- wsh,
- krd.response_compressed));
- /* Set cache control headers: our response varies depending on these
headers */
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (wsh->wire_reply,
- MHD_HTTP_HEADER_VARY,
- MHD_HTTP_HEADER_ACCEPT_ENCODING));
- /* Information is always public, revalidate after 1 day */
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (wsh->wire_reply,
- MHD_HTTP_HEADER_CACHE_CONTROL,
- "public,max-age=86400"));
- GNUNET_break (MHD_YES ==
- MHD_add_response_header (krd.response_compressed,
- MHD_HTTP_HEADER_ETAG,
- etag));
- krd.etag = GNUNET_strdup (etag);
- }
- krd.cherry_pick_date = last_cherry_pick_date;
- GNUNET_array_append (ksh->krd_array,
- ksh->krd_array_length,
- krd);
- return GNUNET_OK;
-}
-
-
-/**
- * Update the "/keys" responses in @a ksh, computing the detailed replies.
- *
- * This function is to recompute all (including cherry-picked) responses we
- * might want to return, based on the state already in @a ksh.
- *
- * @param[in,out] ksh state handle to update
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-finish_keys_response (struct DH_KeyStateHandle *ksh)
-{
- enum GNUNET_GenericReturnValue ret = GNUNET_SYSERR;
- json_t *recoup;
- struct SignKeyCtx sctx;
- json_t *grouped_denominations = NULL;
- struct GNUNET_TIME_Timestamp last_cherry_pick_date;
- struct GNUNET_CONTAINER_Heap *heap;
- struct GNUNET_HashContext *hash_context = NULL;
- struct GNUNET_HashCode grouped_hash_xor = {0};
- /* Remember if we have any denomination with age restriction */
- bool has_age_restricted_denomination = false;
-
- sctx.signkeys = json_array ();
- GNUNET_assert (NULL != sctx.signkeys);
- sctx.min_sk_frequency = GNUNET_TIME_UNIT_FOREVER_REL;
- GNUNET_CONTAINER_multipeermap_iterate (ksh->signkey_map,
- &add_sign_key_cb,
- &sctx);
- recoup = json_array ();
- GNUNET_assert (NULL != recoup);
- heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MAX);
- {
- struct DenomKeyCtx dkc = {
- .recoup = recoup,
- .heap = heap,
- .min_dk_frequency = GNUNET_TIME_UNIT_FOREVER_REL,
- };
-
- GNUNET_CONTAINER_multihashmap_iterate (ksh->denomkey_map,
- &add_denom_key_cb,
- &dkc);
- ksh->rekey_frequency
- = GNUNET_TIME_relative_min (dkc.min_dk_frequency,
- sctx.min_sk_frequency);
- }
-
- hash_context = GNUNET_CRYPTO_hash_context_start ();
-
- grouped_denominations = json_array ();
- GNUNET_assert (NULL != grouped_denominations);
-
- last_cherry_pick_date = GNUNET_TIME_UNIT_ZERO_TS;
-
- // FIXME: This block contains the implementation of the DEPRECATED
- // "denom_pubs" array along with the new grouped "denominations".
- // "denom_pubs" Will be removed sooner or later.
- {
- struct DH_DonationUnitKey *dk;
- struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
- /* GroupData is the value we store for each group meta-data */
- struct GroupData
- {
- /**
- * The json blob with the group meta-data and list of denominations
- */
- json_t *json;
-
- /**
- * xor of all hashes of denominations in that group
- */
- struct GNUNET_HashCode hash_xor;
- };
-
- denominations_by_group =
- GNUNET_CONTAINER_multihashmap_create (1024,
- GNUNET_NO /* NO, because keys are
only on the stack */
- );
-
-
- /* heap = min heap, sorted by start time */
- while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
- {
- if (GNUNET_TIME_timestamp_cmp (last_cherry_pick_date,
- !=,
- dk->meta.start) &&
- (! GNUNET_TIME_absolute_is_zero (last_cherry_pick_date.abs_time)) )
- {
- /*
- * This is not the first entry in the heap (because
last_cherry_pick_date !=
- * GNUNET_TIME_UNIT_ZERO_TS) and the previous entry had a different
- * start time. Therefore, we create a new entry in ksh.
- */
- struct GNUNET_HashCode hc;
-
- GNUNET_CRYPTO_hash_context_finish (
- GNUNET_CRYPTO_hash_context_copy (hash_context),
- &hc);
-
- if (GNUNET_OK !=
- create_krd (ksh,
- &hc,
- last_cherry_pick_date,
- sctx.signkeys,
- recoup,
- grouped_denominations,
- &grouped_hash_xor))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to generate key response data for %s\n",
- GNUNET_TIME_timestamp2s (last_cherry_pick_date));
- GNUNET_CRYPTO_hash_context_abort (hash_context);
- /* drain heap before destroying it */
- while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
- /* intentionally empty */;
- GNUNET_CONTAINER_heap_destroy (heap);
- goto CLEANUP;
- }
- }
-
- last_cherry_pick_date = dk->meta.start;
- /*
- * Group the denominations by {cipher, value}.
- *
- * For each group we save the group meta-data and the list of
- * denominations in this group as a json-blob in the multihashmap
- * denominations_by_group.
- */
- {
- static const char *denoms_key = "denoms";
- struct GroupData *group;
- json_t *list;
- json_t *entry;
- struct GNUNET_HashCode key;
- struct TALER_DenominationGroup meta = {
- .cipher = dk->denom_pub.cipher,
- .value = dk->meta.value
- };
-
- /* Search the group/JSON-blob for the key */
- TALER_denomination_group_get_key (&meta,
- &key);
- group = GNUNET_CONTAINER_multihashmap_get (
- denominations_by_group,
- &key);
- if (NULL == group)
- {
- /* There is no group for this meta-data yet, so we create a new
group */
- bool age_restricted = meta.age_mask.bits != 0;
- const char *cipher;
-
- group = GNUNET_new (struct GroupData);
- switch (meta.cipher)
- {
- case TALER_DENOMINATION_RSA:
- cipher = age_restricted ? "RSA+age_restricted" : "RSA";
- break;
- case TALER_DENOMINATION_CS:
- cipher = age_restricted ? "CS+age_restricted" : "CS";
- break;
- default:
- GNUNET_assert (false);
- }
-
- group->json = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("cipher",
- cipher),
- TALER_JSON_pack_amount ("value",
- &meta.value));
- GNUNET_assert (NULL != group->json);
-
- if (age_restricted)
- {
- int r = json_object_set_new (group->json,
- "age_mask",
- json_integer (meta.age_mask.bits));
-
- GNUNET_assert (0 == r);
-
- /* Remember that we have found at least _one_ age restricted
denomination */
- has_age_restricted_denomination = true;
- }
-
- /* Create a new array for the denominations in this group */
- list = json_array ();
- GNUNET_assert (NULL != list);
- GNUNET_assert (0 ==
- json_object_set_new (group->json,
- denoms_key,
- list));
- GNUNET_assert (
- GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_put (denominations_by_group,
- &key,
- group,
-
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
- }
-
- /* Now that we have found/created the right group, add the
- denomination to the list */
- {
- struct HelperDonationUnit *hd;
- struct GNUNET_JSON_PackSpec key_spec;
- bool private_key_lost;
-
- hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
- &dk->h_denom_pub.hash);
- private_key_lost
- = (NULL == hd) ||
- GNUNET_TIME_absolute_is_past (
- GNUNET_TIME_absolute_add (
- hd->start_time.abs_time,
- hd->validity_duration));
- switch (meta.cipher)
- {
- case TALER_DENOMINATION_RSA:
- key_spec =
- GNUNET_JSON_pack_rsa_public_key (
- "rsa_pub",
- dk->denom_pub.details.rsa_public_key);
- break;
- case TALER_DENOMINATION_CS:
- key_spec =
- GNUNET_JSON_pack_data_varsize (
- "cs_pub",
- &dk->denom_pub.details.cs_public_key,
- sizeof (dk->denom_pub.details.cs_public_key));
- break;
- default:
- GNUNET_assert (false);
- }
-
- entry = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("master_sig",
- &dk->master_sig),
- GNUNET_JSON_pack_allow_null (
- private_key_lost
- ? GNUNET_JSON_pack_bool ("lost",
- true)
- : GNUNET_JSON_pack_string ("dummy",
- NULL)),
- GNUNET_JSON_pack_timestamp ("stamp_start",
- dk->meta.start),
- GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw",
- dk->meta.expire_withdraw),
- GNUNET_JSON_pack_timestamp ("stamp_expire_deposit",
- dk->meta.expire_deposit),
- GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
- dk->meta.expire_legal),
- key_spec
- );
- GNUNET_assert (NULL != entry);
- }
-
- /* Build up the running xor of all hashes of the denominations in this
- group */
- GNUNET_CRYPTO_hash_xor (&dk->h_denom_pub.hash,
- &group->hash_xor,
- &group->hash_xor);
-
- /* Finally, add the denomination to the list of denominations in this
- group */
- list = json_object_get (group->json, denoms_key);
- GNUNET_assert (NULL != list);
- GNUNET_assert (true == json_is_array (list));
- GNUNET_assert (0 ==
- json_array_append_new (list, entry));
- }
- } /* loop over heap ends */
-
- /* Create the JSON-array of grouped denominations */
- if (0 <
- GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
- {
- struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
- struct GroupData *group = NULL;
-
- iter =
- GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
-
- while (GNUNET_OK ==
- GNUNET_CONTAINER_multihashmap_iterator_next (iter,
- NULL,
- (const
- void **) &group))
- {
- /* Add the XOR over all hashes of denominations in this group to the
group */
- GNUNET_assert (0 ==
- json_object_set_new (
- group->json,
- "hash",
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto (NULL,
- &group->hash_xor))));
-
- /* Add this group to the array */
- GNUNET_assert (0 ==
- json_array_append_new (
- grouped_denominations,
- group->json));
- /* Build the running XOR over all hash(_xor) */
- GNUNET_CRYPTO_hash_xor (&group->hash_xor,
- &grouped_hash_xor,
- &grouped_hash_xor);
- GNUNET_free (group);
- }
- GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
-
- }
-
- GNUNET_CONTAINER_multihashmap_destroy (denominations_by_group);
- }
-
- GNUNET_CONTAINER_heap_destroy (heap);
- if (! GNUNET_TIME_absolute_is_zero (last_cherry_pick_date.abs_time))
- {
- struct GNUNET_HashCode hc;
-
- GNUNET_CRYPTO_hash_context_finish (hash_context,
- &hc);
- if (GNUNET_OK !=
- create_krd (ksh,
- &hc,
- last_cherry_pick_date,
- sctx.signkeys,
- recoup,
- grouped_denominations,
- &grouped_hash_xor))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to generate key response data for %s\n",
- GNUNET_TIME_timestamp2s (last_cherry_pick_date));
- goto CLEANUP;
- }
- ksh->management_only = false;
-
- /* Sanity check: Make sure that age restriction is enabled IFF at least
- * one age restricted denomination exist */
- if (! has_age_restricted_denomination && DH_age_restriction_enabled)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Age restriction is enabled, but NO denominations with age
restriction found!\n");
- goto CLEANUP;
- }
- else if (has_age_restricted_denomination && ! DH_age_restriction_enabled)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Age restriction is NOT enabled, but denominations with age
restriction found!\n");
- goto CLEANUP;
- }
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "No denomination keys available. Refusing to generate /keys
response.\n");
- GNUNET_CRYPTO_hash_context_abort (hash_context);
- }
-
- ret = GNUNET_OK;
-
-CLEANUP:
- json_decref (grouped_denominations);
- json_decref (sctx.signkeys);
- json_decref (recoup);
- return ret;
-}
-
-
-/**
- * Create a key state.
- *
- * @param[in] hs helper state to (re)use, NULL if not available
- * @param management_only if we should NOT run 'finish_keys_response()'
- * because we only need the state for the /management/keys API
- * @return NULL on error (i.e. failed to access database)
- */
-static struct DH_KeyStateHandle *
-build_key_state (struct HelperState *hs,
- bool management_only)
-{
- struct DH_KeyStateHandle *ksh;
- enum GNUNET_DB_QueryStatus qs;
-
- ksh = GNUNET_new (struct DH_KeyStateHandle);
- ksh->signature_expires = GNUNET_TIME_UNIT_FOREVER_TS;
- ksh->reload_time = GNUNET_TIME_timestamp_get ();
- /* We must use the key_generation from when we STARTED the process! */
- ksh->key_generation = key_generation;
- if (NULL == hs)
- {
- ksh->helpers = GNUNET_new (struct HelperState);
- if (GNUNET_OK !=
- setup_key_helpers (ksh->helpers))
- {
- GNUNET_free (ksh->helpers);
- GNUNET_assert (NULL == ksh->management_keys_reply);
- GNUNET_free (ksh);
- return NULL;
- }
- }
- else
- {
- ksh->helpers = hs;
- }
- ksh->denomkey_map = GNUNET_CONTAINER_multihashmap_create (1024,
- true);
- ksh->signkey_map = GNUNET_CONTAINER_multipeermap_create (32,
- false /* MUST be
false! */
- );
- /* NOTE: fetches master-signed signkeys, but ALSO those that were revoked! */
- GNUNET_break (GNUNET_OK ==
- DH_plugin->preflight (DH_plugin->cls));
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
- destroy_key_state (ksh,
- true);
- return NULL;
- }
- qs = DH_plugin->iterate_denominations (DH_plugin->cls,
- &denomination_info_cb,
- ksh);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR != qs);
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
- destroy_key_state (ksh,
- true);
- return NULL;
- }
- /* NOTE: ONLY fetches non-revoked AND master-signed signkeys! */
- qs = DH_plugin->iterate_active_signkeys (DH_plugin->cls,
- &signkey_info_cb,
- ksh);
- if (qs < 0)
- {
- GNUNET_break (0);
- destroy_key_state (ksh,
- true);
- return NULL;
- }
- qs = DH_plugin->iterate_auditor_denominations (DH_plugin->cls,
- &auditor_denom_cb,
- ksh);
- if (qs < 0)
- {
- GNUNET_break (0);
- destroy_key_state (ksh,
- true);
- return NULL;
- }
- qs = DH_plugin->iterate_active_auditors (DH_plugin->cls,
- &auditor_info_cb,
- ksh);
- if (qs < 0)
- {
- GNUNET_break (0);
- destroy_key_state (ksh,
- true);
- return NULL;
- }
-
- if (management_only)
- {
- ksh->management_only = true;
- return ksh;
- }
-
- if (GNUNET_OK !=
- finish_keys_response (ksh))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Could not finish /keys response (likely no signing keys
available yet)\n");
- destroy_key_state (ksh,
- true);
- return NULL;
- }
-
- return ksh;
-}
-
-
-void
-DH_keys_update_states ()
-{
- struct GNUNET_DB_EventHeaderP es = {
- .size = htons (sizeof (es)),
- .type = htons (TALER_DBEVENT_DONAU_KEYS_UPDATED),
- };
-
- DH_plugin->event_notify (DH_plugin->cls,
- &es,
- NULL,
- 0);
- key_generation++;
- DH_resume_keys_requests (false);
-}
-
-
-static struct DH_KeyStateHandle *
-keys_get_state (bool management_only)
-{
- struct DH_KeyStateHandle *old_ksh;
- struct DH_KeyStateHandle *ksh;
-
- old_ksh = key_state;
- if (NULL == old_ksh)
- {
- ksh = build_key_state (NULL,
- management_only);
- if (NULL == ksh)
- return NULL;
- key_state = ksh;
- return ksh;
- }
- if ( (old_ksh->key_generation < key_generation) ||
- (GNUNET_TIME_absolute_is_past (old_ksh->signature_expires.abs_time)) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Rebuilding /keys, generation upgrade from %llu to %llu\n",
- (unsigned long long) old_ksh->key_generation,
- (unsigned long long) key_generation);
- ksh = build_key_state (old_ksh->helpers,
- management_only);
- key_state = ksh;
- old_ksh->helpers = NULL;
- destroy_key_state (old_ksh,
- false);
- return ksh;
- }
- sync_key_helpers (old_ksh->helpers);
- return old_ksh;
-}
-
-
-struct DH_KeyStateHandle *
-DH_keys_get_state_for_management_only (void)
-{
- return keys_get_state (true);
-}
-
-
-struct DH_KeyStateHandle *
-DH_keys_get_state (void)
-{
- struct DH_KeyStateHandle *ksh;
-
- ksh = keys_get_state (false);
- if (NULL == ksh)
- return NULL;
-
- if (ksh->management_only)
- {
- if (GNUNET_OK !=
- finish_keys_response (ksh))
- return NULL;
- }
-
- return ksh;
-}
struct DH_DonationUnitKey *
@@ -2497,45 +1362,6 @@ DH_keys_denomination_cs_batch_r_pub (
r_pubs);
}
-
-void
-DH_keys_denomination_revoke (const struct TALER_DenominationHashP *h_denom_pub)
-{
- struct DH_KeyStateHandle *ksh;
- struct HelperDonationUnit *hd;
-
- ksh = DH_keys_get_state ();
- if (NULL == ksh)
- {
- GNUNET_break (0);
- return;
- }
- hd = GNUNET_CONTAINER_multihashmap_get (ksh->helpers->denom_keys,
- &h_denom_pub->hash);
- if (NULL == hd)
- {
- GNUNET_break (0);
- return;
- }
- switch (hd->denom_pub.cipher)
- {
- case TALER_DENOMINATION_RSA:
- TALER_CRYPTO_helper_rsa_revoke (ksh->helpers->rsadh,
- &hd->h_details.h_rsa);
- DH_keys_update_states ();
- return;
- case TALER_DENOMINATION_CS:
- TALER_CRYPTO_helper_cs_revoke (ksh->helpers->csdh,
- &hd->h_details.h_cs);
- DH_keys_update_states ();
- return;
- default:
- GNUNET_break (0);
- return;
- }
-}
-
-
enum TALER_ErrorCode
DH_keys_donau_sign_ (
const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
@@ -2559,95 +1385,6 @@ DH_keys_donau_sign_ (
sig);
}
-
-enum TALER_ErrorCode
-DH_keys_donau_sign2_ (
- void *cls,
- const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
- struct DONAU_DonauPublicKeyP *pub,
- struct TALER_DonauSignatureP *sig)
-{
- struct DH_KeyStateHandle *ksh = cls;
- enum TALER_ErrorCode ec;
-
- DH_METRICS_num_signatures[DH_MT_SIGNATURE_EDDSA]++;
- ec = TALER_CRYPTO_helper_esign_sign_ (ksh->helpers->esh,
- purpose,
- pub,
- sig);
- if (TALER_EC_NONE != ec)
- return ec;
- {
- /* Here we check here that 'pub' is set to an donau public key that is
- actually signed by the master key! Otherwise, we happily continue to
- use key material even if the offline signatures have not been made
- yet! */
- struct GNUNET_PeerIdentity pid;
- struct SigningKey *sk;
-
- pid.public_key = pub->eddsa_pub;
- sk = GNUNET_CONTAINER_multipeermap_get (ksh->signkey_map,
- &pid);
- if (NULL == sk)
- {
- /* just to be safe, zero out the (valid) signature, as the key
- should not or no longer be used */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Cannot sign, offline key signatures are missing!\n");
- memset (sig,
- 0,
- sizeof (*sig));
- return TALER_EC_DONAU_SIGNKEY_HELPER_BUG;
- }
- }
- return ec;
-}
-
-
-void
-DH_keys_donau_revoke (const struct DONAU_DonauPublicKeyP *donau_pub)
-{
- struct DH_KeyStateHandle *ksh;
-
- ksh = DH_keys_get_state ();
- if (NULL == ksh)
- {
- GNUNET_break (0);
- return;
- }
- TALER_CRYPTO_helper_esign_revoke (ksh->helpers->esh,
- donau_pub);
- DH_keys_update_states ();
-}
-
-
-/**
- * Comparator used for a binary search by cherry_pick_date for @a key in the
- * `struct KeysResponseData` array. See libc's qsort() and bsearch() functions.
- *
- * @param key pointer to a `struct GNUNET_TIME_Timestamp`
- * @param value pointer to a `struct KeysResponseData` array entry
- * @return 0 if time matches, -1 if key is smaller, 1 if key is larger
- */
-static int
-krd_search_comparator (const void *key,
- const void *value)
-{
- const struct GNUNET_TIME_Timestamp *kd = key;
- const struct KeysResponseData *krd = value;
-
- if (GNUNET_TIME_timestamp_cmp (*kd,
- >,
- krd->cherry_pick_date))
- return -1;
- if (GNUNET_TIME_timestamp_cmp (*kd,
- <,
- krd->cherry_pick_date))
- return 1;
- return 0;
-}
-
-
MHD_RESULT
DH_keys_get_handler (struct DH_RequestContext *rc,
const char *const args[])
@@ -2762,217 +1499,4 @@ DH_keys_get_handler (struct DH_RequestContext *rc,
}
-/**
- * Closure for #add_future_denomkey_cb and #add_future_signkey_cb.
- */
-struct FutureBuilderContext
-{
- /**
- * Our key state.
- */
- struct DH_KeyStateHandle *ksh;
-
- /**
- * Array of denomination keys.
- */
- json_t *denoms;
-
- /**
- * Array of signing keys.
- */
- json_t *signkeys;
-
-};
-
-
-/**
- * Function called on all of our current and future denomination keys
- * known to the helper process. Filters out those that are current
- * and adds the remaining denomination keys (with their configuration
- * data) to the JSON array.
- *
- * @param cls the `struct FutureBuilderContext *`
- * @param h_denom_pub hash of the denomination public key
- * @param value a `struct HelperDonationUnit`
- * @return #GNUNET_OK (continue to iterate)
- */
-static enum GNUNET_GenericReturnValue
-add_future_denomkey_cb (void *cls,
- const struct GNUNET_HashCode *h_denom_pub,
- void *value)
-{
- struct FutureBuilderContext *fbc = cls;
- struct HelperDonationUnit *hd = value;
- struct DH_DonationUnitKey *dk;
- struct DONAUDB_DenominationKeyMetaData meta = {0};
-
- dk = GNUNET_CONTAINER_multihashmap_get (fbc->ksh->denomkey_map,
- h_denom_pub);
- if (NULL != dk)
- return GNUNET_OK; /* skip: this key is already active! */
- if (GNUNET_TIME_relative_is_zero (hd->validity_duration))
- return GNUNET_OK; /* this key already expired! */
- meta.start = hd->start_time;
- meta.expire_withdraw = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (meta.start.abs_time,
- hd->validity_duration));
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- fbc->denoms,
- GNUNET_JSON_PACK (
- TALER_JSON_pack_amount ("value",
- &meta.value),
- GNUNET_JSON_pack_timestamp ("stamp_start",
- meta.start),
- GNUNET_JSON_pack_timestamp ("stamp_expire_withdraw",
- meta.expire_withdraw),
- GNUNET_JSON_pack_timestamp ("stamp_expire_deposit",
- meta.expire_deposit),
- GNUNET_JSON_pack_timestamp ("stamp_expire_legal",
- meta.expire_legal),
- TALER_JSON_pack_denom_pub ("denom_pub",
- &hd->denom_pub),
- GNUNET_JSON_pack_data_auto ("denom_secmod_sig",
- &hd->sm_sig),
- GNUNET_JSON_pack_string ("section_name",
- hd->section_name))));
- return GNUNET_OK;
-}
-
-
-/**
- * Function called on all of our current and future donau signing keys
- * known to the helper process. Filters out those that are current
- * and adds the remaining signing keys (with their configuration
- * data) to the JSON array.
- *
- * @param cls the `struct FutureBuilderContext *`
- * @param pid actually the donau public key (type disguised)
- * @param value a `struct HelperDonationUnit`
- * @return #GNUNET_OK (continue to iterate)
- */
-static enum GNUNET_GenericReturnValue
-add_future_signkey_cb (void *cls,
- const struct GNUNET_PeerIdentity *pid,
- void *value)
-{
- struct FutureBuilderContext *fbc = cls;
- struct HelperSignkey *hsk = value;
- struct SigningKey *sk;
- struct GNUNET_TIME_Timestamp stamp_expire;
- struct GNUNET_TIME_Timestamp legal_end;
-
- sk = GNUNET_CONTAINER_multipeermap_get (fbc->ksh->signkey_map,
- pid);
- if (NULL != sk)
- return GNUNET_OK; /* skip: this key is already active */
- if (GNUNET_TIME_relative_is_zero (hsk->validity_duration))
- return GNUNET_OK; /* this key already expired! */
- stamp_expire = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (hsk->start_time.abs_time,
- hsk->validity_duration));
- legal_end = GNUNET_TIME_absolute_to_timestamp (
- GNUNET_TIME_absolute_add (stamp_expire.abs_time,
- signkey_legal_duration));
- GNUNET_assert (0 ==
- json_array_append_new (
- fbc->signkeys,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("key",
- &hsk->donau_pub),
- GNUNET_JSON_pack_timestamp ("stamp_start",
- hsk->start_time),
- GNUNET_JSON_pack_timestamp ("stamp_expire",
- stamp_expire),
- GNUNET_JSON_pack_timestamp ("stamp_end",
- legal_end),
- GNUNET_JSON_pack_data_auto ("signkey_secmod_sig",
- &hsk->sm_sig))));
- return GNUNET_OK;
-}
-
-
-MHD_RESULT
-DH_keys_management_get_keys_handler (const struct DH_RequestHandler *rh,
- struct MHD_Connection *connection)
-{
- struct DH_KeyStateHandle *ksh;
- json_t *reply;
-
- (void) rh;
- ksh = DH_keys_get_state_for_management_only ();
- if (NULL == ksh)
- {
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_SERVICE_UNAVAILABLE,
- TALER_EC_DONAU_GENERIC_KEYS_MISSING,
- "no key state");
- }
- sync_key_helpers (ksh->helpers);
- if (NULL == ksh->management_keys_reply)
- {
- struct FutureBuilderContext fbc = {
- .ksh = ksh,
- .denoms = json_array (),
- .signkeys = json_array ()
- };
-
- if ( (GNUNET_is_zero (&denom_rsa_sm_pub)) &&
- (GNUNET_is_zero (&denom_cs_sm_pub)) )
- {
- /* Either IPC failed, or neither helper had any denominations
configured. */
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_GATEWAY,
-
TALER_EC_DONAU_DENOMINATION_HELPER_UNAVAILABLE,
- NULL);
- }
- if (GNUNET_is_zero (&esign_sm_pub))
- {
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_GATEWAY,
-
TALER_EC_DONAU_SIGNKEY_HELPER_UNAVAILABLE,
- NULL);
- }
- GNUNET_assert (NULL != fbc.denoms);
- GNUNET_assert (NULL != fbc.signkeys);
- GNUNET_CONTAINER_multihashmap_iterate (ksh->helpers->denom_keys,
- &add_future_denomkey_cb,
- &fbc);
- GNUNET_CONTAINER_multipeermap_iterate (ksh->helpers->esign_keys,
- &add_future_signkey_cb,
- &fbc);
- reply = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("future_denoms",
- fbc.denoms),
- GNUNET_JSON_pack_array_steal ("future_signkeys",
- fbc.signkeys),
- GNUNET_JSON_pack_data_auto ("master_pub",
- &DH_master_public_key),
- GNUNET_JSON_pack_data_auto ("denom_secmod_public_key",
- &denom_rsa_sm_pub),
- GNUNET_JSON_pack_data_auto ("denom_secmod_cs_public_key",
- &denom_cs_sm_pub),
- GNUNET_JSON_pack_data_auto ("signkey_secmod_public_key",
- &esign_sm_pub));
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Returning GET /management/keys response:\n");
- if (NULL == reply)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
-
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
- NULL);
- GNUNET_assert (NULL == ksh->management_keys_reply);
- ksh->management_keys_reply = reply;
- }
- else
- {
- reply = ksh->management_keys_reply;
- }
- return TALER_MHD_reply_json (connection,
- reply,
- MHD_HTTP_OK);
-}
-
-
/* end of donau-httpd_keys.c */
diff --git a/src/donau/donau-httpd_responses.c
b/src/donau/donau-httpd_responses.c
deleted file mode 100644
index c2c650f..0000000
--- a/src/donau/donau-httpd_responses.c
+++ /dev/null
@@ -1,560 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_responses.c
- * @brief API for generating generic replies of the donau; these
- * functions are called DH_RESPONSE_reply_ and they generate
- * and queue MHD response objects for a given connection.
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <microhttpd.h>
-#include <zlib.h>
-#include "donau-httpd_responses.h"
-#include <taler/taler_util.h>
-#include "taler/taler_json_lib.h"
-#include "taler/taler_mhd_lib.h"
-#include "donau-httpd_keys.h"
-
-
-// /**
-// * Compile the transaction history of a coin into a JSON object.
-// *
-// * @param coin_pub public key of the coin
-// * @param tl transaction history to JSON-ify
-// * @return json representation of the @a rh, NULL on error
-// */
-// json_t *
-// DH_RESPONSE_compile_transaction_history (
-// const struct TALER_CoinSpendPublicKeyP *coin_pub,
-// const struct DONAUDB_TransactionList *tl)
-// {
-// json_t *history;
-
-// history = json_array ();
-// if (NULL == history)
-// {
-// GNUNET_break (0); /* out of memory!? */
-// return NULL;
-// }
-// for (const struct DONAUDB_TransactionList *pos = tl;
-// NULL != pos;
-// pos = pos->next)
-// {
-// switch (pos->type)
-// {
-// case DONAUDB_TT_DEPOSIT:
-// {
-// const struct DONAUDB_DepositListEntry *deposit =
-// pos->details.deposit;
-// struct TALER_CharityWireHashP h_wire;
-
-// TALER_charity_wire_signature_hash (deposit->receiver_wire_account,
-// &deposit->wire_salt,
-// &h_wire);
-// #if ENABLE_SANITY_CHECKS
-// /* internal sanity check before we hand out a bogus sig... */
-// DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
-// if (GNUNET_OK !=
-// TALER_wallet_deposit_verify (
-// &deposit->amount_with_fee,
-// &deposit->deposit_fee,
-// &h_wire,
-// &deposit->h_contract_terms,
-// deposit->no_wallet_data_hash
-// ? NULL
-// : &deposit->wallet_data_hash,
-// deposit->no_age_commitment
-// ? NULL
-// : &deposit->h_age_commitment,
-// &deposit->h_policy,
-// &deposit->h_denom_pub,
-// deposit->timestamp,
-// &deposit->charity_pub,
-// deposit->refund_deadline,
-// coin_pub,
-// &deposit->csig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// #endif
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "DEPOSIT"),
-// TALER_JSON_pack_amount ("amount",
-// &deposit->amount_with_fee),
-// TALER_JSON_pack_amount ("deposit_fee",
-// &deposit->deposit_fee),
-// GNUNET_JSON_pack_timestamp ("timestamp",
-// deposit->timestamp),
-// GNUNET_JSON_pack_allow_null (
-// GNUNET_JSON_pack_timestamp ("refund_deadline",
-// deposit->refund_deadline)),
-// GNUNET_JSON_pack_data_auto ("charity_pub",
-// &deposit->charity_pub),
-// GNUNET_JSON_pack_data_auto ("h_contract_terms",
-// &deposit->h_contract_terms),
-// GNUNET_JSON_pack_data_auto ("h_wire",
-// &h_wire),
-// GNUNET_JSON_pack_allow_null (
-// deposit->no_age_commitment ?
-// GNUNET_JSON_pack_string (
-// "h_age_commitment", NULL) :
-// GNUNET_JSON_pack_data_auto ("h_age_commitment",
-// &deposit->h_age_commitment)),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &deposit->csig))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// break;
-// }
-// case DONAUDB_TT_MELT:
-// {
-// const struct DONAUDB_MeltListEntry *melt =
-// pos->details.melt;
-// const struct TALER_AgeCommitmentHash *phac = NULL;
-
-// #if ENABLE_SANITY_CHECKS
-// DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
-// if (GNUNET_OK !=
-// TALER_wallet_melt_verify (
-// &melt->amount_with_fee,
-// &melt->melt_fee,
-// &melt->rc,
-// &melt->h_denom_pub,
-// &melt->h_age_commitment,
-// coin_pub,
-// &melt->coin_sig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// #endif
-
-// /* Age restriction is optional. We communicate a NULL value to
-// * JSON_PACK below */
-// if (! melt->no_age_commitment)
-// phac = &melt->h_age_commitment;
-
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "MELT"),
-// TALER_JSON_pack_amount ("amount",
-// &melt->amount_with_fee),
-// TALER_JSON_pack_amount ("melt_fee",
-// &melt->melt_fee),
-// GNUNET_JSON_pack_data_auto ("rc",
-// &melt->rc),
-// GNUNET_JSON_pack_allow_null (
-// GNUNET_JSON_pack_data_auto ("h_age_commitment",
-// phac)),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &melt->coin_sig))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// }
-// break;
-// case DONAUDB_TT_REFUND:
-// {
-// const struct DONAUDB_RefundListEntry *refund =
-// pos->details.refund;
-// struct TALER_Amount value;
-
-// #if ENABLE_SANITY_CHECKS
-// DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
-// if (GNUNET_OK !=
-// TALER_charity_refund_verify (
-// coin_pub,
-// &refund->h_contract_terms,
-// refund->rtransaction_id,
-// &refund->refund_amount,
-// &refund->charity_pub,
-// &refund->charity_sig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// #endif
-// if (0 >
-// TALER_amount_subtract (&value,
-// &refund->refund_amount,
-// &refund->refund_fee))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "REFUND"),
-// TALER_JSON_pack_amount ("amount",
-// &value),
-// TALER_JSON_pack_amount ("refund_fee",
-// &refund->refund_fee),
-// GNUNET_JSON_pack_data_auto ("h_contract_terms",
-// &refund->h_contract_terms),
-// GNUNET_JSON_pack_data_auto ("charity_pub",
-// &refund->charity_pub),
-// GNUNET_JSON_pack_uint64 ("rtransaction_id",
-// refund->rtransaction_id),
-// GNUNET_JSON_pack_data_auto ("charity_sig",
-// &refund->charity_sig))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// }
-// break;
-// case DONAUDB_TT_OLD_COIN_RECOUP:
-// {
-// struct DONAUDB_RecoupRefreshListEntry *pr =
-// pos->details.old_coin_recoup;
-// struct DONAU_DonauPublicKeyP epub;
-// struct TALER_DonauSignatureP esig;
-
-// if (TALER_EC_NONE !=
-// TALER_donau_online_confirm_recoup_refresh_sign (
-// &DH_keys_donau_sign_,
-// pr->timestamp,
-// &pr->value,
-// &pr->coin.coin_pub,
-// &pr->old_coin_pub,
-// &epub,
-// &esig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// /* NOTE: we could also provide coin_pub's coin_sig, denomination
key hash and
-// the denomination key's RSA signature over coin_pub, but as the
-// wallet should really already have this information (and cannot
-// check or do anything with it anyway if it doesn't), it seems
-// strictly unnecessary. */
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "OLD-COIN-RECOUP"),
-// TALER_JSON_pack_amount ("amount",
-// &pr->value),
-// GNUNET_JSON_pack_data_auto ("donau_sig",
-// &esig),
-// GNUNET_JSON_pack_data_auto ("donau_pub",
-// &epub),
-// GNUNET_JSON_pack_data_auto ("coin_pub",
-// &pr->coin.coin_pub),
-// GNUNET_JSON_pack_timestamp ("timestamp",
-// pr->timestamp))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// break;
-// }
-// case DONAUDB_TT_RECOUP:
-// {
-// const struct DONAUDB_RecoupListEntry *recoup =
-// pos->details.recoup;
-// struct DONAU_DonauPublicKeyP epub;
-// struct TALER_DonauSignatureP esig;
-
-// if (TALER_EC_NONE !=
-// TALER_donau_online_confirm_recoup_sign (
-// &DH_keys_donau_sign_,
-// recoup->timestamp,
-// &recoup->value,
-// coin_pub,
-// &recoup->reserve_pub,
-// &epub,
-// &esig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "RECOUP"),
-// TALER_JSON_pack_amount ("amount",
-// &recoup->value),
-// GNUNET_JSON_pack_data_auto ("donau_sig",
-// &esig),
-// GNUNET_JSON_pack_data_auto ("donau_pub",
-// &epub),
-// GNUNET_JSON_pack_data_auto ("reserve_pub",
-// &recoup->reserve_pub),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &recoup->coin_sig),
-// GNUNET_JSON_pack_data_auto ("coin_blind",
-// &recoup->coin_blind),
-// GNUNET_JSON_pack_data_auto ("reserve_pub",
-// &recoup->reserve_pub),
-// GNUNET_JSON_pack_timestamp ("timestamp",
-// recoup->timestamp))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// }
-// break;
-// case DONAUDB_TT_RECOUP_REFRESH:
-// {
-// struct DONAUDB_RecoupRefreshListEntry *pr =
-// pos->details.recoup_refresh;
-// struct DONAU_DonauPublicKeyP epub;
-// struct TALER_DonauSignatureP esig;
-
-// if (TALER_EC_NONE !=
-// TALER_donau_online_confirm_recoup_refresh_sign (
-// &DH_keys_donau_sign_,
-// pr->timestamp,
-// &pr->value,
-// coin_pub,
-// &pr->old_coin_pub,
-// &epub,
-// &esig))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// /* NOTE: we could also provide coin_pub's coin_sig, denomination key
-// hash and the denomination key's RSA signature over coin_pub, but
as
-// the wallet should really already have this information (and
cannot
-// check or do anything with it anyway if it doesn't), it seems
-// strictly unnecessary. */
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "RECOUP-REFRESH"),
-// TALER_JSON_pack_amount ("amount",
-// &pr->value),
-// GNUNET_JSON_pack_data_auto ("donau_sig",
-// &esig),
-// GNUNET_JSON_pack_data_auto ("donau_pub",
-// &epub),
-// GNUNET_JSON_pack_data_auto ("old_coin_pub",
-// &pr->old_coin_pub),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &pr->coin_sig),
-// GNUNET_JSON_pack_data_auto ("coin_blind",
-// &pr->coin_blind),
-// GNUNET_JSON_pack_timestamp ("timestamp",
-// pr->timestamp))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// break;
-// }
-
-// case DONAUDB_TT_PURSE_DEPOSIT:
-// {
-// struct DONAUDB_PurseDepositListEntry *pd
-// = pos->details.purse_deposit;
-// const struct TALER_AgeCommitmentHash *phac = NULL;
-
-// if (! pd->no_age_commitment)
-// phac = &pd->h_age_commitment;
-
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "PURSE-DEPOSIT"),
-// TALER_JSON_pack_amount ("amount",
-// &pd->amount),
-// GNUNET_JSON_pack_string ("donau_base_url",
-// NULL == pd->donau_base_url
-// ? DH_base_url
-// : pd->donau_base_url),
-// GNUNET_JSON_pack_allow_null (
-// GNUNET_JSON_pack_data_auto ("h_age_commitment",
-// phac)),
-// GNUNET_JSON_pack_data_auto ("purse_pub",
-// &pd->purse_pub),
-// GNUNET_JSON_pack_bool ("refunded",
-// pd->refunded),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &pd->coin_sig))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// break;
-// }
-
-// case DONAUDB_TT_PURSE_REFUND:
-// {
-// const struct DONAUDB_PurseRefundListEntry *prefund =
-// pos->details.purse_refund;
-// struct TALER_Amount value;
-// enum TALER_ErrorCode ec;
-// struct DONAU_DonauPublicKeyP epub;
-// struct TALER_DonauSignatureP esig;
-
-// if (0 >
-// TALER_amount_subtract (&value,
-// &prefund->refund_amount,
-// &prefund->refund_fee))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// ec = TALER_donau_online_purse_refund_sign (
-// &DH_keys_donau_sign_,
-// &value,
-// &prefund->refund_fee,
-// coin_pub,
-// &prefund->purse_pub,
-// &epub,
-// &esig);
-// if (TALER_EC_NONE != ec)
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "PURSE-REFUND"),
-// TALER_JSON_pack_amount ("amount",
-// &value),
-// TALER_JSON_pack_amount ("refund_fee",
-// &prefund->refund_fee),
-// GNUNET_JSON_pack_data_auto ("donau_sig",
-// &esig),
-// GNUNET_JSON_pack_data_auto ("donau_pub",
-// &epub),
-// GNUNET_JSON_pack_data_auto ("purse_pub",
-// &prefund->purse_pub))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// }
-// break;
-
-// case DONAUDB_TT_RESERVE_OPEN:
-// {
-// struct DONAUDB_ReserveOpenListEntry *role
-// = pos->details.reserve_open;
-
-// if (0 !=
-// json_array_append_new (
-// history,
-// GNUNET_JSON_PACK (
-// GNUNET_JSON_pack_string ("type",
-// "RESERVE-OPEN-DEPOSIT"),
-// TALER_JSON_pack_amount ("coin_contribution",
-// &role->coin_contribution),
-// GNUNET_JSON_pack_data_auto ("reserve_sig",
-// &role->reserve_sig),
-// GNUNET_JSON_pack_data_auto ("coin_sig",
-// &role->coin_sig))))
-// {
-// GNUNET_break (0);
-// json_decref (history);
-// return NULL;
-// }
-// break;
-// }
-// }
-// }
-// return history;
-// }
-
-
-// MHD_RESULT
-// DH_RESPONSE_reply_unknown_denom_pub_hash (
-// struct MHD_Connection *connection,
-// const struct TALER_DenominationHashP *dph)
-// {
-// struct DONAU_DonauPublicKeyP epub;
-// struct TALER_DonauSignatureP esig;
-// struct GNUNET_TIME_Timestamp now;
-// enum TALER_ErrorCode ec;
-
-// now = GNUNET_TIME_timestamp_get ();
-// ec = TALER_donau_online_denomination_unknown_sign (
-// &DH_keys_donau_sign_,
-// now,
-// dph,
-// &epub,
-// &esig);
-// if (TALER_EC_NONE != ec)
-// {
-// GNUNET_break (0);
-// return TALER_MHD_reply_with_error (connection,
-// MHD_HTTP_INTERNAL_SERVER_ERROR,
-// ec,
-// NULL);
-// }
-// return TALER_MHD_REPLY_JSON_PACK (
-// connection,
-// MHD_HTTP_NOT_FOUND,
-// TALER_JSON_pack_ec (TALER_EC_DONAU_GENERIC_DENOMINATION_KEY_UNKNOWN),
-// GNUNET_JSON_pack_timestamp ("timestamp",
-// now),
-// GNUNET_JSON_pack_data_auto ("donau_pub",
-// &epub),
-// GNUNET_JSON_pack_data_auto ("donau_sig",
-// &esig),
-// GNUNET_JSON_pack_data_auto ("h_denom_pub",
-// dph));
-// }
-
-
-/* end of taler-donau-httpd_responses.c */
diff --git a/src/donau/donau-httpd_responses.h
b/src/donau/donau-httpd_responses.h
deleted file mode 100644
index 8970467..0000000
--- a/src/donau/donau-httpd_responses.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- 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 Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_responses.h
- * @brief API for generating generic replies of the donau; these
- * functions are called DH_RESPONSE_reply_ and they generate
- * and queue MHD response objects for a given connection.
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_RESPONSES_H
-#define DONAU_HTTPD_RESPONSES_H
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include "taler/taler_error_codes.h"
-#include "donau-httpd.h"
-#include "donau-httpd_db.h"
-#include "donaudb_lib.h"
-#include <gnunet/gnunet_mhd_compat.h>
-
-
-/**
- * Compile the history of a reserve into a JSON object.
- *
- * @param rh reserve history to JSON-ify
- * @return json representation of the @a rh, NULL on error
- */
-//json_t *
-//DH_RESPONSE_compile_reserve_history (
-// const struct DONAUDB_ReserveHistory *rh);
-
-
-/**
- * Send assertion that the given denomination key hash
- * is unknown to us at this time.
- *
- * @param connection connection to the client
- * @param dph denomination public key hash
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_unknown_denom_pub_hash (
- struct MHD_Connection *connection,
- const struct TALER_DenominationHashP *dph);
-
-
-/**
- * Return error message indicating that a reserve had
- * an insufficient balance for the given operation.
- *
- * @param connection connection to the client
- * @param ec specific error code to return with the reserve history
- * @param balance_required the balance required for the operation
- * @param reserve_pub the reserve with insufficient balance
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_reserve_insufficient_balance (
- struct MHD_Connection *connection,
- enum TALER_ErrorCode ec,
- const struct TALER_Amount *balance_required,
- const struct TALER_ReservePublicKeyP *reserve_pub);
-
-
-/**
- * Send information that an AML process is blocking
- * the operation right now.
- *
- * @param connection connection to the client
- * @param status current AML status
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_aml_blocked (struct MHD_Connection *connection,
- enum TALER_AmlDecisionState status);
-
-
-/**
- * Send assertion that the given denomination key hash
- * is not usable (typically expired) at this time.
- *
- * @param connection connection to the client
- * @param dph denomination public key hash
- * @param ec error code to use
- * @param oper name of the operation that is not allowed at this time
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_expired_denom_pub_hash (
- struct MHD_Connection *connection,
- const struct TALER_DenominationHashP *dph,
- enum TALER_ErrorCode ec,
- const char *oper);
-
-
-/**
- * Send assertion that the given denomination cannot be used for this
operation.
- *
- * @param connection connection to the client
- * @param dph denomination public key hash
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_invalid_denom_cipher_for_operation (
- struct MHD_Connection *connection,
- const struct TALER_DenominationHashP *dph);
-
-
-/**
- * Send proof that a request is invalid to client because of
- * insufficient funds. This function will create a message with all
- * of the operations affecting the coin that demonstrate that the coin
- * has insufficient value.
- *
- * @param connection connection to the client
- * @param ec error code to return
- * @param h_denom_pub hash of the denomination of the coin
- * @param coin_pub public key of the coin
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_coin_insufficient_funds (
- struct MHD_Connection *connection,
- enum TALER_ErrorCode ec,
- const struct TALER_DenominationHashP *h_denom_pub,
- const struct TALER_CoinSpendPublicKeyP *coin_pub);
-
-/**
- * Fundamental details about a purse.
- */
-struct DH_PurseDetails
-{
- /**
- * When should the purse expire.
- */
- struct GNUNET_TIME_Timestamp purse_expiration;
-
- /**
- * Hash of the contract terms of the purse.
- */
- struct TALER_PrivateContractHashP h_contract_terms;
-
- /**
- * Public key of the purse we are creating.
- */
- struct TALER_PurseContractPublicKeyP purse_pub;
-
- /**
- * Total amount to be put into the purse.
- */
- struct TALER_Amount target_amount;
-};
-
-
-/**
- * Send confirmation that a purse was created with
- * the current purse balance.
- *
- * @param connection connection to the client
- * @param pd purse details
- * @param donau_timestamp our time for purse creation
- * @param purse_balance current balance in the purse
- * @return MHD result code
- */
-MHD_RESULT
-DH_RESPONSE_reply_purse_created (
- struct MHD_Connection *connection,
- struct GNUNET_TIME_Timestamp donau_timestamp,
- const struct TALER_Amount *purse_balance,
- const struct DH_PurseDetails *pd);
-
-
-/**
- * Compile the transaction history of a coin into a JSON object.
- *
- * @param coin_pub public key of the coin
- * @param tl transaction history to JSON-ify
- * @return json representation of the @a rh, NULL on error
- */
-json_t *
-DH_RESPONSE_compile_transaction_history (
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct DONAUDB_TransactionList *tl);
-
-
-#endif
diff --git a/src/donau/donau-httpd_submit_receipts_get.c
b/src/donau/donau-httpd_submit_receipts_get.c
deleted file mode 100644
index c241c53..0000000
--- a/src/donau/donau-httpd_submit_receipts_get.c
+++ /dev/null
@@ -1,519 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_deposits_get.c
- * @brief Handle wire deposit tracking-related requests
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include <pthread.h>
-#include "taler_dbevents.h"
-#include "taler/taler_json_lib.h"
-#include "taler/taler_mhd_lib.h"
-#include "taler_signatures.h"
-#include "taler-donau-httpd_keys.h"
-#include "taler-donau-httpd_deposits_get.h"
-#include "taler-donau-httpd_responses.h"
-
-
-/**
- * Closure for #handle_wtid_data.
- */
-struct DepositWtidContext
-{
-
- /**
- * Kept in a DLL.
- */
- struct DepositWtidContext *next;
-
- /**
- * Kept in a DLL.
- */
- struct DepositWtidContext *prev;
-
- /**
- * Context for the request we are processing.
- */
- struct DH_RequestContext *rc;
-
- /**
- * Subscription for the database event we are waiting for.
- */
- struct GNUNET_DB_EventHandler *eh;
-
- /**
- * Hash over the proposal data of the contract for which this deposit is
made.
- */
- struct TALER_PrivateContractHashP h_contract_terms;
-
- /**
- * Hash over the wiring information of the charity.
- */
- struct TALER_CharityWireHashP h_wire;
-
- /**
- * The Charity's public key. The deposit inquiry request is to be
- * signed by the corresponding private key (using EdDSA).
- */
- struct DONAU_CharityPublicKeyP charity;
-
- /**
- * The coin's public key. This is the value that must have been
- * signed (blindly) by the Donau.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- /**
- * Set by #handle_wtid data to the wire transfer ID.
- */
- struct TALER_WireTransferIdentifierRawP wtid;
-
- /**
- * Signature by the charity.
- */
- struct DONAU_CharitySignatureP charity_sig;
-
-
- /**
- * Set by #handle_wtid data to the coin's contribution to the wire transfer.
- */
- struct TALER_Amount coin_contribution;
-
- /**
- * Set by #handle_wtid data to the fee charged to the coin.
- */
- struct TALER_Amount coin_fee;
-
- /**
- * Set by #handle_wtid data to the wire transfer execution time.
- */
- struct GNUNET_TIME_Timestamp execution_time;
-
- /**
- * Timeout of the request, for long-polling.
- */
- struct GNUNET_TIME_Absolute timeout;
-
- /**
- * Set by #handle_wtid to the coin contribution to the transaction
- * (that is, @e coin_contribution minus @e coin_fee).
- */
- struct TALER_Amount coin_delta;
-
- /**
- * KYC status information for the receiving account.
- */
- struct DONAUDB_KycStatus kyc;
-
- /**
- * AML status information for the receiving account.
- */
- enum TALER_AmlDecisionState aml_decision;
-
- /**
- * Set to #GNUNET_YES by #handle_wtid if the wire transfer is still pending
- * (and the above were not set).
- * Set to #GNUNET_SYSERR if there was a serious error.
- */
- enum GNUNET_GenericReturnValue pending;
-
- /**
- * #GNUNET_YES if we were suspended, #GNUNET_SYSERR
- * if we were woken up due to shutdown.
- */
- enum GNUNET_GenericReturnValue suspended;
-};
-
-
-/**
- * Head of DLL of suspended requests.
- */
-static struct DepositWtidContext *dwc_head;
-
-/**
- * Tail of DLL of suspended requests.
- */
-static struct DepositWtidContext *dwc_tail;
-
-
-void
-DH_deposits_get_cleanup ()
-{
- struct DepositWtidContext *n;
- for (struct DepositWtidContext *ctx = dwc_head;
- NULL != ctx;
- ctx = n)
- {
- n = ctx->next;
- GNUNET_assert (GNUNET_YES == ctx->suspended);
- ctx->suspended = GNUNET_SYSERR;
- MHD_resume_connection (ctx->rc->connection);
- GNUNET_CONTAINER_DLL_remove (dwc_head,
- dwc_tail,
- ctx);
- }
-}
-
-
-/**
- * A charity asked for details about a deposit. Provide
- * them. Generates the 200 reply.
- *
- * @param connection connection to the client
- * @param ctx details to respond with
- * @return MHD result code
- */
-static MHD_RESULT
-reply_deposit_details (
- struct MHD_Connection *connection,
- const struct DepositWtidContext *ctx)
-{
- struct DONAU_DonauPublicKeyP pub;
- struct TALER_DonauSignatureP sig;
- enum TALER_ErrorCode ec;
-
- if (TALER_EC_NONE !=
- (ec = TALER_donau_online_confirm_wire_sign (
- &DH_keys_donau_sign_,
- &ctx->h_wire,
- &ctx->h_contract_terms,
- &ctx->wtid,
- &ctx->coin_pub,
- ctx->execution_time,
- &ctx->coin_delta,
- &pub,
- &sig)))
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_ec (connection,
- ec,
- NULL);
- }
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_data_auto ("wtid",
- &ctx->wtid),
- GNUNET_JSON_pack_timestamp ("execution_time",
- ctx->execution_time),
- TALER_JSON_pack_amount ("coin_contribution",
- &ctx->coin_delta),
- GNUNET_JSON_pack_data_auto ("donau_sig",
- &sig),
- GNUNET_JSON_pack_data_auto ("donau_pub",
- &pub));
-}
-
-
-/**
- * Execute a "deposits" GET. Returns the transfer information
- * associated with the given deposit.
- *
- * If it returns a non-error code, the transaction logic MUST
- * NOT queue a MHD response. IF it returns an hard error, the
- * transaction logic MUST queue a MHD response and set @a mhd_ret. IF
- * it returns the soft error code, the function MAY be called again to
- * retry and MUST NOT queue a MHD response.
- *
- * @param cls closure of type `struct DepositWtidContext *`
- * @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
- * if transaction failed (!)
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-deposits_get_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct DepositWtidContext *ctx = cls;
- enum GNUNET_DB_QueryStatus qs;
- bool pending;
- struct TALER_Amount fee;
-
- qs = DH_plugin->lookup_transfer_by_deposit (DH_plugin->cls,
- &ctx->h_contract_terms,
- &ctx->h_wire,
- &ctx->coin_pub,
- &ctx->charity,
- &pending,
- &ctx->wtid,
- &ctx->execution_time,
- &ctx->coin_contribution,
- &fee,
- &ctx->kyc,
- &ctx->aml_decision);
- if (0 > qs)
- {
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- {
- GNUNET_break (0);
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
- }
- return qs;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- *mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_NOT_FOUND,
-
TALER_EC_DONAU_DEPOSITS_GET_NOT_FOUND,
- NULL);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
-
- if (0 >
- TALER_amount_subtract (&ctx->coin_delta,
- &ctx->coin_contribution,
- &fee))
- {
- GNUNET_break (0);
- ctx->pending = GNUNET_SYSERR;
- return qs;
- }
- ctx->pending = (pending) ? GNUNET_YES : GNUNET_NO;
- return qs;
-}
-
-
-/**
- * Function called on events received from Postgres.
- * Wakes up long pollers.
- *
- * @param cls the `struct DepositWtidContext *`
- * @param extra additional event data provided
- * @param extra_size number of bytes in @a extra
- */
-static void
-db_event_cb (void *cls,
- const void *extra,
- size_t extra_size)
-{
- struct DepositWtidContext *ctx = cls;
- struct GNUNET_AsyncScopeSave old_scope;
-
- (void) extra;
- (void) extra_size;
- if (GNUNET_NO != ctx->suspended)
- return; /* might get multiple wake-up events */
- GNUNET_CONTAINER_DLL_remove (dwc_head,
- dwc_tail,
- ctx);
- GNUNET_async_scope_enter (&ctx->rc->async_scope_id,
- &old_scope);
- DH_check_invariants ();
- ctx->suspended = GNUNET_NO;
- MHD_resume_connection (ctx->rc->connection);
- TALER_MHD_daemon_trigger ();
- DH_check_invariants ();
- GNUNET_async_scope_restore (&old_scope);
-}
-
-
-/**
- * Lookup and return the wire transfer identifier.
- *
- * @param ctx context of the signed request to execute
- * @return MHD result code
- */
-static MHD_RESULT
-handle_track_transaction_request (
- struct DepositWtidContext *ctx)
-{
- struct MHD_Connection *connection = ctx->rc->connection;
-
- if ( (GNUNET_TIME_absolute_is_future (ctx->timeout)) &&
- (NULL == ctx->eh) )
- {
- struct TALER_CoinDepositEventP rep = {
- .header.size = htons (sizeof (rep)),
- .header.type = htons (TALER_DBEVENT_DONAU_DEPOSIT_STATUS_CHANGED),
- .charity_pub = ctx->charity
- };
-
- ctx->eh = DH_plugin->event_listen (
- DH_plugin->cls,
- GNUNET_TIME_absolute_get_remaining (ctx->timeout),
- &rep.header,
- &db_event_cb,
- ctx);
- }
- {
- MHD_RESULT mhd_ret;
-
- if (GNUNET_OK !=
- DH_DB_run_transaction (connection,
- "handle deposits GET",
- DH_MT_REQUEST_OTHER,
- &mhd_ret,
- &deposits_get_transaction,
- ctx))
- return mhd_ret;
- }
- if (GNUNET_SYSERR == ctx->pending)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_INVARIANT_FAILURE,
- "wire fees exceed aggregate in
database");
- if (GNUNET_YES == ctx->pending)
- {
- if ( (GNUNET_TIME_absolute_is_future (ctx->timeout)) &&
- (GNUNET_NO == ctx->suspended) )
- {
- GNUNET_CONTAINER_DLL_insert (dwc_head,
- dwc_tail,
- ctx);
- ctx->suspended = GNUNET_YES;
- MHD_suspend_connection (connection);
- return MHD_YES;
- }
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_ACCEPTED,
- GNUNET_JSON_pack_allow_null (
- (0 == ctx->kyc.requirement_row)
- ? GNUNET_JSON_pack_string ("requirement_row",
- NULL)
- : GNUNET_JSON_pack_uint64 ("requirement_row",
- ctx->kyc.requirement_row)),
- GNUNET_JSON_pack_uint64 ("aml_decision",
- (uint32_t) ctx->aml_decision),
- GNUNET_JSON_pack_bool ("kyc_ok",
- ctx->kyc.ok),
- GNUNET_JSON_pack_timestamp ("execution_time",
- ctx->execution_time));
- }
- return reply_deposit_details (connection,
- ctx);
-}
-
-
-/**
- * Function called to clean up a context.
- *
- * @param rc request context with data to clean up
- */
-static void
-dwc_cleaner (struct DH_RequestContext *rc)
-{
- struct DepositWtidContext *ctx = rc->rh_ctx;
-
- GNUNET_assert (GNUNET_NO == ctx->suspended);
- if (NULL != ctx->eh)
- {
- DH_plugin->event_listen_cancel (DH_plugin->cls,
- ctx->eh);
- ctx->eh = NULL;
- }
- GNUNET_free (ctx);
-}
-
-
-MHD_RESULT
-DH_handler_deposits_get (struct DH_RequestContext *rc,
- const char *const args[4])
-{
- struct DepositWtidContext *ctx = rc->rh_ctx;
-
- if (NULL == ctx)
- {
- ctx = GNUNET_new (struct DepositWtidContext);
- ctx->rc = rc;
- rc->rh_ctx = ctx;
- rc->rh_cleaner = &dwc_cleaner;
-
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (args[0],
- strlen (args[0]),
- &ctx->h_wire,
- sizeof (ctx->h_wire)))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_DEPOSITS_GET_INVALID_H_WIRE,
- args[0]);
- }
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (args[1],
- strlen (args[1]),
- &ctx->charity,
- sizeof (ctx->charity)))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_DEPOSITS_GET_INVALID_CHARITY_PUB,
- args[1]);
- }
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (args[2],
- strlen (args[2]),
- &ctx->h_contract_terms,
- sizeof (ctx->h_contract_terms)))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS,
- args[2]);
- }
- if (GNUNET_OK !=
- GNUNET_STRINGS_string_to_data (args[3],
- strlen (args[3]),
- &ctx->coin_pub,
- sizeof (ctx->coin_pub)))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
-
TALER_EC_DONAU_DEPOSITS_GET_INVALID_COIN_PUB,
- args[3]);
- }
- TALER_MHD_parse_request_arg_auto_t (rc->connection,
- "charity_sig",
- &ctx->charity_sig);
- TALER_MHD_parse_request_timeout (rc->connection,
- &ctx->timeout);
- DH_METRICS_num_verifications[DH_MT_SIGNATURE_EDDSA]++;
- {
- if (GNUNET_OK !=
- TALER_charity_deposit_verify (&ctx->charity,
- &ctx->coin_pub,
- &ctx->h_contract_terms,
- &ctx->h_wire,
- &ctx->charity_sig))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_FORBIDDEN,
-
TALER_EC_DONAU_DEPOSITS_GET_CHARITY_SIGNATURE_INVALID,
- NULL);
- }
- }
- }
-
- return handle_track_transaction_request (ctx);
-}
-
-
-/* end of taler-donau-httpd_deposits_get.c */
diff --git a/src/donau/donau-httpd_submit_receipts_get.h
b/src/donau/donau-httpd_submit_receipts_get.h
deleted file mode 100644
index 3e2c8e4..0000000
--- a/src/donau/donau-httpd_submit_receipts_get.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2017, 2021 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_deposits_get.h
- * @brief Handle wire transfer tracking-related requests
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_DEPOSITS_GET_H
-#define DONAU_HTTPD_DEPOSITS_GET_H
-
-#include <gnunet/gnunet_util_lib.h>
-#include <microhttpd.h>
-#include "taler-donau-httpd.h"
-
-
-/**
- * Resume long pollers on GET /deposits.
- */
-void
-DH_deposits_get_cleanup (void);
-
-
-/**
- * Handle a "/deposits/$H_WIRE/$CHARITY_PUB/$H_CONTRACT_TERMS/$COIN_PUB"
- * request.
- *
- * @param rc request context
- * @param args array of additional options (length: 4, contains:
- * h_wire, charity_pub, h_contract_terms and coin_pub)
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_deposits_get (struct DH_RequestContext *rc,
- const char *const args[4]);
-
-
-#endif
diff --git a/src/donau/donau-httpd_terms.c b/src/donau/donau-httpd_terms.c
deleted file mode 100644
index a3e25b4..0000000
--- a/src/donau/donau-httpd_terms.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019, 2021 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_terms.c
- * @brief Handle /terms requests to return the terms of service
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include "taler/taler_mhd_lib.h"
-#include "donau-httpd_responses.h"
-
-/**
- * Our terms of service.
- */
-//static struct TALER_MHD_Legal *tos;
-
-
-/**
- * Our privacy policy.
- */
-//static struct TALER_MHD_Legal *pp;
-
-
-// MHD_RESULT
-// DH_handler_terms (struct DH_RequestContext *rc,
-// const char *const args[])
-// {
-// (void) args;
-// return TALER_MHD_reply_legal (rc->connection,
-// tos);
-// }
-
-
-// MHD_RESULT
-// DH_handler_privacy (struct DH_RequestContext *rc,
-// const char *const args[])
-// {
-// (void) args;
-// return TALER_MHD_reply_legal (rc->connection,
-// pp);
-// }
-
-
-// void
-// DH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg)
-// {
-// tos = TALER_MHD_legal_load (cfg,
-// "donau",
-// "TERMS_DIR",
-// "TERMS_ETAG");
-// if (NULL == tos)
-// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-// "Terms of service not configured\n");
-// pp = TALER_MHD_legal_load (cfg,
-// "donau",
-// "PRIVACY_DIR",
-// "PRIVACY_ETAG");
-// if (NULL == pp)
-// GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-// "Privacy policy not configured\n");
-// }
-
-
-/* end of taler-donau-httpd_terms.c */
diff --git a/src/donau/donau-httpd_terms.h b/src/donau/donau-httpd_terms.h
deleted file mode 100644
index 2f8b657..0000000
--- a/src/donau/donau-httpd_terms.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019, 2021 Taler Systems SA
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU Affero 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 CHARITYABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
-
- You should have received a copy of the GNU Affero General Public License
along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-/**
- * @file taler-donau-httpd_terms.h
- * @brief Handle /terms requests to return the terms of service
- * @author Christian Grothoff
- */
-#ifndef DONAU_HTTPD_TERMS_H
-#define DONAU_HTTPD_TERMS_H
-#include "taler/platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <jansson.h>
-#include <microhttpd.h>
-#include "taler/taler_mhd_lib.h"
-#include "donau-httpd_responses.h"
-
-
-/**
- * Handle a "/terms" request.
- *
- * @param rc request context
- * @param args array of additional options (must be empty for this function)
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_terms (struct DH_RequestContext *rc,
- const char *const args[]);
-
-
-/**
- * Handle a "/privacy" request.
- *
- * @param rc request context
- * @param args array of additional options (must be empty for this function)
- * @return MHD result code
- */
-MHD_RESULT
-DH_handler_privacy (struct DH_RequestContext *rc,
- const char *const args[]);
-
-
-/**
- * Load our terms of service as per configuration.
- *
- * @param cfg configuration to process
- */
-void
-DH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg);
-
-
-#endif
diff --git a/src/donaudb/pg_add_donation_unit_key.h
b/src/donaudb/pg_add_donation_unit_key.h
index a0670db..b05208f 100644
--- a/src/donaudb/pg_add_donation_unit_key.h
+++ b/src/donaudb/pg_add_donation_unit_key.h
@@ -26,8 +26,7 @@
#include "donaudb_plugin.h"
/**
- * Activate donation unit key, turning it into a "current" or "valid"
- * donation_unit key by adding the master signature.
+ * Add donation unit key.
*
* @param cls closure
* @param donation_unit_pub the actual donation_unit key
diff --git a/src/lib/donau_api_batch_issue_receipts.c
b/src/lib/donau_api_batch_issue_receipts.c
deleted file mode 100644
index 30bc19b..0000000
--- a/src/lib/donau_api_batch_issue_receipts.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*
- 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 CHARITYABILITY 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/>
-*/
-/**
- * @file lib/donau_api_batch_withdraw.c
- * @brief Implementation of /reserves/$RESERVE_PUB/batch-withdraw requests
with blinding/unblinding
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_donau_service.h"
-#include "taler/taler_json_lib.h"
-#include "donau_api_handle.h"
-#include "taler_signatures.h"
-#include "donau_api_curl_defaults.h"
-
-
-/**
- * Data we keep per coin in the batch.
- */
-struct CoinData
-{
-
- /**
- * Denomination key we are withdrawing.
- */
- struct DONAU_DenomPublicKey pk;
-
- /**
- * Master key material for the coin.
- */
- struct TALER_PlanchetMasterSecretP ps;
-
- /**
- * Age commitment for the coin.
- */
- const struct TALER_AgeCommitmentHash *ach;
-
- /**
- * blinding secret
- */
- union TALER_DenominationBlindingKeyP bks;
-
- /**
- * Private key of the coin we are withdrawing.
- */
- struct TALER_CoinSpendPrivateKeyP priv;
-
- /**
- * Details of the planchet.
- */
- struct TALER_PlanchetDetail pd;
-
- /**
- * Values of the @cipher selected
- */
- struct TALER_DonauWithdrawValues alg_values;
-
- /**
- * Hash of the public key of the coin we are signing.
- */
- struct TALER_CoinPubHashP c_hash;
-
- /**
- * Handler for the CS R request (only used for TALER_DENOMINATION_CS
denominations)
- */
- struct DONAU_CsRWithdrawHandle *csrh;
-
- /**
- * Batch withdraw this coin is part of.
- */
- struct DONAU_BatchWithdrawHandle *wh;
-};
-
-
-/**
- * @brief A batch withdraw handle
- */
-struct DONAU_BatchWithdrawHandle
-{
-
- /**
- * The curl context to use
- */
- struct GNUNET_CURL_Context *curl_ctx;
-
- /**
- * The base URL to the donau
- */
- const char *donau_url;
-
- /**
- * The /keys information from the donau
- */
- const struct DONAU_Keys *keys;
-
-
- /**
- * Handle for the actual (internal) batch withdraw operation.
- */
- struct DONAU_BatchWithdraw2Handle *wh2;
-
- /**
- * Function to call with the result.
- */
- DONAU_BatchWithdrawCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Reserve private key.
- */
- const struct TALER_ReservePrivateKeyP *reserve_priv;
-
- /**
- * Array of per-coin data.
- */
- struct CoinData *coins;
-
- /**
- * Length of the @e coins array.
- */
- unsigned int num_coins;
-
- /**
- * Number of CS requests still pending.
- */
- unsigned int cs_pending;
-
-};
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserves/$RESERVE_PUB/batch-withdraw request.
- *
- * @param cls the `struct DONAU_BatchWithdrawHandle`
- * @param bw2r response data
- */
-static void
-handle_reserve_batch_withdraw_finished (
- void *cls,
- const struct DONAU_BatchWithdraw2Response *bw2r)
-{
- struct DONAU_BatchWithdrawHandle *wh = cls;
- struct DONAU_BatchWithdrawResponse wr = {
- .hr = bw2r->hr
- };
- struct DONAU_PrivateCoinDetails coins[GNUNET_NZL (wh->num_coins)];
-
- wh->wh2 = NULL;
- memset (coins,
- 0,
- sizeof (coins));
- switch (bw2r->hr.http_status)
- {
- case MHD_HTTP_OK:
- {
- if (bw2r->details.ok.blind_sigs_length != wh->num_coins)
- {
- GNUNET_break_op (0);
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- for (unsigned int i = 0; i<wh->num_coins; i++)
- {
- struct CoinData *cd = &wh->coins[i];
- struct DONAU_PrivateCoinDetails *coin = &coins[i];
- struct TALER_FreshCoin fc;
-
- if (GNUNET_OK !=
- TALER_planchet_to_coin (&cd->pk.key,
- &bw2r->details.ok.blind_sigs[i],
- &cd->bks,
- &cd->priv,
- cd->ach,
- &cd->c_hash,
- &cd->alg_values,
- &fc))
- {
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_DONAU_WITHDRAW_UNBLIND_FAILURE;
- break;
- }
- coin->coin_priv = cd->priv;
- coin->bks = cd->bks;
- coin->sig = fc.sig;
- coin->donau_vals = cd->alg_values;
- }
- wr.details.ok.coins = coins;
- wr.details.ok.num_coins = wh->num_coins;
- break;
- }
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- {
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &wr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &wr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (bw2r->hr.reply,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- break;
- default:
- break;
- }
- wh->cb (wh->cb_cls,
- &wr);
- for (unsigned int i = 0; i<wh->num_coins; i++)
- TALER_denom_sig_free (&coins[i].sig);
- DONAU_batch_withdraw_cancel (wh);
-}
-
-
-/**
- * Runs phase two, the actual withdraw operation.
- * Started once the preparation for CS-denominations is
- * done.
- *
- * @param[in,out] wh batch withdraw to start phase 2 for
- */
-static void
-phase_two (struct DONAU_BatchWithdrawHandle *wh)
-{
- struct TALER_PlanchetDetail pds[wh->num_coins];
-
- for (unsigned int i = 0; i<wh->num_coins; i++)
- {
- struct CoinData *cd = &wh->coins[i];
-
- pds[i] = cd->pd;
- }
- wh->wh2 = DONAU_batch_withdraw2 (
- wh->curl_ctx,
- wh->donau_url,
- wh->keys,
- wh->reserve_priv,
- wh->num_coins,
- pds,
- &handle_reserve_batch_withdraw_finished,
- wh);
-}
-
-
-/**
- * Function called when stage 1 of CS withdraw is finished (request r_pub's)
- *
- * @param cls the `struct CoinData *`
- * @param csrr replies from the /csr-withdraw request
- */
-static void
-withdraw_cs_stage_two_callback (
- void *cls,
- const struct DONAU_CsRWithdrawResponse *csrr)
-{
- struct CoinData *cd = cls;
- struct DONAU_BatchWithdrawHandle *wh = cd->wh;
- struct DONAU_BatchWithdrawResponse wr = {
- .hr = csrr->hr
- };
-
- cd->csrh = NULL;
- GNUNET_assert (TALER_DENOMINATION_CS == cd->pk.key.cipher);
- switch (csrr->hr.http_status)
- {
- case MHD_HTTP_OK:
- cd->alg_values = csrr->details.ok.alg_values;
- TALER_planchet_setup_coin_priv (&cd->ps,
- &cd->alg_values,
- &cd->priv);
- TALER_planchet_blinding_secret_create (&cd->ps,
- &cd->alg_values,
- &cd->bks);
- /* This initializes the 2nd half of the
- wh->pd.blinded_planchet! */
- if (GNUNET_OK !=
- TALER_planchet_prepare (&cd->pk.key,
- &cd->alg_values,
- &cd->bks,
- &cd->priv,
- cd->ach,
- &cd->c_hash,
- &cd->pd))
- {
- GNUNET_break (0);
- DONAU_batch_withdraw_cancel (wh);
- }
- wh->cs_pending--;
- if (0 == wh->cs_pending)
- phase_two (wh);
- return;
- default:
- break;
- }
- wh->cb (wh->cb_cls,
- &wr);
- DONAU_batch_withdraw_cancel (wh);
-}
-
-
-struct DONAU_BatchWithdrawHandle *
-DONAU_batch_withdraw (
- struct GNUNET_CURL_Context *curl_ctx,
- const char *donau_url,
- const struct DONAU_Keys *keys,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- unsigned int wci_length,
- const struct DONAU_WithdrawCoinInput wcis[static wci_length],
- DONAU_BatchWithdrawCallback res_cb,
- void *res_cb_cls)
-{
- struct DONAU_BatchWithdrawHandle *wh;
-
- wh = GNUNET_new (struct DONAU_BatchWithdrawHandle);
- wh->curl_ctx = curl_ctx;
- wh->donau_url = donau_url;
- wh->keys = keys;
- wh->cb = res_cb;
- wh->cb_cls = res_cb_cls;
- wh->reserve_priv = reserve_priv;
- wh->num_coins = wci_length;
- wh->coins = GNUNET_new_array (wh->num_coins,
- struct CoinData);
- for (unsigned int i = 0; i<wci_length; i++)
- {
- struct CoinData *cd = &wh->coins[i];
- const struct DONAU_WithdrawCoinInput *wci = &wcis[i];
-
- cd->wh = wh;
- cd->ps = *wci->ps;
- cd->ach = wci->ach;
- cd->pk = *wci->pk;
- TALER_denom_pub_deep_copy (&cd->pk.key,
- &wci->pk->key);
- switch (wci->pk->key.cipher)
- {
- case TALER_DENOMINATION_RSA:
- {
- cd->alg_values.cipher = TALER_DENOMINATION_RSA;
- TALER_planchet_setup_coin_priv (&cd->ps,
- &cd->alg_values,
- &cd->priv);
- TALER_planchet_blinding_secret_create (&cd->ps,
- &cd->alg_values,
- &cd->bks);
- if (GNUNET_OK !=
- TALER_planchet_prepare (&cd->pk.key,
- &cd->alg_values,
- &cd->bks,
- &cd->priv,
- cd->ach,
- &cd->c_hash,
- &cd->pd))
- {
- GNUNET_break (0);
- DONAU_batch_withdraw_cancel (wh);
- return NULL;
- }
- break;
- }
- case TALER_DENOMINATION_CS:
- {
- TALER_cs_withdraw_nonce_derive (
- &cd->ps,
- &cd->pd.blinded_planchet.details.cs_blinded_planchet.nonce);
- /* Note that we only initialize the first half
- of the blinded_planchet here; the other part
- will be done after the /csr-withdraw request! */
- cd->pd.blinded_planchet.cipher = TALER_DENOMINATION_CS;
- cd->csrh = DONAU_csr_withdraw (
- curl_ctx,
- donau_url,
- &cd->pk,
- &cd->pd.blinded_planchet.details.cs_blinded_planchet.nonce,
- &withdraw_cs_stage_two_callback,
- cd);
- if (NULL == cd->csrh)
- {
- GNUNET_break (0);
- DONAU_batch_withdraw_cancel (wh);
- return NULL;
- }
- wh->cs_pending++;
- break;
- }
- default:
- GNUNET_break (0);
- DONAU_batch_withdraw_cancel (wh);
- return NULL;
- }
- }
- if (0 == wh->cs_pending)
- phase_two (wh);
- return wh;
-}
-
-
-void
-DONAU_batch_withdraw_cancel (
- struct DONAU_BatchWithdrawHandle *wh)
-{
- for (unsigned int i = 0; i<wh->num_coins; i++)
- {
- struct CoinData *cd = &wh->coins[i];
-
- if (NULL != cd->csrh)
- {
- DONAU_csr_withdraw_cancel (cd->csrh);
- cd->csrh = NULL;
- }
- TALER_blinded_planchet_free (&cd->pd.blinded_planchet);
- TALER_denom_pub_free (&cd->pk.key);
- }
- GNUNET_free (wh->coins);
- if (NULL != wh->wh2)
- {
- DONAU_batch_withdraw2_cancel (wh->wh2);
- wh->wh2 = NULL;
- }
- GNUNET_free (wh);
-}
diff --git a/src/lib/donau_api_batch_issue_receipts2.c
b/src/lib/donau_api_batch_issue_receipts2.c
deleted file mode 100644
index e6b9fe5..0000000
--- a/src/lib/donau_api_batch_issue_receipts2.c
+++ /dev/null
@@ -1,555 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2023 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 CHARITYABILITY 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/>
-*/
-/**
- * @file lib/donau_api_batch_withdraw2.c
- * @brief Implementation of /reserves/$RESERVE_PUB/batch-withdraw requests
without blinding/unblinding
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler_donau_service.h"
-#include "taler/taler_json_lib.h"
-#include "donau_api_handle.h"
-#include "taler_signatures.h"
-#include "donau_api_curl_defaults.h"
-
-
-/**
- * @brief A batch withdraw handle
- */
-struct DONAU_BatchWithdraw2Handle
-{
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * The /keys material from the donau
- */
- const struct DONAU_Keys *keys;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- DONAU_BatchWithdraw2Callback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Context for #DH_curl_easy_post(). Keeps the data that must
- * persist for Curl to make the upload.
- */
- struct TALER_CURL_PostContext post_ctx;
-
- /**
- * Total amount requested (value plus withdraw fee).
- */
- struct TALER_Amount requested_amount;
-
- /**
- * Public key of the reserve we are withdrawing from.
- */
- struct TALER_ReservePublicKeyP reserve_pub;
-
- /**
- * Number of coins expected.
- */
- unsigned int num_coins;
-};
-
-
-/**
- * We got a 200 OK response for the /reserves/$RESERVE_PUB/batch-withdraw
operation.
- * Extract the coin's signature and return it to the caller. The signature we
- * get from the donau is for the blinded value. Thus, we first must
- * unblind it and then should verify its validity against our coin's hash.
- *
- * If everything checks out, we return the unblinded signature
- * to the application via the callback.
- *
- * @param wh operation handle
- * @param json reply from the donau
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static enum GNUNET_GenericReturnValue
-reserve_batch_withdraw_ok (struct DONAU_BatchWithdraw2Handle *wh,
- const json_t *json)
-{
- struct TALER_BlindedDenominationSignature blind_sigs[wh->num_coins];
- const json_t *ja = json_object_get (json,
- "ev_sigs");
- const json_t *j;
- unsigned int index;
- struct DONAU_BatchWithdraw2Response bwr = {
- .hr.reply = json,
- .hr.http_status = MHD_HTTP_OK
- };
-
- if ( (NULL == ja) ||
- (! json_is_array (ja)) ||
- (wh->num_coins != json_array_size (ja)) )
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- json_array_foreach (ja, index, j)
- {
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_blinded_denom_sig ("ev_sig",
- &blind_sigs[index]),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- for (unsigned int i = 0; i<index; i++)
- TALER_blinded_denom_sig_free (&blind_sigs[i]);
- return GNUNET_SYSERR;
- }
- }
-
- /* signature is valid, return it to the application */
- bwr.details.ok.blind_sigs = blind_sigs;
- bwr.details.ok.blind_sigs_length = wh->num_coins;
- wh->cb (wh->cb_cls,
- &bwr);
- /* make sure callback isn't called again after return */
- wh->cb = NULL;
- for (unsigned int i = 0; i<wh->num_coins; i++)
- TALER_blinded_denom_sig_free (&blind_sigs[i]);
-
- return GNUNET_OK;
-}
-
-
-/**
- * We got a 409 CONFLICT response for the
/reserves/$RESERVE_PUB/batch-withdraw operation.
- * Check the signatures on the batch withdraw transactions in the provided
- * history and that the balances add up. We don't do anything directly
- * with the information, as the JSON will be returned to the application.
- * However, our job is ensuring that the donau followed the protocol, and
- * this in particular means checking all of the signatures in the history.
- *
- * @param wh operation handle
- * @param json reply from the donau
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on errors
- */
-static enum GNUNET_GenericReturnValue
-reserve_batch_withdraw_payment_required (
- struct DONAU_BatchWithdraw2Handle *wh,
- const json_t *json)
-{
- struct TALER_Amount balance;
- struct TALER_Amount total_in_from_history;
- struct TALER_Amount total_out_from_history;
- json_t *history;
- size_t len;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("balance",
- &balance),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (json,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- history = json_object_get (json,
- "history");
- if (NULL == history)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* go over transaction history and compute
- total incoming and outgoing amounts */
- len = json_array_size (history);
- {
- struct DONAU_ReserveHistoryEntry *rhistory;
-
- /* Use heap allocation as "len" may be very big and thus this may
- not fit on the stack. Use "GNUNET_malloc_large" as a malicious
- donau may theoretically try to crash us by giving a history
- that does not fit into our memory. */
- rhistory = GNUNET_malloc_large (
- sizeof (struct DONAU_ReserveHistoryEntry)
- * len);
- if (NULL == rhistory)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
-
- if (GNUNET_OK !=
- DONAU_parse_reserve_history (
- wh->keys,
- history,
- &wh->reserve_pub,
- balance.currency,
- &total_in_from_history,
- &total_out_from_history,
- len,
- rhistory))
- {
- GNUNET_break_op (0);
- DONAU_free_reserve_history (len,
- rhistory);
- return GNUNET_SYSERR;
- }
- DONAU_free_reserve_history (len,
- rhistory);
- }
-
- /* Check that funds were really insufficient */
- if (0 >= TALER_amount_cmp (&wh->requested_amount,
- &balance))
- {
- /* Requested amount is smaller or equal to reported balance,
- so this should not have failed. */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /reserves/$RESERVE_PUB/batch-withdraw request.
- *
- * @param cls the `struct DONAU_BatchWithdraw2Handle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_reserve_batch_withdraw_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct DONAU_BatchWithdraw2Handle *wh = cls;
- const json_t *j = response;
- struct DONAU_BatchWithdraw2Response bwr = {
- .hr.reply = j,
- .hr.http_status = (unsigned int) response_code
- };
-
- wh->job = NULL;
- switch (response_code)
- {
- case 0:
- bwr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- if (GNUNET_OK !=
- reserve_batch_withdraw_ok (wh,
- j))
- {
- GNUNET_break_op (0);
- bwr.hr.http_status = 0;
- bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- GNUNET_assert (NULL == wh->cb);
- DONAU_batch_withdraw2_cancel (wh);
- return;
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- /* only validate reply is well-formed */
- {
- uint64_t ptu;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_uint64 ("legitimization_uuid",
- &ptu),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- bwr.hr.http_status = 0;
- bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the donau is buggy
- (or API version conflict); just pass JSON reply to the application */
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_FORBIDDEN:
- GNUNET_break_op (0);
- /* Nothing really to verify, donau says one of the signatures is
- invalid; as we checked them, this should never happen, we
- should pass the JSON reply to the application */
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_NOT_FOUND:
- /* Nothing really to verify, the donau basically just says
- that it doesn't know this reserve. Can happen if we
- query before the wire transfer went through.
- We should simply pass the JSON reply to the application. */
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_CONFLICT:
- /* The donau says that the reserve has insufficient funds;
- check the signatures in the history... */
- if (GNUNET_OK !=
- reserve_batch_withdraw_payment_required (wh,
- j))
- {
- GNUNET_break_op (0);
- bwr.hr.http_status = 0;
- bwr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- }
- else
- {
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- }
- break;
- case MHD_HTTP_GONE:
- /* could happen if denomination was revoked */
- /* Note: one might want to check /keys for revocation
- signature here, alas tricky in case our /keys
- is outdated => left to clients */
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- break;
- default:
- /* unexpected response code */
- GNUNET_break_op (0);
- bwr.hr.ec = TALER_JSON_get_error_code (j);
- bwr.hr.hint = TALER_JSON_get_error_hint (j);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for donau batch withdraw\n",
- (unsigned int) response_code,
- (int) bwr.hr.ec);
- break;
- }
- if (NULL != wh->cb)
- {
- wh->cb (wh->cb_cls,
- &bwr);
- wh->cb = NULL;
- }
- DONAU_batch_withdraw2_cancel (wh);
-}
-
-
-struct DONAU_BatchWithdraw2Handle *
-DONAU_batch_withdraw2 (
- struct GNUNET_CURL_Context *curl_ctx,
- const char *donau_url,
- const struct DONAU_Keys *keys,
- const struct TALER_ReservePrivateKeyP *reserve_priv,
- unsigned int pds_length,
- const struct TALER_PlanchetDetail pds[static pds_length],
- DONAU_BatchWithdraw2Callback res_cb,
- void *res_cb_cls)
-{
- struct DONAU_BatchWithdraw2Handle *wh;
- const struct DONAU_DenomPublicKey *dk;
- struct TALER_ReserveSignatureP reserve_sig;
- char arg_str[sizeof (struct TALER_ReservePublicKeyP) * 2 + 32];
- struct TALER_BlindedCoinHashP bch;
- json_t *jc;
-
- GNUNET_assert (NULL != keys);
- wh = GNUNET_new (struct DONAU_BatchWithdraw2Handle);
- wh->keys = keys;
- wh->cb = res_cb;
- wh->cb_cls = res_cb_cls;
- wh->num_coins = pds_length;
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (keys->currency,
- &wh->requested_amount));
- GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
- &wh->reserve_pub.eddsa_pub);
- {
- char pub_str[sizeof (struct TALER_ReservePublicKeyP) * 2];
- char *end;
-
- end = GNUNET_STRINGS_data_to_string (
- &wh->reserve_pub,
- sizeof (struct TALER_ReservePublicKeyP),
- pub_str,
- sizeof (pub_str));
- *end = '\0';
- GNUNET_snprintf (arg_str,
- sizeof (arg_str),
- "reserves/%s/batch-withdraw",
- pub_str);
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Attempting to batch-withdraw from reserve %s\n",
- TALER_B2S (&wh->reserve_pub));
- wh->url = TALER_url_join (donau_url,
- arg_str,
- NULL);
- if (NULL == wh->url)
- {
- GNUNET_break (0);
- DONAU_batch_withdraw2_cancel (wh);
- return NULL;
- }
- jc = json_array ();
- GNUNET_assert (NULL != jc);
- for (unsigned int i = 0; i<pds_length; i++)
- {
- const struct TALER_PlanchetDetail *pd = &pds[i];
- struct TALER_Amount coin_total;
- json_t *withdraw_obj;
-
- dk = DONAU_get_denomination_key_by_hash (keys,
- &pd->denom_pub_hash);
- if (NULL == dk)
- {
- DONAU_batch_withdraw2_cancel (wh);
- json_decref (jc);
- GNUNET_break (0);
- return NULL;
- }
- /* Compute how much we expected to charge to the reserve */
- if (0 >
- TALER_amount_add (&coin_total,
- &dk->fees.withdraw,
- &dk->value))
- {
- /* Overflow here? Very strange, our CPU must be fried... */
- GNUNET_break (0);
- DONAU_batch_withdraw2_cancel (wh);
- json_decref (jc);
- return NULL;
- }
- if (0 >
- TALER_amount_add (&wh->requested_amount,
- &wh->requested_amount,
- &coin_total))
- {
- /* Overflow here? Very strange, our CPU must be fried... */
- GNUNET_break (0);
- DONAU_batch_withdraw2_cancel (wh);
- json_decref (jc);
- return NULL;
- }
- if (GNUNET_OK !=
- TALER_coin_ev_hash (&pd->blinded_planchet,
- &pd->denom_pub_hash,
- &bch))
- {
- GNUNET_break (0);
- DONAU_batch_withdraw2_cancel (wh);
- json_decref (jc);
- return NULL;
- }
- TALER_wallet_withdraw_sign (&pd->denom_pub_hash,
- &coin_total,
- &bch,
- reserve_priv,
- &reserve_sig);
- withdraw_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_data_auto ("denom_pub_hash",
- &pd->denom_pub_hash),
- TALER_JSON_pack_blinded_planchet ("coin_ev",
- &pd->blinded_planchet),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &reserve_sig));
- GNUNET_assert (NULL != withdraw_obj);
- GNUNET_assert (0 ==
- json_array_append_new (jc,
- withdraw_obj));
- }
- {
- CURL *eh;
- json_t *req;
-
- req = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal ("planchets",
- jc));
- eh = DONAU_curl_easy_get_ (wh->url);
- if ( (NULL == eh) ||
- (GNUNET_OK !=
- TALER_curl_easy_post (&wh->post_ctx,
- eh,
- req)) )
- {
- GNUNET_break (0);
- if (NULL != eh)
- curl_easy_cleanup (eh);
- json_decref (req);
- DONAU_batch_withdraw2_cancel (wh);
- return NULL;
- }
- json_decref (req);
- wh->job = GNUNET_CURL_job_add2 (curl_ctx,
- eh,
- wh->post_ctx.headers,
- &handle_reserve_batch_withdraw_finished,
- wh);
- }
- return wh;
-}
-
-
-void
-DONAU_batch_withdraw2_cancel (
- struct DONAU_BatchWithdraw2Handle *wh)
-{
- if (NULL != wh->job)
- {
- GNUNET_CURL_job_cancel (wh->job);
- wh->job = NULL;
- }
- GNUNET_free (wh->url);
- TALER_curl_easy_post_finished (&wh->post_ctx);
- GNUNET_free (wh);
-}
diff --git a/src/lib/donau_api_batch_submit_receipts.c
b/src/lib/donau_api_batch_submit_receipts.c
deleted file mode 100644
index 08bea01..0000000
--- a/src/lib/donau_api_batch_submit_receipts.c
+++ /dev/null
@@ -1,779 +0,0 @@
-/*
- 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 CHARITYABILITY 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/>
- */
-/**
- * @file lib/donau_api_batch_deposit.c
- * @brief Implementation of the /batch-deposit request of the donau's HTTP API
- * @author Sree Harsha Totakura <sreeharsha@totakura.in>
- * @author Christian Grothoff
- */
-#include "taler/platform.h"
-#include <jansson.h>
-#include <microhttpd.h> /* just for HTTP status codes */
-#include <gnunet/gnunet_util_lib.h>
-#include <gnunet/gnunet_json_lib.h>
-#include <gnunet/gnunet_curl_lib.h>
-#include "taler/taler_json_lib.h"
-#include "taler_auditor_service.h"
-#include "taler_donau_service.h"
-#include "donau_api_common.h"
-#include "donau_api_handle.h"
-#include "taler_signatures.h"
-#include "donau_api_curl_defaults.h"
-
-
-/**
- * 1:#AUDITOR_CHANCE is the probability that we report deposits
- * to the auditor.
- *
- * 20==5% of going to auditor. This is possibly still too high, but set
- * deliberately this high for testing
- */
-#define AUDITOR_CHANCE 20
-
-
-/**
- * Entry in list of ongoing interactions with an auditor.
- */
-struct TEAH_AuditorInteractionEntry
-{
- /**
- * DLL entry.
- */
- struct TEAH_AuditorInteractionEntry *next;
-
- /**
- * DLL entry.
- */
- struct TEAH_AuditorInteractionEntry *prev;
-
- /**
- * URL of our auditor. For logging.
- */
- const char *auditor_url;
-
- /**
- * Interaction state.
- */
- struct TALER_AUDITOR_DepositConfirmationHandle *dch;
-
- /**
- * Batch deposit this is for.
- */
- struct DONAU_BatchDepositHandle *dh;
-};
-
-
-/**
- * @brief A Deposit Handle
- */
-struct DONAU_BatchDepositHandle
-{
-
- /**
- * The keys of the donau.
- */
- struct DONAU_Keys *keys;
-
- /**
- * Context for our curl request(s).
- */
- struct GNUNET_CURL_Context *ctx;
-
- /**
- * The url for this request.
- */
- char *url;
-
- /**
- * Context for #DH_curl_easy_post(). Keeps the data that must
- * persist for Curl to make the upload.
- */
- struct TALER_CURL_PostContext post_ctx;
-
- /**
- * Handle for the request.
- */
- struct GNUNET_CURL_Job *job;
-
- /**
- * Function to call with the result.
- */
- DONAU_BatchDepositResultCallback cb;
-
- /**
- * Closure for @a cb.
- */
- void *cb_cls;
-
- /**
- * Details about the contract.
- */
- struct DONAU_DepositContractDetail dcd;
-
- /**
- * Array with details about the coins.
- */
- struct DONAU_CoinDepositDetail *cdds;
-
- /**
- * Hash of the charity's wire details.
- */
- struct TALER_CharityWireHashP h_wire;
-
- /**
- * Time when this confirmation was generated / when the donau received
- * the deposit request.
- */
- struct GNUNET_TIME_Timestamp donau_timestamp;
-
- /**
- * Donau signatures, set for #auditor_cb.
- */
- struct TALER_DonauSignatureP *donau_sigs;
-
- /**
- * Head of DLL of interactions with this auditor.
- */
- struct TEAH_AuditorInteractionEntry *ai_head;
-
- /**
- * Tail of DLL of interactions with this auditor.
- */
- struct TEAH_AuditorInteractionEntry *ai_tail;
-
- /**
- * Result to return to the application once @e ai_head is empty.
- */
- struct DONAU_BatchDepositResult dr;
-
- /**
- * Donau signing public key, set for #auditor_cb.
- */
- struct DONAU_DonauPublicKeyP donau_pub;
-
- /**
- * Response object to free at the end.
- */
- json_t *response;
-
- /**
- * Chance that we will inform the auditor about the deposit
- * is 1:n, where the value of this field is "n".
- */
- unsigned int auditor_chance;
-
- /**
- * Length of the @e cdds array.
- */
- unsigned int num_cdds;
-
-};
-
-
-/**
- * Finish batch deposit operation by calling the callback.
- *
- * @param[in] dh handle to finished batch deposit operation
- */
-static void
-finish_dh (struct DONAU_BatchDepositHandle *dh)
-{
- dh->cb (dh->cb_cls,
- &dh->dr);
- DONAU_batch_deposit_cancel (dh);
-}
-
-
-/**
- * Function called with the result from our call to the
- * auditor's /deposit-confirmation handler.
- *
- * @param cls closure of type `struct TEAH_AuditorInteractionEntry *`
- * @param dcr response
- */
-static void
-acc_confirmation_cb (
- void *cls,
- const struct TALER_AUDITOR_DepositConfirmationResponse *dcr)
-{
- struct TEAH_AuditorInteractionEntry *aie = cls;
- struct DONAU_BatchDepositHandle *dh = aie->dh;
-
- if (MHD_HTTP_OK != dcr->hr.http_status)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to submit deposit confirmation to auditor `%s' with
HTTP status %d (EC: %d). This is acceptable if it does not happen often.\n",
- aie->auditor_url,
- dcr->hr.http_status,
- dcr->hr.ec);
- }
- GNUNET_CONTAINER_DLL_remove (dh->ai_head,
- dh->ai_tail,
- aie);
- GNUNET_free (aie);
- if (NULL == dh->ai_head)
- finish_dh (dh);
-}
-
-
-/**
- * Function called for each auditor to give us a chance to possibly
- * launch a deposit confirmation interaction.
- *
- * @param cls closure
- * @param auditor_url base URL of the auditor
- * @param auditor_pub public key of the auditor
- */
-static void
-auditor_cb (void *cls,
- const char *auditor_url,
- const struct TALER_AuditorPublicKeyP *auditor_pub)
-{
- struct DONAU_BatchDepositHandle *dh = cls;
- const struct DONAU_SigningPublicKey *spk;
- struct TEAH_AuditorInteractionEntry *aie;
- struct TALER_Amount amount_without_fee;
- const struct DONAU_DenomPublicKey *dki;
- unsigned int coin;
-
- if (0 !=
- GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- dh->auditor_chance))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Not providing deposit confirmation to auditor\n");
- return;
- }
- coin = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- dh->num_cdds);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Will provide deposit confirmation to auditor `%s'\n",
- TALER_B2S (auditor_pub));
- dki = DONAU_get_denomination_key_by_hash (dh->keys,
- &dh->cdds[coin].h_denom_pub);
- GNUNET_assert (NULL != dki);
- spk = DONAU_get_signing_key_info (dh->keys,
- &dh->donau_pub);
- if (NULL == spk)
- {
- GNUNET_break_op (0);
- return;
- }
- GNUNET_assert (0 <=
- TALER_amount_subtract (&amount_without_fee,
- &dh->cdds[coin].amount,
- &dki->fees.deposit));
- aie = GNUNET_new (struct TEAH_AuditorInteractionEntry);
- aie->dh = dh;
- aie->auditor_url = auditor_url;
- aie->dch = TALER_AUDITOR_deposit_confirmation (
- dh->ctx,
- auditor_url,
- &dh->h_wire,
- &dh->h_policy,
- &dh->dcd.h_contract_terms,
- dh->donau_timestamp,
- dh->dcd.wire_deadline,
- dh->dcd.refund_deadline,
- &amount_without_fee,
- &dh->cdds[coin].coin_pub,
- &dh->dcd.charity_pub,
- &dh->donau_pub,
- &dh->donau_sigs[coin],
- &dh->keys->master_pub,
- spk->valid_from,
- spk->valid_until,
- spk->valid_legal,
- &spk->master_sig,
- &acc_confirmation_cb,
- aie);
- GNUNET_CONTAINER_DLL_insert (dh->ai_head,
- dh->ai_tail,
- aie);
-}
-
-
-/**
- * Function called when we're done processing the
- * HTTP /deposit request.
- *
- * @param cls the `struct DONAU_BatchDepositHandle`
- * @param response_code HTTP response code, 0 on error
- * @param response parsed JSON result, NULL on error
- */
-static void
-handle_deposit_finished (void *cls,
- long response_code,
- const void *response)
-{
- struct DONAU_BatchDepositHandle *dh = cls;
- const json_t *j = response;
- struct DONAU_BatchDepositResult *dr = &dh->dr;
-
- dh->job = NULL;
- dh->response = json_incref ((json_t*) j);
- dr->hr.reply = dh->response;
- dr->hr.http_status = (unsigned int) response_code;
- switch (response_code)
- {
- case 0:
- dr->hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
- break;
- case MHD_HTTP_OK:
- {
- const json_t *sigs;
- json_t *sig;
- unsigned int idx;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_array_const ("donau_sigs",
- &sigs),
- GNUNET_JSON_spec_fixed_auto ("donau_pub",
- &dh->donau_pub),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_string ("transaction_base_url",
- &dr->details.ok.transaction_base_url),
- NULL),
- GNUNET_JSON_spec_timestamp ("donau_timestamp",
- &dh->donau_timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- if (json_array_size (sigs) != dh->num_cdds)
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- dh->donau_sigs = GNUNET_new_array (dh->num_cdds,
- struct TALER_DonauSignatureP);
- if (GNUNET_OK !=
- DONAU_test_signing_key (dh->keys,
- &dh->donau_pub))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_DONAU_DEPOSIT_INVALID_SIGNATURE_BY_DONAU;
- break;
- }
- json_array_foreach (sigs, idx, sig)
- {
- struct GNUNET_JSON_Specification ispec[] = {
- GNUNET_JSON_spec_fixed_auto ("donau_sig",
- &dh->donau_sigs[idx]),
- GNUNET_JSON_spec_end ()
- };
- struct TALER_Amount amount_without_fee;
- const struct DONAU_DenomPublicKey *dki;
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (sig,
- ispec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- dki = DONAU_get_denomination_key_by_hash (dh->keys,
- &dh->cdds[idx].
- h_denom_pub);
- GNUNET_assert (NULL != dki);
- GNUNET_assert (0 <=
- TALER_amount_subtract (&amount_without_fee,
- &dh->cdds[idx].amount,
- &dki->fees.deposit));
-
- if (GNUNET_OK !=
- TALER_donau_online_deposit_confirmation_verify (
- &dh->dcd.h_contract_terms,
- &dh->h_wire,
- &dh->h_policy,
- dh->donau_timestamp,
- dh->dcd.wire_deadline,
- dh->dcd.refund_deadline,
- &amount_without_fee,
- &dh->cdds[idx].coin_pub,
- &dh->dcd.charity_pub,
- &dh->donau_pub,
- &dh->donau_sigs[idx]))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_DONAU_DEPOSIT_INVALID_SIGNATURE_BY_DONAU;
- break;
- }
- }
- TEAH_get_auditors_for_dc (dh->keys,
- &auditor_cb,
- dh);
- }
- dr->details.ok.donau_sigs = dh->donau_sigs;
- dr->details.ok.donau_pub = &dh->donau_pub;
- dr->details.ok.deposit_timestamp = dh->donau_timestamp;
- dr->details.ok.num_signatures = dh->num_cdds;
- break;
- case MHD_HTTP_BAD_REQUEST:
- /* This should never happen, either us or the donau is buggy
- (or API version conflict); just pass JSON reply to the application */
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_FORBIDDEN:
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, donau says one of the signatures is
- invalid; as we checked them, this should never happen, we
- should pass the JSON reply to the application */
- break;
- case MHD_HTTP_NOT_FOUND:
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the application */
- break;
- case MHD_HTTP_CONFLICT:
- {
- struct TALER_CoinSpendPublicKeyP coin_pub;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &coin_pub),
- GNUNET_JSON_spec_end ()
- };
- const struct DONAU_DenomPublicKey *dki;
- bool found = false;
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (j,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- for (unsigned int i = 0; i<dh->num_cdds; i++)
- {
- if (0 !=
- GNUNET_memcmp (&coin_pub,
- &dh->cdds[i].coin_pub))
- continue;
- dki = DONAU_get_denomination_key_by_hash (dh->keys,
- &dh->cdds[i].
- h_denom_pub);
- GNUNET_assert (NULL != dki);
- if (GNUNET_OK !=
- DONAU_check_coin_conflict_ (
- dh->keys,
- j,
- dki,
- &dh->cdds[i].coin_pub,
- &dh->cdds[i].coin_sig,
- &dh->cdds[i].amount))
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- found = true;
- break;
- }
- if (! found)
- {
- GNUNET_break_op (0);
- dr->hr.http_status = 0;
- dr->hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- }
- break;
- case MHD_HTTP_GONE:
- /* could happen if denomination was revoked */
- /* Note: one might want to check /keys for revocation
- signature here, alas tricky in case our /keys
- is outdated => left to clients */
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- break;
- case MHD_HTTP_INTERNAL_SERVER_ERROR:
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- /* Server had an internal issue; we should retry, but this API
- leaves this to the application */
- break;
- default:
- /* unexpected response code */
- dr->hr.ec = TALER_JSON_get_error_code (j);
- dr->hr.hint = TALER_JSON_get_error_hint (j);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected response code %u/%d for donau deposit\n",
- (unsigned int) response_code,
- dr->hr.ec);
- GNUNET_break_op (0);
- break;
- }
- if (NULL != dh->ai_head)
- return;
- finish_dh (dh);
-}
-
-
-struct DONAU_BatchDepositHandle *
-DONAU_batch_deposit (
- struct GNUNET_CURL_Context *ctx,
- const char *url,
- struct DONAU_Keys *keys,
- const struct DONAU_DepositContractDetail *dcd,
- unsigned int num_cdds,
- const struct DONAU_CoinDepositDetail cdds[static num_cdds],
- DONAU_BatchDepositResultCallback cb,
- void *cb_cls,
- enum TALER_ErrorCode *ec)
-{
- struct DONAU_BatchDepositHandle *dh;
- json_t *deposit_obj;
- json_t *deposits;
- CURL *eh;
- struct TALER_Amount amount_without_fee;
- const struct GNUNET_HashCode *wallet_data_hashp;
-
- if (GNUNET_TIME_timestamp_cmp (dcd->refund_deadline,
- >,
- dcd->wire_deadline))
- {
- GNUNET_break_op (0);
- *ec = TALER_EC_DONAU_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE;
- return NULL;
- }
- dh = GNUNET_new (struct DONAU_BatchDepositHandle);
- dh->auditor_chance = AUDITOR_CHANCE;
- dh->cb = cb;
- dh->cb_cls = cb_cls;
- dh->cdds = GNUNET_memdup (cdds,
- num_cdds
- * sizeof (*cdds));
- dh->num_cdds = num_cdds;
- dh->dcd = *dcd;
- if (NULL != dcd->policy_details)
- TALER_deposit_policy_hash (dcd->policy_details,
- &dh->h_policy);
- TALER_charity_wire_signature_hash (dcd->charity_payto_uri,
- &dcd->wire_salt,
- &dh->h_wire);
- deposits = json_array ();
- GNUNET_assert (NULL != deposits);
- for (unsigned int i = 0; i<num_cdds; i++)
- {
- const struct DONAU_CoinDepositDetail *cdd = &cdds[i];
- const struct DONAU_DenomPublicKey *dki;
- const struct TALER_AgeCommitmentHash *h_age_commitmentp;
-
- dki = DONAU_get_denomination_key_by_hash (keys,
- &cdd->h_denom_pub);
- if (NULL == dki)
- {
- *ec = TALER_EC_DONAU_GENERIC_DENOMINATION_KEY_UNKNOWN;
- GNUNET_break_op (0);
- return NULL;
- }
- if (0 >
- TALER_amount_subtract (&amount_without_fee,
- &cdd->amount,
- &dki->fees.deposit))
- {
- *ec = TALER_EC_DONAU_DEPOSIT_FEE_ABOVE_AMOUNT;
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Amount: %s\n",
- TALER_amount2s (&cdd->amount));
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Fee: %s\n",
- TALER_amount2s (&dki->fees.deposit));
- GNUNET_free (dh->cdds);
- GNUNET_free (dh);
- return NULL;
- }
-
- if (GNUNET_OK !=
- DONAU_verify_deposit_signature_ (dcd,
- &dh->h_policy,
- &dh->h_wire,
- cdd,
- dki))
- {
- *ec = TALER_EC_DONAU_DEPOSIT_COIN_SIGNATURE_INVALID;
- GNUNET_break_op (0);
- GNUNET_free (dh->cdds);
- GNUNET_free (dh);
- return NULL;
- }
- if (GNUNET_is_zero (&cdd->h_age_commitment))
- h_age_commitmentp = NULL;
- else
- h_age_commitmentp = &cdd->h_age_commitment;
- GNUNET_assert (
- 0 ==
- json_array_append_new (
- deposits,
- GNUNET_JSON_PACK (
- TALER_JSON_pack_amount ("contribution",
- &cdd->amount),
- GNUNET_JSON_pack_data_auto ("denom_pub_hash",
- &cdd->h_denom_pub),
- TALER_JSON_pack_denom_sig ("ub_sig",
- &cdd->denom_sig),
- GNUNET_JSON_pack_data_auto ("coin_pub",
- &cdd->coin_pub),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_data_auto ("h_age_commitment",
- h_age_commitmentp)),
- GNUNET_JSON_pack_data_auto ("coin_sig",
- &cdd->coin_sig)
- )));
- }
- dh->url = TALER_url_join (url,
- "batch-deposit",
- NULL);
- if (NULL == dh->url)
- {
- GNUNET_break (0);
- *ec = TALER_EC_GENERIC_ALLOCATION_FAILURE;
- GNUNET_free (dh->url);
- GNUNET_free (dh->cdds);
- GNUNET_free (dh);
- return NULL;
- }
-
- if (GNUNET_is_zero (&dcd->wallet_data_hash))
- wallet_data_hashp = NULL;
- else
- wallet_data_hashp = &dcd->wallet_data_hash;
-
- deposit_obj = GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("charity_payto_uri",
- dcd->charity_payto_uri),
- GNUNET_JSON_pack_data_auto ("wire_salt",
- &dcd->wire_salt),
- GNUNET_JSON_pack_data_auto ("h_contract_terms",
- &dcd->h_contract_terms),
- GNUNET_JSON_pack_array_steal ("coins",
- deposits),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_data_auto ("wallet_data_hash",
- wallet_data_hashp)),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_steal ("policy_details",
- (json_t *) dcd->policy_details)),
- GNUNET_JSON_pack_timestamp ("timestamp",
- dcd->wallet_timestamp),
- GNUNET_JSON_pack_data_auto ("charity_pub",
- &dcd->charity_pub),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_timestamp ("refund_deadline",
- dcd->refund_deadline)),
- GNUNET_JSON_pack_timestamp ("wire_transfer_deadline",
- dcd->wire_deadline));
- GNUNET_assert (NULL != deposit_obj);
- eh = DONAU_curl_easy_get_ (dh->url);
- if ( (NULL == eh) ||
- (GNUNET_OK !=
- TALER_curl_easy_post (&dh->post_ctx,
- eh,
- deposit_obj)) )
- {
- *ec = TALER_EC_GENERIC_CURL_ALLOCATION_FAILURE;
- GNUNET_break (0);
- if (NULL != eh)
- curl_easy_cleanup (eh);
- json_decref (deposit_obj);
- GNUNET_free (dh->cdds);
- GNUNET_free (dh->url);
- GNUNET_free (dh);
- return NULL;
- }
- json_decref (deposit_obj);
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "URL for deposit: `%s'\n",
- dh->url);
- dh->ctx = ctx;
- dh->keys = DONAU_keys_incref (keys);
- dh->job = GNUNET_CURL_job_add2 (ctx,
- eh,
- dh->post_ctx.headers,
- &handle_deposit_finished,
- dh);
- return dh;
-}
-
-
-void
-DONAU_batch_deposit_force_dc (
- struct DONAU_BatchDepositHandle *deposit)
-{
- deposit->auditor_chance = 1;
-}
-
-
-void
-DONAU_batch_deposit_cancel (
- struct DONAU_BatchDepositHandle *deposit)
-{
- struct TEAH_AuditorInteractionEntry *aie;
-
- while (NULL != (aie = deposit->ai_head))
- {
- GNUNET_assert (aie->dh == deposit);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Not sending deposit confirmation to auditor `%s' due to
cancellation\n",
- aie->auditor_url);
- TALER_AUDITOR_deposit_confirmation_cancel (aie->dch);
- GNUNET_CONTAINER_DLL_remove (deposit->ai_head,
- deposit->ai_tail,
- aie);
- GNUNET_free (aie);
- }
- if (NULL != deposit->job)
- {
- GNUNET_CURL_job_cancel (deposit->job);
- deposit->job = NULL;
- }
- DONAU_keys_decref (deposit->keys);
- GNUNET_free (deposit->url);
- GNUNET_free (deposit->cdds);
- GNUNET_free (deposit->donau_sigs);
- TALER_curl_easy_post_finished (&deposit->post_ctx);
- json_decref (deposit->response);
- GNUNET_free (deposit);
-}
-
-
-/* end of donau_api_batch_deposit.c */
diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c
index 9ebc96b..8466f11 100644
--- a/src/lib/donau_api_handle.c
+++ b/src/lib/donau_api_handle.c
@@ -128,54 +128,3 @@ struct DONAU_GetKeysHandle
if (cond) { GNUNET_break (0); goto EXITIF_exit; } \
} while (0)
-
-/**
- * Parse a donau's signing key encoded in JSON.
- *
- * @param[out] sign_key where to return the result
- * @param sign_key_obj json to parse
- * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
- * invalid or the @a sign_key_obj is malformed.
- */
-static enum GNUNET_GenericReturnValue
-parse_json_signkey (struct DONAU_SigningPublicKeyAndValidity *sign_key,
- const json_t *sign_key_obj)
-{
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("master_sig",
- &sign_key->master_sig),
- GNUNET_JSON_spec_fixed_auto ("key",
- &sign_key->key),
- GNUNET_JSON_spec_timestamp ("stamp_start",
- &sign_key->valid_from),
- GNUNET_JSON_spec_timestamp ("stamp_expire",
- &sign_key->valid_until),
- GNUNET_JSON_spec_timestamp ("stamp_end",
- &sign_key->valid_legal),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (sign_key_obj,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (! check_sigs)
- return GNUNET_OK;
- if (GNUNET_OK !=
- TALER_donau_offline_signkey_validity_verify (
- &sign_key->key,
- sign_key->valid_from,
- sign_key->valid_until,
- sign_key->valid_legal,
- master_key,
- &sign_key->master_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
diff --git a/src/lib/donau_api_issue_receipts.c
b/src/lib/donau_api_issue_receipts.c
index dc62019..37070b1 100644
--- a/src/lib/donau_api_issue_receipts.c
+++ b/src/lib/donau_api_issue_receipts.c
@@ -68,16 +68,6 @@ struct DONAU_WithdrawHandle
*/
void *cb_cls;
- /**
- * Reserve private key.
- */
- const struct TALER_ReservePrivateKeyP *reserve_priv;
-
- /**
- * Seed of the planchet.
- */
- struct TALER_PlanchetMasterSecretP ps;
-
/**
* blinding secret
*/
@@ -98,21 +88,11 @@ struct DONAU_WithdrawHandle
*/
struct TALER_DonauWithdrawValues alg_values;
- /**
- * Hash of the age commitment for this coin, if applicable. Maybe NULL
- */
- const struct TALER_AgeCommitmentHash *ach;
-
/**
* Denomination key we are withdrawing.
*/
struct DONAU_DenomPublicKey pk;
- /**
- * Hash of the public key of the coin we are signing.
- */
- struct TALER_CoinPubHashP c_hash;
-
/**
* Handler for the CS R request (only used for TALER_DENOMINATION_CS
denominations)
*/
@@ -121,85 +101,6 @@ struct DONAU_WithdrawHandle
};
-/**
- * Function called when we're done processing the
- * HTTP /reserves/$RESERVE_PUB/withdraw request.
- *
- * @param cls the `struct DONAU_WithdrawHandle`
- * @param w2r response data
- */
-static void
-handle_reserve_withdraw_finished (
- void *cls,
- const struct DONAU_Withdraw2Response *w2r)
-{
- struct DONAU_WithdrawHandle *wh = cls;
- struct DONAU_WithdrawResponse wr = {
- .hr = w2r->hr
- };
-
- wh->wh2 = NULL;
- switch (w2r->hr.http_status)
- {
- case MHD_HTTP_OK:
- {
- struct TALER_FreshCoin fc;
-
- if (GNUNET_OK !=
- TALER_planchet_to_coin (&wh->pk.key,
- &w2r->details.ok.blind_sig,
- &wh->bks,
- &wh->priv,
- wh->ach,
- &wh->c_hash,
- &wh->alg_values,
- &fc))
- {
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_DONAU_WITHDRAW_UNBLIND_FAILURE;
- break;
- }
- wr.details.ok.coin_priv = wh->priv;
- wr.details.ok.bks = wh->bks;
- wr.details.ok.sig = fc.sig;
- wr.details.ok.donau_vals = wh->alg_values;
- break;
- }
- case MHD_HTTP_UNAVAILABLE_FOR_LEGAL_REASONS:
- {
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto (
- "h_payto",
- &wr.details.unavailable_for_legal_reasons.h_payto),
- GNUNET_JSON_spec_uint64 (
- "requirement_row",
- &wr.details.unavailable_for_legal_reasons.requirement_row),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (w2r->hr.reply,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- wr.hr.http_status = 0;
- wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
- break;
- }
- }
- break;
- default:
- break;
- }
- wh->cb (wh->cb_cls,
- &wr);
- if (MHD_HTTP_OK == w2r->hr.http_status)
- TALER_denom_sig_free (&wr.details.ok.sig);
- DONAU_withdraw_cancel (wh);
-}
-
-
/**
* Function called when stage 1 of CS withdraw is finished (request r_pub's)
*
diff --git a/src/testing/testing_api_misc.c b/src/testing/testing_api_misc.c
index dda3895..8de3795 100644
--- a/src/testing/testing_api_misc.c
+++ b/src/testing/testing_api_misc.c
@@ -226,12 +226,10 @@ TALER_TESTING_cleanup_files_cfg (
(void) cls;
if (GNUNET_OK !=
GNUNET_CONFIGURATION_get_value_filename (cfg,
- "donau-offline",
"SECM_TOFU_FILE",
&dir))
{
GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
- "donau-offline",
"SECM_TOFU_FILE");
return GNUNET_SYSERR;
}
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/01
- [taler-donau] branch master updated: cleanup,
gnunet <=
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/02
- [taler-donau] branch master updated: cleanup, gnunet, 2024/01/05