summaryrefslogtreecommitdiff
path: root/src/lib/exchange_api_common.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-09-18 22:11:28 +0200
committerChristian Grothoff <christian@grothoff.org>2023-09-18 22:11:28 +0200
commitdfe576f9379954ab8164da7521bef930d3af3948 (patch)
treeb7fffe7cfc8767df6b672ccfd08614b550352f1c /src/lib/exchange_api_common.c
parent12cff1b4439ab5dcc26fcf79e19518ae1bdce069 (diff)
downloadexchange-dfe576f9379954ab8164da7521bef930d3af3948.tar.gz
exchange-dfe576f9379954ab8164da7521bef930d3af3948.tar.bz2
exchange-dfe576f9379954ab8164da7521bef930d3af3948.zip
more work on new history logic
Diffstat (limited to 'src/lib/exchange_api_common.c')
-rw-r--r--src/lib/exchange_api_common.c1633
1 files changed, 2 insertions, 1631 deletions
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index 3ad880171..4846e1188 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2015-2022 Taler Systems SA
+ Copyright (C) 2015-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
@@ -27,1542 +27,6 @@
#include "taler_signatures.h"
-/**
- * Context for history entry helpers.
- */
-struct HistoryParseContext
-{
-
- /**
- * Keys of the exchange we use.
- */
- const struct TALER_EXCHANGE_Keys *keys;
-
- /**
- * Our reserve public key.
- */
- const struct TALER_ReservePublicKeyP *reserve_pub;
-
- /**
- * Array of UUIDs.
- */
- struct GNUNET_HashCode *uuids;
-
- /**
- * Where to sum up total inbound amounts.
- */
- struct TALER_Amount *total_in;
-
- /**
- * Where to sum up total outbound amounts.
- */
- struct TALER_Amount *total_out;
-
- /**
- * Number of entries already used in @e uuids.
- */
- unsigned int uuid_off;
-};
-
-
-/**
- * Type of a function called to parse a reserve history
- * entry @a rh.
- *
- * @param[in,out] rh where to write the result
- * @param[in,out] uc UUID context for duplicate detection
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-typedef enum GNUNET_GenericReturnValue
-(*ParseHelper)(struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction);
-
-
-/**
- * Parse "credit" reserve history entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_credit (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- const char *wire_url;
- uint64_t wire_reference;
- struct GNUNET_TIME_Timestamp timestamp;
- struct GNUNET_JSON_Specification withdraw_spec[] = {
- GNUNET_JSON_spec_uint64 ("wire_reference",
- &wire_reference),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_string ("sender_account_url",
- &wire_url),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_CREDIT;
- if (0 >
- TALER_amount_add (uc->total_in,
- uc->total_in,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- withdraw_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rh->details.in_details.sender_url = GNUNET_strdup (wire_url);
- rh->details.in_details.wire_reference = wire_reference;
- rh->details.in_details.timestamp = timestamp;
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "credit" reserve history entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_withdraw (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- struct TALER_ReserveSignatureP sig;
- struct TALER_DenominationHashP h_denom_pub;
- struct TALER_BlindedCoinHashP bch;
- struct TALER_Amount withdraw_fee;
- struct GNUNET_JSON_Specification withdraw_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &sig),
- TALER_JSON_spec_amount_any ("withdraw_fee",
- &withdraw_fee),
- GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
- &h_denom_pub),
- GNUNET_JSON_spec_fixed_auto ("h_coin_envelope",
- &bch),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_WITHDRAWAL;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- withdraw_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* Check that the signature is a valid withdraw request */
- if (GNUNET_OK !=
- TALER_wallet_withdraw_verify (&h_denom_pub,
- &rh->amount,
- &bch,
- uc->reserve_pub,
- &sig))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- /* check that withdraw fee matches expectations! */
- {
- const struct TALER_EXCHANGE_Keys *key_state;
- const struct TALER_EXCHANGE_DenomPublicKey *dki;
-
- key_state = uc->keys;
- dki = TALER_EXCHANGE_get_denomination_key_by_hash (key_state,
- &h_denom_pub);
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&withdraw_fee,
- &dki->fees.withdraw)) ||
- (0 !=
- TALER_amount_cmp (&withdraw_fee,
- &dki->fees.withdraw)) )
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- rh->details.withdraw.fee = withdraw_fee;
- }
- rh->details.withdraw.out_authorization_sig
- = json_object_get (transaction,
- "signature");
- /* Check check that the same withdraw transaction
- isn't listed twice by the exchange. We use the
- "uuid" array to remember the hashes of all
- signatures, and compare the hashes to find
- duplicates. */
- GNUNET_CRYPTO_hash (&sig,
- sizeof (sig),
- &uc->uuids[uc->uuid_off]);
- for (unsigned int i = 0; i<uc->uuid_off; i++)
- {
- if (0 == GNUNET_memcmp (&uc->uuids[uc->uuid_off],
- &uc->uuids[i]))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- }
- uc->uuid_off++;
-
- if (0 >
- TALER_amount_add (uc->total_out,
- uc->total_out,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (withdraw_spec);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "recoup" reserve history entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_recoup (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification recoup_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &rh->details.recoup_details.coin_pub),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &rh->details.recoup_details.exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &rh->details.recoup_details.exchange_pub),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &rh->details.recoup_details.timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_RECOUP;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- recoup_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = uc->keys;
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (key_state,
- &rh->details.
- recoup_details.exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_confirm_recoup_verify (
- rh->details.recoup_details.timestamp,
- &rh->amount,
- &rh->details.recoup_details.coin_pub,
- uc->reserve_pub,
- &rh->details.recoup_details.exchange_pub,
- &rh->details.recoup_details.exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 >
- TALER_amount_add (uc->total_in,
- uc->total_in,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "closing" reserve history entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_closing (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- const struct TALER_EXCHANGE_Keys *key_state;
- struct GNUNET_JSON_Specification closing_spec[] = {
- GNUNET_JSON_spec_string (
- "receiver_account_details",
- &rh->details.close_details.receiver_account_details),
- GNUNET_JSON_spec_fixed_auto ("wtid",
- &rh->details.close_details.wtid),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &rh->details.close_details.exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &rh->details.close_details.exchange_pub),
- TALER_JSON_spec_amount_any ("closing_fee",
- &rh->details.close_details.fee),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &rh->details.close_details.timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_CLOSING;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- closing_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- key_state = uc->keys;
- if (GNUNET_OK !=
- TALER_EXCHANGE_test_signing_key (
- key_state,
- &rh->details.close_details.exchange_pub))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_reserve_closed_verify (
- rh->details.close_details.timestamp,
- &rh->amount,
- &rh->details.close_details.fee,
- rh->details.close_details.receiver_account_details,
- &rh->details.close_details.wtid,
- uc->reserve_pub,
- &rh->details.close_details.exchange_pub,
- &rh->details.close_details.exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 >
- TALER_amount_add (uc->total_out,
- uc->total_out,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "merge" reserve history entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_merge (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- uint32_t flags32;
- struct GNUNET_JSON_Specification merge_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &rh->details.merge_details.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("merge_pub",
- &rh->details.merge_details.merge_pub),
- GNUNET_JSON_spec_fixed_auto ("purse_pub",
- &rh->details.merge_details.purse_pub),
- GNUNET_JSON_spec_uint32 ("min_age",
- &rh->details.merge_details.min_age),
- GNUNET_JSON_spec_uint32 ("flags",
- &flags32),
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &rh->details.merge_details.reserve_sig),
- TALER_JSON_spec_amount_any ("purse_fee",
- &rh->details.merge_details.purse_fee),
- GNUNET_JSON_spec_timestamp ("merge_timestamp",
- &rh->details.merge_details.merge_timestamp),
- GNUNET_JSON_spec_timestamp ("purse_expiration",
- &rh->details.merge_details.purse_expiration),
- GNUNET_JSON_spec_bool ("merged",
- &rh->details.merge_details.merged),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_MERGE;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- merge_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- rh->details.merge_details.flags =
- (enum TALER_WalletAccountMergeFlags) flags32;
- if (GNUNET_OK !=
- TALER_wallet_account_merge_verify (
- rh->details.merge_details.merge_timestamp,
- &rh->details.merge_details.purse_pub,
- rh->details.merge_details.purse_expiration,
- &rh->details.merge_details.h_contract_terms,
- &rh->amount,
- &rh->details.merge_details.purse_fee,
- rh->details.merge_details.min_age,
- rh->details.merge_details.flags,
- uc->reserve_pub,
- &rh->details.merge_details.reserve_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (rh->details.merge_details.merged)
- {
- if (0 >
- TALER_amount_add (uc->total_in,
- uc->total_in,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- else
- {
- if (0 >
- TALER_amount_add (uc->total_out,
- uc->total_out,
- &rh->details.merge_details.purse_fee))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "open" reserve open entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_open (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- struct GNUNET_JSON_Specification open_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &rh->details.open_request.reserve_sig),
- TALER_JSON_spec_amount_any ("open_payment",
- &rh->details.open_request.reserve_payment),
- GNUNET_JSON_spec_uint32 ("requested_min_purses",
- &rh->details.open_request.purse_limit),
- GNUNET_JSON_spec_timestamp ("request_timestamp",
- &rh->details.open_request.request_timestamp),
- GNUNET_JSON_spec_timestamp ("requested_expiration",
- &rh->details.open_request.reserve_expiration),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_OPEN;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- open_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_reserve_open_verify (
- &rh->amount,
- rh->details.open_request.request_timestamp,
- rh->details.open_request.reserve_expiration,
- rh->details.open_request.purse_limit,
- uc->reserve_pub,
- &rh->details.open_request.reserve_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 >
- TALER_amount_add (uc->total_out,
- uc->total_out,
- &rh->amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Parse "close" reserve close entry.
- *
- * @param[in,out] rh entry to parse
- * @param uc our context
- * @param transaction the transaction to parse
- * @return #GNUNET_OK on success
- */
-static enum GNUNET_GenericReturnValue
-parse_close (struct TALER_EXCHANGE_ReserveHistoryEntry *rh,
- struct HistoryParseContext *uc,
- const json_t *transaction)
-{
- struct GNUNET_JSON_Specification close_spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &rh->details.close_request.reserve_sig),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_payto",
- &rh->details.close_request.
- target_account_h_payto),
- NULL),
- GNUNET_JSON_spec_timestamp ("request_timestamp",
- &rh->details.close_request.request_timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- rh->type = TALER_EXCHANGE_RTT_CLOSE;
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- close_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* force amount to invalid */
- memset (&rh->amount,
- 0,
- sizeof (rh->amount));
- if (GNUNET_OK !=
- TALER_wallet_reserve_close_verify (
- rh->details.close_request.request_timestamp,
- &rh->details.close_request.target_account_h_payto,
- uc->reserve_pub,
- &rh->details.close_request.reserve_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGE_parse_reserve_history (
- const struct TALER_EXCHANGE_Keys *keys,
- const json_t *history,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const char *currency,
- struct TALER_Amount *total_in,
- struct TALER_Amount *total_out,
- unsigned int history_length,
- struct TALER_EXCHANGE_ReserveHistoryEntry rhistory[static history_length])
-{
- const struct
- {
- const char *type;
- ParseHelper helper;
- } map[] = {
- { "CREDIT", &parse_credit },
- { "WITHDRAW", &parse_withdraw },
- { "RECOUP", &parse_recoup },
- { "MERGE", &parse_merge },
- { "CLOSING", &parse_closing },
- { "OPEN", &parse_open },
- { "CLOSE", &parse_close },
- { NULL, NULL }
- };
- struct GNUNET_HashCode uuid[history_length];
- struct HistoryParseContext uc = {
- .keys = keys,
- .reserve_pub = reserve_pub,
- .uuids = uuid,
- .total_in = total_in,
- .total_out = total_out
- };
-
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (currency,
- total_in));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (currency,
- total_out));
- for (unsigned int off = 0; off<history_length; off++)
- {
- struct TALER_EXCHANGE_ReserveHistoryEntry *rh = &rhistory[off];
- json_t *transaction;
- struct TALER_Amount amount;
- const char *type;
- struct GNUNET_JSON_Specification hist_spec[] = {
- GNUNET_JSON_spec_string ("type",
- &type),
- TALER_JSON_spec_amount_any ("amount",
- &amount),
- /* 'wire' and 'signature' are optional depending on 'type'! */
- GNUNET_JSON_spec_end ()
- };
- bool found = false;
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- hist_spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- json_dumpf (transaction,
- stderr,
- JSON_INDENT (2));
- return GNUNET_SYSERR;
- }
- rh->amount = amount;
- if (GNUNET_YES !=
- TALER_amount_cmp_currency (&amount,
- total_in))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- for (unsigned int i = 0; NULL != map[i].type; i++)
- {
- if (0 == strcasecmp (map[i].type,
- type))
- {
- found = true;
- if (GNUNET_OK !=
- map[i].helper (rh,
- &uc,
- transaction))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- break;
- }
- }
- if (! found)
- {
- /* unexpected 'type', protocol incompatibility, complain! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- return GNUNET_OK;
-}
-
-
-void
-TALER_EXCHANGE_free_reserve_history (
- unsigned int len,
- struct TALER_EXCHANGE_ReserveHistoryEntry rhistory[static len])
-{
- for (unsigned int i = 0; i<len; i++)
- {
- switch (rhistory[i].type)
- {
- case TALER_EXCHANGE_RTT_CREDIT:
- GNUNET_free (rhistory[i].details.in_details.sender_url);
- break;
- case TALER_EXCHANGE_RTT_WITHDRAWAL:
- break;
- case TALER_EXCHANGE_RTT_AGEWITHDRAWAL:
- break;
- case TALER_EXCHANGE_RTT_RECOUP:
- break;
- case TALER_EXCHANGE_RTT_CLOSING:
- break;
- case TALER_EXCHANGE_RTT_MERGE:
- break;
- case TALER_EXCHANGE_RTT_OPEN:
- break;
- case TALER_EXCHANGE_RTT_CLOSE:
- break;
- }
- }
- GNUNET_free (rhistory);
-}
-
-
-/**
- * Context for coin helpers.
- */
-struct CoinHistoryParseContext
-{
-
- /**
- * Denomination of the coin.
- */
- const struct TALER_EXCHANGE_DenomPublicKey *dk;
-
- /**
- * Our coin public key.
- */
- const struct TALER_CoinSpendPublicKeyP *coin_pub;
-
- /**
- * Where to sum up total refunds.
- */
- struct TALER_Amount rtotal;
-
- /**
- * Total amount encountered.
- */
- struct TALER_Amount *total;
-
-};
-
-
-/**
- * Signature of functions that operate on one of
- * the coin's history entries.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-typedef enum GNUNET_GenericReturnValue
-(*CoinCheckHelper)(struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction);
-
-
-/**
- * Handle deposit entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_deposit (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_MerchantWireHashP h_wire;
- struct TALER_PrivateContractHashP h_contract_terms;
- struct TALER_ExtensionPolicyHashP h_policy;
- bool no_h_policy;
- struct GNUNET_HashCode wallet_data_hash;
- bool no_wallet_data_hash;
- struct GNUNET_TIME_Timestamp wallet_timestamp;
- struct TALER_MerchantPublicKeyP merchant_pub;
- struct GNUNET_TIME_Timestamp refund_deadline = {0};
- struct TALER_CoinSpendSignatureP sig;
- struct TALER_AgeCommitmentHash hac;
- bool no_hac;
- struct TALER_Amount deposit_fee;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &h_contract_terms),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("wallet_data_hash",
- &wallet_data_hash),
- &no_wallet_data_hash),
- GNUNET_JSON_spec_fixed_auto ("h_wire",
- &h_wire),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
- &hac),
- &no_hac),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_policy",
- &h_policy),
- &no_h_policy),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &wallet_timestamp),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_timestamp ("refund_deadline",
- &refund_deadline),
- NULL),
- TALER_JSON_spec_amount_any ("deposit_fee",
- &deposit_fee),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &merchant_pub),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_deposit_verify (
- amount,
- &deposit_fee,
- &h_wire,
- &h_contract_terms,
- no_wallet_data_hash ? NULL : &wallet_data_hash,
- no_hac ? NULL : &hac,
- no_h_policy ? NULL : &h_policy,
- &pc->dk->h_key,
- wallet_timestamp,
- &merchant_pub,
- refund_deadline,
- pc->coin_pub,
- &sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* check that deposit fee matches our expectations from /keys! */
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&deposit_fee,
- &pc->dk->fees.deposit)) ||
- (0 !=
- TALER_amount_cmp (&deposit_fee,
- &pc->dk->fees.deposit)) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Handle melt entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_melt (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_CoinSpendSignatureP sig;
- struct TALER_RefreshCommitmentP rc;
- struct TALER_AgeCommitmentHash h_age_commitment;
- bool no_hac;
- struct TALER_Amount melt_fee;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("rc",
- &rc),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
- &h_age_commitment),
- &no_hac),
- TALER_JSON_spec_amount_any ("melt_fee",
- &melt_fee),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
-
- /* check that melt fee matches our expectations from /keys! */
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&melt_fee,
- &pc->dk->fees.refresh)) ||
- (0 !=
- TALER_amount_cmp (&melt_fee,
- &pc->dk->fees.refresh)) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_melt_verify (
- amount,
- &melt_fee,
- &rc,
- &pc->dk->h_key,
- no_hac
- ? NULL
- : &h_age_commitment,
- pc->coin_pub,
- &sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Handle refund entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_refund (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_PrivateContractHashP h_contract_terms;
- struct TALER_MerchantPublicKeyP merchant_pub;
- struct TALER_MerchantSignatureP sig;
- struct TALER_Amount refund_fee;
- struct TALER_Amount sig_amount;
- uint64_t rtransaction_id;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("refund_fee",
- &refund_fee),
- GNUNET_JSON_spec_fixed_auto ("merchant_sig",
- &sig),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
- &h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub",
- &merchant_pub),
- GNUNET_JSON_spec_uint64 ("rtransaction_id",
- &rtransaction_id),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (0 >
- TALER_amount_add (&sig_amount,
- &refund_fee,
- amount))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_merchant_refund_verify (pc->coin_pub,
- &h_contract_terms,
- rtransaction_id,
- &sig_amount,
- &merchant_pub,
- &sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- /* NOTE: theoretically, we could also check that the given
- merchant_pub and h_contract_terms appear in the
- history under deposits. However, there is really no benefit
- for the exchange to lie here, so not checking is probably OK
- (an auditor ought to check, though). Then again, we similarly
- had no reason to check the merchant's signature (other than a
- well-formendess check). */
-
- /* check that refund fee matches our expectations from /keys! */
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund_fee,
- &pc->dk->fees.refund)) ||
- (0 !=
- TALER_amount_cmp (&refund_fee,
- &pc->dk->fees.refund)) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Handle recoup entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_recoup (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_ReservePublicKeyP reserve_pub;
- struct GNUNET_TIME_Timestamp timestamp;
- union TALER_DenominationBlindingKeyP coin_bks;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_CoinSpendSignatureP coin_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
- GNUNET_JSON_spec_fixed_auto ("reserve_pub",
- &reserve_pub),
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &coin_sig),
- GNUNET_JSON_spec_fixed_auto ("coin_blind",
- &coin_bks),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_confirm_recoup_verify (
- timestamp,
- amount,
- pc->coin_pub,
- &reserve_pub,
- &exchange_pub,
- &exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_recoup_verify (&pc->dk->h_key,
- &coin_bks,
- pc->coin_pub,
- &coin_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Handle recoup-refresh entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_recoup_refresh (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- /* This is the coin that was subjected to a recoup,
- the value being credited to the old coin. */
- struct TALER_CoinSpendPublicKeyP old_coin_pub;
- union TALER_DenominationBlindingKeyP coin_bks;
- struct GNUNET_TIME_Timestamp timestamp;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_CoinSpendSignatureP coin_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &coin_sig),
- GNUNET_JSON_spec_fixed_auto ("old_coin_pub",
- &old_coin_pub),
- GNUNET_JSON_spec_fixed_auto ("coin_blind",
- &coin_bks),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_confirm_recoup_refresh_verify (
- timestamp,
- amount,
- pc->coin_pub,
- &old_coin_pub,
- &exchange_pub,
- &exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_recoup_verify (&pc->dk->h_key,
- &coin_bks,
- pc->coin_pub,
- &coin_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Handle old coin recoup entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_old_coin_recoup (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- /* This is the coin that was credited in a recoup,
- the value being credited to the this coin. */
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct TALER_CoinSpendPublicKeyP new_coin_pub;
- struct GNUNET_TIME_Timestamp timestamp;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &new_coin_pub),
- GNUNET_JSON_spec_timestamp ("timestamp",
- &timestamp),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_confirm_recoup_refresh_verify (
- timestamp,
- amount,
- &new_coin_pub,
- pc->coin_pub,
- &exchange_pub,
- &exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Handle purse deposit entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_purse_deposit (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_CoinSpendSignatureP coin_sig;
- const char *exchange_base_url;
- bool refunded;
- struct TALER_AgeCommitmentHash phac = { 0 };
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("purse_pub",
- &purse_pub),
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &coin_sig),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
- &coin_sig),
- NULL),
- GNUNET_JSON_spec_string ("exchange_base_url",
- &exchange_base_url),
- GNUNET_JSON_spec_mark_optional (
- GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
- &phac),
- NULL),
- GNUNET_JSON_spec_bool ("refunded",
- &refunded),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_purse_deposit_verify (
- exchange_base_url,
- &purse_pub,
- amount,
- &pc->dk->h_key,
- &phac,
- pc->coin_pub,
- &coin_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (refunded)
- {
- /* We wave the deposit fee. */
- if (0 >
- TALER_amount_add (&pc->rtotal,
- &pc->rtotal,
- &pc->dk->fees.deposit))
- {
- /* overflow in refund history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Handle purse refund entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_purse_refund (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_PurseContractPublicKeyP purse_pub;
- struct TALER_Amount refund_fee;
- struct TALER_ExchangePublicKeyP exchange_pub;
- struct TALER_ExchangeSignatureP exchange_sig;
- struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount_any ("refund_fee",
- &refund_fee),
- GNUNET_JSON_spec_fixed_auto ("purse_pub",
- &purse_pub),
- GNUNET_JSON_spec_fixed_auto ("exchange_sig",
- &exchange_sig),
- GNUNET_JSON_spec_fixed_auto ("exchange_pub",
- &exchange_pub),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_exchange_online_purse_refund_verify (
- amount,
- &refund_fee,
- pc->coin_pub,
- &purse_pub,
- &exchange_pub,
- &exchange_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund_fee,
- &pc->dk->fees.refund)) ||
- (0 !=
- TALER_amount_cmp (&refund_fee,
- &pc->dk->fees.refund)) )
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_NO;
-}
-
-
-/**
- * Handle reserve deposit entry in the coin's history.
- *
- * @param[in,out] pc overall context
- * @param amount main amount of this operation
- * @param transaction JSON details for the operation
- * @return #GNUNET_SYSERR on error,
- * #GNUNET_OK to add, #GNUNET_NO to subtract
- */
-static enum GNUNET_GenericReturnValue
-help_reserve_open_deposit (struct CoinHistoryParseContext *pc,
- const struct TALER_Amount *amount,
- json_t *transaction)
-{
- struct TALER_ReserveSignatureP reserve_sig;
- struct TALER_CoinSpendSignatureP coin_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &reserve_sig),
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &coin_sig),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_OK !=
- TALER_wallet_reserve_open_deposit_verify (
- amount,
- &reserve_sig,
- pc->coin_pub,
- &coin_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_YES;
-}
-
-
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGE_verify_coin_history (
- const struct TALER_EXCHANGE_DenomPublicKey *dk,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const json_t *history,
- struct TALER_Amount *total)
-{
- const char *currency = dk->value.currency;
- const struct
- {
- const char *type;
- CoinCheckHelper helper;
- } map[] = {
- { "DEPOSIT", &help_deposit },
- { "MELT", &help_melt },
- { "REFUND", &help_refund },
- { "RECOUP", &help_recoup },
- { "RECOUP-REFRESH", &help_recoup_refresh },
- { "OLD-COIN-RECOUP", &help_old_coin_recoup },
- { "PURSE-DEPOSIT", &help_purse_deposit },
- { "PURSE-REFUND", &help_purse_refund },
- { "RESERVE-OPEN-DEPOSIT", &help_reserve_open_deposit },
- { NULL, NULL }
- };
- struct CoinHistoryParseContext pc = {
- .dk = dk,
- .coin_pub = coin_pub,
- .total = total
- };
- size_t len;
-
- if (NULL == history)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- len = json_array_size (history);
- if (0 == len)
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (currency,
- total));
- GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (currency,
- &pc.rtotal));
- for (size_t off = 0; off<len; off++)
- {
- enum GNUNET_GenericReturnValue add;
- json_t *transaction;
- struct TALER_Amount amount;
- const char *type;
- struct GNUNET_JSON_Specification spec_glob[] = {
- TALER_JSON_spec_amount_any ("amount",
- &amount),
- GNUNET_JSON_spec_string ("type",
- &type),
- GNUNET_JSON_spec_end ()
- };
-
- transaction = json_array_get (history,
- off);
- if (GNUNET_OK !=
- GNUNET_JSON_parse (transaction,
- spec_glob,
- NULL, NULL))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- if (GNUNET_YES !=
- TALER_amount_cmp_currency (&amount,
- &pc.rtotal))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Operation of type %s with amount %s\n",
- type,
- TALER_amount2s (&amount));
- add = GNUNET_SYSERR;
- for (unsigned int i = 0; NULL != map[i].type; i++)
- {
- if (0 == strcasecmp (type,
- map[i].type))
- {
- add = map[i].helper (&pc,
- &amount,
- transaction);
- break;
- }
- }
- switch (add)
- {
- case GNUNET_SYSERR:
- /* entry type not supported, new version on server? */
- GNUNET_break_op (0);
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Unexpected type `%s' in response\n",
- type);
- return GNUNET_SYSERR;
- case GNUNET_YES:
- /* This amount should be added to the total */
- if (0 >
- TALER_amount_add (total,
- total,
- &amount))
- {
- /* overflow in history already!? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- break;
- case GNUNET_NO:
- /* This amount should be subtracted from the total.
-
- However, for the implementation, we first *add* up all of
- these negative amounts, as we might get refunds before
- deposits from a semi-evil exchange. Then, at the end, we do
- the subtraction by calculating "total = total - rtotal" */
- if (0 >
- TALER_amount_add (&pc.rtotal,
- &pc.rtotal,
- &amount))
- {
- /* overflow in refund history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- break;
- } /* end of switch(add) */
- }
- /* Finally, subtract 'rtotal' from total to handle the subtractions */
- if (0 >
- TALER_amount_subtract (total,
- total,
- &pc.rtotal))
- {
- /* underflow in history? inconceivable! Bad exchange! */
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
const struct TALER_EXCHANGE_SigningPublicKey *
TALER_EXCHANGE_get_signing_key_info (
const struct TALER_EXCHANGE_Keys *keys,
@@ -1811,59 +275,7 @@ TALER_EXCHANGE_check_purse_econtract_conflict_ (
}
-/**
- * Verify that @a coin_sig does NOT appear in
- * the history of @a proof and thus whatever transaction
- * is authorized by @a coin_sig is a conflict with
- * @a proof.
- *
- * @param proof a proof to check
- * @param coin_sig signature that must not be in @a proof
- * @return #GNUNET_OK if @a coin_sig is not in @a proof
- */
-// FIXME: move to exchange_api_coin_history.c!
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGE_check_coin_signature_conflict_ (
- const json_t *proof,
- const struct TALER_CoinSpendSignatureP *coin_sig)
-{
- json_t *history;
- size_t off;
- json_t *entry;
-
- history = json_object_get (proof,
- "history");
- if (NULL == history)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- json_array_foreach (history, off, entry)
- {
- struct TALER_CoinSpendSignatureP cs;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_sig",
- &cs),
- GNUNET_JSON_spec_end ()
- };
-
- if (GNUNET_OK !=
- GNUNET_JSON_parse (entry,
- spec,
- NULL, NULL))
- continue; /* entry without coin signature */
- if (0 ==
- GNUNET_memcmp (&cs,
- coin_sig))
- {
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- }
- return GNUNET_OK;
-}
-
-
+// FIXME: should be used...
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_check_coin_denomination_conflict_ (
const json_t *proof,
@@ -1896,47 +308,6 @@ TALER_EXCHANGE_check_coin_denomination_conflict_ (
}
-/**
- * Check that the provided @a proof indeeds indicates
- * a conflict for @a coin_pub.
- *
- * @param keys exchange keys
- * @param proof provided conflict proof
- * @param dk denomination of @a coin_pub that the client
- * used
- * @param coin_pub public key of the coin
- * @param required balance required on the coin for the operation
- * @return #GNUNET_OK if @a proof holds
- */
-// FIXME: move to exchange_api_coin_history.c!
-enum GNUNET_GenericReturnValue
-TALER_EXCHANGE_check_coin_conflict_ (
- const struct TALER_EXCHANGE_Keys *keys,
- const json_t *proof,
- const struct TALER_EXCHANGE_DenomPublicKey *dk,
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_Amount *required)
-{
- enum TALER_ErrorCode ec;
-
- ec = TALER_JSON_get_error_code (proof);
- switch (ec)
- {
- case TALER_EC_EXCHANGE_GENERIC_INSUFFICIENT_FUNDS:
- /* Nothing to check anymore here, proof needs to be
- checked in the GET /coins/$COIN_PUB handler */
- break;
- case TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_DENOMINATION_KEY:
- // FIXME: write check!
- break;
- default:
- GNUNET_break_op (0);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
enum GNUNET_GenericReturnValue
TALER_EXCHANGE_get_min_denomination_ (
const struct TALER_EXCHANGE_Keys *keys,