summaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/Makefile.am1
-rw-r--r--src/exchange/taler-exchange-httpd.c6
-rw-r--r--src/exchange/taler-exchange-httpd_coins_get.c490
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_get.c2
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_history.c429
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_history.h5
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_status.c243
-rw-r--r--src/exchange/taler-exchange-httpd_reserves_status.h43
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c911
-rw-r--r--src/exchange/taler-exchange-httpd_responses.h24
10 files changed, 826 insertions, 1328 deletions
diff --git a/src/exchange/Makefile.am b/src/exchange/Makefile.am
index dded2b1f0..86829edda 100644
--- a/src/exchange/Makefile.am
+++ b/src/exchange/Makefile.am
@@ -180,7 +180,6 @@ taler_exchange_httpd_SOURCES = \
taler-exchange-httpd_reserves_history.c taler-exchange-httpd_reserves_history.h \
taler-exchange-httpd_reserves_open.c taler-exchange-httpd_reserves_open.h \
taler-exchange-httpd_reserves_purse.c taler-exchange-httpd_reserves_purse.h \
- taler-exchange-httpd_reserves_status.c taler-exchange-httpd_reserves_status.h \
taler-exchange-httpd_responses.c taler-exchange-httpd_responses.h \
taler-exchange-httpd_terms.c taler-exchange-httpd_terms.h \
taler-exchange-httpd_transfers_get.c taler-exchange-httpd_transfers_get.h \
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index ad4b50d23..d059e7430 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -67,7 +67,6 @@
#include "taler-exchange-httpd_reserves_history.h"
#include "taler-exchange-httpd_reserves_open.h"
#include "taler-exchange-httpd_reserves_purse.h"
-#include "taler-exchange-httpd_reserves_status.h"
#include "taler-exchange-httpd_terms.h"
#include "taler-exchange-httpd_transfers_get.h"
#include "taler-exchange-httpd_withdraw.h"
@@ -732,10 +731,7 @@ handle_post_reserves (struct TEH_RequestContext *rc,
.op = "withdraw",
.handler = &TEH_handler_withdraw
},
- {
- .op = "status",
- .handler = &TEH_handler_reserves_status
- },
+ // FIXME: change to GET!
{
.op = "history",
.handler = &TEH_handler_reserves_history
diff --git a/src/exchange/taler-exchange-httpd_coins_get.c b/src/exchange/taler-exchange-httpd_coins_get.c
index 9f61b38f6..c5cf6ba56 100644
--- a/src/exchange/taler-exchange-httpd_coins_get.c
+++ b/src/exchange/taler-exchange-httpd_coins_get.c
@@ -48,6 +48,492 @@ add_response_headers (void *cls,
}
+/**
+ * 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
+ */
+static json_t *
+compile_transaction_history (
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const struct TALER_EXCHANGEDB_TransactionList *tl)
+{
+ json_t *history;
+
+ history = json_array ();
+ if (NULL == history)
+ {
+ GNUNET_break (0); /* out of memory!? */
+ return NULL;
+ }
+ for (const struct TALER_EXCHANGEDB_TransactionList *pos = tl;
+ NULL != pos;
+ pos = pos->next)
+ {
+ switch (pos->type)
+ {
+ case TALER_EXCHANGEDB_TT_DEPOSIT:
+ {
+ const struct TALER_EXCHANGEDB_DepositListEntry *deposit =
+ pos->details.deposit;
+ struct TALER_MerchantWireHashP h_wire;
+
+ TALER_merchant_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... */
+ TEH_METRICS_num_verifications[TEH_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->merchant_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 (
+ // FIXME: offset missing! (here and in all other cases!)
+ 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 ("merchant_pub",
+ &deposit->merchant_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 TALER_EXCHANGEDB_TT_MELT:
+ {
+ const struct TALER_EXCHANGEDB_MeltListEntry *melt =
+ pos->details.melt;
+ const struct TALER_AgeCommitmentHash *phac = NULL;
+
+#if ENABLE_SANITY_CHECKS
+ TEH_METRICS_num_verifications[TEH_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 TALER_EXCHANGEDB_TT_REFUND:
+ {
+ const struct TALER_EXCHANGEDB_RefundListEntry *refund =
+ pos->details.refund;
+ struct TALER_Amount value;
+
+#if ENABLE_SANITY_CHECKS
+ TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
+ if (GNUNET_OK !=
+ TALER_merchant_refund_verify (
+ coin_pub,
+ &refund->h_contract_terms,
+ refund->rtransaction_id,
+ &refund->refund_amount,
+ &refund->merchant_pub,
+ &refund->merchant_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 ("merchant_pub",
+ &refund->merchant_pub),
+ GNUNET_JSON_pack_uint64 ("rtransaction_id",
+ refund->rtransaction_id),
+ GNUNET_JSON_pack_data_auto ("merchant_sig",
+ &refund->merchant_sig))))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ }
+ break;
+ case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
+ {
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *pr =
+ pos->details.old_coin_recoup;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ if (TALER_EC_NONE !=
+ TALER_exchange_online_confirm_recoup_refresh_sign (
+ &TEH_keys_exchange_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 ("exchange_sig",
+ &esig),
+ GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_RECOUP:
+ {
+ const struct TALER_EXCHANGEDB_RecoupListEntry *recoup =
+ pos->details.recoup;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ if (TALER_EC_NONE !=
+ TALER_exchange_online_confirm_recoup_sign (
+ &TEH_keys_exchange_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 ("exchange_sig",
+ &esig),
+ GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
+ {
+ struct TALER_EXCHANGEDB_RecoupRefreshListEntry *pr =
+ pos->details.recoup_refresh;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ if (TALER_EC_NONE !=
+ TALER_exchange_online_confirm_recoup_refresh_sign (
+ &TEH_keys_exchange_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 ("exchange_sig",
+ &esig),
+ GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
+ {
+ struct TALER_EXCHANGEDB_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 ("exchange_base_url",
+ NULL == pd->exchange_base_url
+ ? TEH_base_url
+ : pd->exchange_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 TALER_EXCHANGEDB_TT_PURSE_REFUND:
+ {
+ const struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund =
+ pos->details.purse_refund;
+ struct TALER_Amount value;
+ enum TALER_ErrorCode ec;
+ struct TALER_ExchangePublicKeyP epub;
+ struct TALER_ExchangeSignatureP esig;
+
+ if (0 >
+ TALER_amount_subtract (&value,
+ &prefund->refund_amount,
+ &prefund->refund_fee))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ ec = TALER_exchange_online_purse_refund_sign (
+ &TEH_keys_exchange_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 ("exchange_sig",
+ &esig),
+ GNUNET_JSON_pack_data_auto ("exchange_pub",
+ &epub),
+ GNUNET_JSON_pack_data_auto ("purse_pub",
+ &prefund->purse_pub))))
+ {
+ GNUNET_break (0);
+ json_decref (history);
+ return NULL;
+ }
+ }
+ break;
+
+ case TALER_EXCHANGEDB_TT_RESERVE_OPEN:
+ {
+ struct TALER_EXCHANGEDB_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
TEH_handler_coins_get (struct TEH_RequestContext *rc,
const struct TALER_CoinSpendPublicKeyP *coin_pub)
@@ -118,8 +604,8 @@ TEH_handler_coins_get (struct TEH_RequestContext *rc,
sizeof (etagp),
"\"%llu\"",
(unsigned long long) etag);
- history = TEH_RESPONSE_compile_transaction_history (coin_pub,
- tl);
+ history = compile_transaction_history (coin_pub,
+ tl);
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
tl = NULL;
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c b/src/exchange/taler-exchange-httpd_reserves_get.c
index bbaac8535..a46886ef4 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.c
+++ b/src/exchange/taler-exchange-httpd_reserves_get.c
@@ -253,7 +253,7 @@ TEH_handler_reserves_get (struct TEH_RequestContext *rc,
{
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN,
+ TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
args[0]);
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
diff --git a/src/exchange/taler-exchange-httpd_reserves_history.c b/src/exchange/taler-exchange-httpd_reserves_history.c
index ffdc6eaa4..1bf73cb25 100644
--- a/src/exchange/taler-exchange-httpd_reserves_history.c
+++ b/src/exchange/taler-exchange-httpd_reserves_history.c
@@ -15,7 +15,7 @@
*/
/**
* @file taler-exchange-httpd_reserves_history.c
- * @brief Handle /reserves/$RESERVE_PUB/history requests
+ * @brief Handle /reserves/$RESERVE_PUB HISTORY requests
* @author Florian Dold
* @author Benedikt Mueller
* @author Christian Grothoff
@@ -30,7 +30,6 @@
#include "taler-exchange-httpd_reserves_history.h"
#include "taler-exchange-httpd_responses.h"
-
/**
* How far do we allow a client's time to be off when
* checking the request timestamp?
@@ -50,26 +49,11 @@ struct ReserveHistoryContext
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;
-
- /**
* History of the reserve, set in the callback.
*/
struct TALER_EXCHANGEDB_ReserveHistory *rh;
/**
- * Global fees applying to the request.
- */
- const struct TEH_GlobalFee *gf;
-
- /**
* Current reserve balance.
*/
struct TALER_Amount balance;
@@ -77,6 +61,305 @@ struct ReserveHistoryContext
/**
+ * 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
+ */
+static json_t *
+compile_reserve_history (
+ const struct TALER_EXCHANGEDB_ReserveHistory *rh)
+{
+ json_t *json_history;
+
+ json_history = json_array ();
+ GNUNET_assert (NULL != json_history);
+ for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
+ NULL != pos;
+ pos = pos->next)
+ {
+ switch (pos->type)
+ {
+ case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
+ {
+ const struct TALER_EXCHANGEDB_BankTransfer *bank =
+ pos->details.bank;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "CREDIT"),
+ // FIXME: offset missing! (here and in all other cases!)
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ bank->execution_date),
+ GNUNET_JSON_pack_string ("sender_account_url",
+ bank->sender_account_details),
+ GNUNET_JSON_pack_uint64 ("wire_reference",
+ bank->wire_reference),
+ TALER_JSON_pack_amount ("amount",
+ &bank->amount))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ break;
+ }
+ case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
+ {
+ const struct TALER_EXCHANGEDB_CollectableBlindcoin *withdraw
+ = pos->details.withdraw;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "WITHDRAW"),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &withdraw->reserve_sig),
+ GNUNET_JSON_pack_data_auto ("h_coin_envelope",
+ &withdraw->h_coin_envelope),
+ GNUNET_JSON_pack_data_auto ("h_denom_pub",
+ &withdraw->denom_pub_hash),
+ TALER_JSON_pack_amount ("withdraw_fee",
+ &withdraw->withdraw_fee),
+ TALER_JSON_pack_amount ("amount",
+ &withdraw->amount_with_fee))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+ case TALER_EXCHANGEDB_RO_RECOUP_COIN:
+ {
+ const struct TALER_EXCHANGEDB_Recoup *recoup
+ = pos->details.recoup;
+ struct TALER_ExchangePublicKeyP pub;
+ struct TALER_ExchangeSignatureP sig;
+
+ if (TALER_EC_NONE !=
+ TALER_exchange_online_confirm_recoup_sign (
+ &TEH_keys_exchange_sign_,
+ recoup->timestamp,
+ &recoup->value,
+ &recoup->coin.coin_pub,
+ &recoup->reserve_pub,
+ &pub,
+ &sig))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "RECOUP"),
+ GNUNET_JSON_pack_data_auto ("exchange_pub",
+ &pub),
+ GNUNET_JSON_pack_data_auto ("exchange_sig",
+ &sig),
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ recoup->timestamp),
+ TALER_JSON_pack_amount ("amount",
+ &recoup->value),
+ GNUNET_JSON_pack_data_auto ("coin_pub",
+ &recoup->coin.coin_pub))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+ case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
+ {
+ const struct TALER_EXCHANGEDB_ClosingTransfer *closing =
+ pos->details.closing;
+ struct TALER_ExchangePublicKeyP pub;
+ struct TALER_ExchangeSignatureP sig;
+
+ if (TALER_EC_NONE !=
+ TALER_exchange_online_reserve_closed_sign (
+ &TEH_keys_exchange_sign_,
+ closing->execution_date,
+ &closing->amount,
+ &closing->closing_fee,
+ closing->receiver_account_details,
+ &closing->wtid,
+ &pos->details.closing->reserve_pub,
+ &pub,
+ &sig))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "CLOSING"),
+ GNUNET_JSON_pack_string ("receiver_account_details",
+ closing->receiver_account_details),
+ GNUNET_JSON_pack_data_auto ("wtid",
+ &closing->wtid),
+ GNUNET_JSON_pack_data_auto ("exchange_pub",
+ &pub),
+ GNUNET_JSON_pack_data_auto ("exchange_sig",
+ &sig),
+ GNUNET_JSON_pack_timestamp ("timestamp",
+ closing->execution_date),
+ TALER_JSON_pack_amount ("amount",
+ &closing->amount),
+ TALER_JSON_pack_amount ("closing_fee",
+ &closing->closing_fee))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+ case TALER_EXCHANGEDB_RO_PURSE_MERGE:
+ {
+ const struct TALER_EXCHANGEDB_PurseMerge *merge =
+ pos->details.merge;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "MERGE"),
+ GNUNET_JSON_pack_data_auto ("h_contract_terms",
+ &merge->h_contract_terms),
+ GNUNET_JSON_pack_data_auto ("merge_pub",
+ &merge->merge_pub),
+ GNUNET_JSON_pack_uint64 ("min_age",
+ merge->min_age),
+ GNUNET_JSON_pack_uint64 ("flags",
+ merge->flags),
+ GNUNET_JSON_pack_data_auto ("purse_pub",
+ &merge->purse_pub),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &merge->reserve_sig),
+ GNUNET_JSON_pack_timestamp ("merge_timestamp",
+ merge->merge_timestamp),
+ GNUNET_JSON_pack_timestamp ("purse_expiration",
+ merge->purse_expiration),
+ TALER_JSON_pack_amount ("purse_fee",
+ &merge->purse_fee),
+ TALER_JSON_pack_amount ("amount",
+ &merge->amount_with_fee),
+ GNUNET_JSON_pack_bool ("merged",
+ merge->merged))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+ case TALER_EXCHANGEDB_RO_HISTORY_REQUEST:
+ {
+ const struct TALER_EXCHANGEDB_HistoryRequest *history =
+ pos->details.history;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "HISTORY"),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &history->reserve_sig),
+ GNUNET_JSON_pack_timestamp ("request_timestamp",
+ history->request_timestamp),
+ TALER_JSON_pack_amount ("amount",
+ &history->history_fee))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+
+ case TALER_EXCHANGEDB_RO_OPEN_REQUEST:
+ {
+ const struct TALER_EXCHANGEDB_OpenRequest *orq =
+ pos->details.open_request;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "OPEN"),
+ GNUNET_JSON_pack_uint64 ("requested_min_purses",
+ orq->purse_limit),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &orq->reserve_sig),
+ GNUNET_JSON_pack_timestamp ("request_timestamp",
+ orq->request_timestamp),
+ GNUNET_JSON_pack_timestamp ("requested_expiration",
+ orq->reserve_expiration),
+ TALER_JSON_pack_amount ("open_fee",
+ &orq->open_fee))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+
+ case TALER_EXCHANGEDB_RO_CLOSE_REQUEST:
+ {
+ const struct TALER_EXCHANGEDB_CloseRequest *crq =
+ pos->details.close_request;
+
+ if (0 !=
+ json_array_append_new (
+ json_history,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("type",
+ "CLOSE"),
+ GNUNET_JSON_pack_data_auto ("reserve_sig",
+ &crq->reserve_sig),
+ GNUNET_is_zero (&crq->target_account_h_payto)
+ ? GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_string ("h_payto",
+ NULL))
+ : GNUNET_JSON_pack_data_auto ("h_payto",
+ &crq->target_account_h_payto),
+ GNUNET_JSON_pack_timestamp ("request_timestamp",
+ crq->request_timestamp))))
+ {
+ GNUNET_break (0);
+ json_decref (json_history);
+ return NULL;
+ }
+ }
+ break;
+ }
+ }
+
+ return json_history;
+}
+
+
+/**
* Send reserve history to client.
*
* @param connection connection to the client
@@ -90,7 +373,7 @@ reply_reserve_history_success (struct MHD_Connection *connection,
const struct TALER_EXCHANGEDB_ReserveHistory *rh = rhc->rh;
json_t *json_history;
- json_history = TEH_RESPONSE_compile_reserve_history (rh);
+ json_history = compile_reserve_history (rh);
if (NULL == json_history)
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
@@ -107,19 +390,20 @@ reply_reserve_history_success (struct MHD_Connection *connection,
/**
- * Function implementing /reserves/$RID/history transaction. Given the public
- * key of a reserve, return the associated transaction history. 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.
+ * Function implementing /reserves/ HISTORY transaction.
+ * Execute a /reserves/ HISTORY. Given the public key of a reserve,
+ * return the associated transaction history. 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 ReserveHistoryContext *`
* @param connection MHD request which triggered the transaction
- * @param[out] mhd_ret set to MHD response status for @a connection,
+ * @param[out] mhd_ret set to MHD response history for @a connection,
* if transaction failed (!); unused
- * @return transaction status
+ * @return transaction history
*/
static enum GNUNET_DB_QueryStatus
reserve_history_transaction (void *cls,
@@ -129,47 +413,9 @@ reserve_history_transaction (void *cls,
struct ReserveHistoryContext *rsc = cls;
enum GNUNET_DB_QueryStatus qs;
- if (! TALER_amount_is_zero (&rsc->gf->fees.history))
- {
- bool balance_ok = false;
- bool idempotent = true;
-
- qs = TEH_plugin->insert_history_request (TEH_plugin->cls,
- rsc->reserve_pub,
- &rsc->reserve_sig,
- rsc->timestamp,
- &rsc->gf->fees.history,
- &balance_ok,
- &idempotent);
- 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,
- "get_reserve_history");
- }
- if (qs <= 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- return qs;
- }
- if (! balance_ok)
- {
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_CONFLICT,
- TALER_EC_EXCHANGE_GET_RESERVE_HISTORY_ERROR_INSUFFICIENT_BALANCE,
- NULL);
- }
- if (idempotent)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Idempotent /reserves/history request observed. Is caching working?\n");
- }
- }
qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
rsc->reserve_pub,
+ 0,
&rsc->balance,
&rsc->rh);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -192,14 +438,13 @@ TEH_handler_reserves_history (struct TEH_RequestContext *rc,
{
struct ReserveHistoryContext rsc;
MHD_RESULT mhd_ret;
+ uint64_t start_off = 0;
+ struct TALER_ReserveSignatureP reserve_sig;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_timestamp ("request_timestamp",
- &rsc.timestamp),
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &rsc.reserve_sig),
+ &reserve_sig),
GNUNET_JSON_spec_end ()
};
- struct GNUNET_TIME_Timestamp now;
rsc.reserve_pub = reserve_pub;
{
@@ -219,51 +464,15 @@ TEH_handler_reserves_history (struct TEH_RequestContext *rc,
return MHD_YES; /* failure */
}
}
- now = GNUNET_TIME_timestamp_get ();
- if (! GNUNET_TIME_absolute_approx_eq (now.abs_time,
- rsc.timestamp.abs_time,
- TIMESTAMP_TOLERANCE))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_EXCHANGE_GENERIC_CLOCK_SKEW,
- NULL);
- }
- {
- struct TEH_KeyStateHandle *keys;
-
- keys = TEH_keys_get_state ();
- if (NULL == keys)
- {
- GNUNET_break (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
- NULL);
- }
- rsc.gf = TEH_keys_global_fee_by_time (keys,
- rsc.timestamp);
- }
- if (NULL == rsc.gf)
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
- NULL);
- }
if (GNUNET_OK !=
- TALER_wallet_reserve_history_verify (rsc.timestamp,
- &rsc.gf->fees.history,
+ TALER_wallet_reserve_history_verify (start_off,
reserve_pub,
- &rsc.reserve_sig))
+ &reserve_sig))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_RESERVES_HISTORY_BAD_SIGNATURE,
+ TALER_EC_EXCHANGE_RESERVE_HISTORY_BAD_SIGNATURE,
NULL);
}
rsc.rh = NULL;
@@ -281,7 +490,7 @@ TEH_handler_reserves_history (struct TEH_RequestContext *rc,
{
return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN,
+ TALER_EC_EXCHANGE_GENERIC_RESERVE_UNKNOWN,
NULL);
}
mhd_ret = reply_reserve_history_success (rc->connection,
diff --git a/src/exchange/taler-exchange-httpd_reserves_history.h b/src/exchange/taler-exchange-httpd_reserves_history.h
index e02cb4d9b..9a2a93782 100644
--- a/src/exchange/taler-exchange-httpd_reserves_history.h
+++ b/src/exchange/taler-exchange-httpd_reserves_history.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2022 Taler Systems SA
+ Copyright (C) 2014-2020 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
@@ -15,8 +15,9 @@
*/
/**
* @file taler-exchange-httpd_reserves_history.h
- * @brief Handle /reserves/$RESERVE_PUB/history requests
+ * @brief Handle /reserves/$RESERVE_PUB HISTORY requests
* @author Florian Dold
+ * @author Benedikt Mueller
* @author Christian Grothoff
*/
#ifndef TALER_EXCHANGE_HTTPD_RESERVES_HISTORY_H
diff --git a/src/exchange/taler-exchange-httpd_reserves_status.c b/src/exchange/taler-exchange-httpd_reserves_status.c
deleted file mode 100644
index 4e7b4f47c..000000000
--- a/src/exchange/taler-exchange-httpd_reserves_status.c
+++ /dev/null
@@ -1,243 +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 MERCHANTABILITY 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-exchange-httpd_reserves_status.c
- * @brief Handle /reserves/$RESERVE_PUB STATUS requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <jansson.h>
-#include "taler_mhd_lib.h"
-#include "taler_json_lib.h"
-#include "taler_dbevents.h"
-#include "taler-exchange-httpd_keys.h"
-#include "taler-exchange-httpd_reserves_status.h"
-#include "taler-exchange-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_status_transaction.
- */
-struct ReserveStatusContext
-{
- /**
- * Public key of the reserve the inquiry is about.
- */
- const struct TALER_ReservePublicKeyP *reserve_pub;
-
- /**
- * History of the reserve, set in the callback.
- */
- struct TALER_EXCHANGEDB_ReserveHistory *rh;
-
- /**
- * Sum of incoming transactions within the returned history.
- * (currently not used).
- */
- struct TALER_Amount balance_in;
-
- /**
- * Sum of outgoing transactions within the returned history.
- * (currently not used).
- */
- struct TALER_Amount balance_out;
-
- /**
- * Current reserve balance.
- */
- struct TALER_Amount balance;
-};
-
-
-/**
- * Send reserve status to client.
- *
- * @param connection connection to the client
- * @param rhc reserve history to return
- * @return MHD result code
- */
-static MHD_RESULT
-reply_reserve_status_success (struct MHD_Connection *connection,
- const struct ReserveStatusContext *rhc)
-{
- const struct TALER_EXCHANGEDB_ReserveHistory *rh = rhc->rh;
- json_t *json_history;
-
- json_history = TEH_RESPONSE_compile_reserve_history (rh);
- if (NULL == json_history)
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
- NULL);
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_OK,
- TALER_JSON_pack_amount ("balance",
- &rhc->balance),
- GNUNET_JSON_pack_array_steal ("history",
- json_history));
-}
-
-
-/**
- * Function implementing /reserves/ STATUS transaction.
- * Execute a /reserves/ STATUS. Given the public key of a reserve,
- * return the associated transaction history. 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 ReserveStatusContext *`
- * @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_status_transaction (void *cls,
- struct MHD_Connection *connection,
- MHD_RESULT *mhd_ret)
-{
- struct ReserveStatusContext *rsc = cls;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TEH_plugin->get_reserve_status (TEH_plugin->cls,
- rsc->reserve_pub,
- &rsc->balance_in,
- &rsc->balance_out,
- &rsc->rh);
- 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,
- "get_reserve_status");
- }
- qs = TEH_plugin->get_reserve_balance (TEH_plugin->cls,
- rsc->reserve_pub,
- &rsc->balance);
- 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,
- "get_reserve_balance");
- }
- return qs;
-}
-
-
-MHD_RESULT
-TEH_handler_reserves_status (struct TEH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root)
-{
- struct ReserveStatusContext rsc;
- MHD_RESULT mhd_ret;
- struct GNUNET_TIME_Timestamp timestamp;
- struct TALER_ReserveSignatureP reserve_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_timestamp ("request_timestamp",
- &timestamp),
- GNUNET_JSON_spec_fixed_auto ("reserve_sig",
- &reserve_sig),
- GNUNET_JSON_spec_end ()
- };
- struct GNUNET_TIME_Timestamp now;
-
- rsc.reserve_pub = reserve_pub;
- {
- 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 */
- }
- }
- now = GNUNET_TIME_timestamp_get ();
- if (! GNUNET_TIME_absolute_approx_eq (now.abs_time,
- timestamp.abs_time,
- TIMESTAMP_TOLERANCE))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_EXCHANGE_GENERIC_CLOCK_SKEW,
- NULL);
- }
- if (GNUNET_OK !=
- TALER_wallet_reserve_status_verify (timestamp,
- reserve_pub,
- &reserve_sig))
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_FORBIDDEN,
- TALER_EC_EXCHANGE_RESERVES_STATUS_BAD_SIGNATURE,
- NULL);
- }
- rsc.rh = NULL;
- if (GNUNET_OK !=
- TEH_DB_run_transaction (rc->connection,
- "get reserve status",
- TEH_MT_REQUEST_OTHER,
- &mhd_ret,
- &reserve_status_transaction,
- &rsc))
- {
- return mhd_ret;
- }
- if (NULL == rsc.rh)
- {
- return TALER_MHD_reply_with_error (rc->connection,
- MHD_HTTP_NOT_FOUND,
- TALER_EC_EXCHANGE_RESERVES_STATUS_UNKNOWN,
- NULL);
- }
- mhd_ret = reply_reserve_status_success (rc->connection,
- &rsc);
- TEH_plugin->free_reserve_history (TEH_plugin->cls,
- rsc.rh);
- return mhd_ret;
-}
-
-
-/* end of taler-exchange-httpd_reserves_status.c */
diff --git a/src/exchange/taler-exchange-httpd_reserves_status.h b/src/exchange/taler-exchange-httpd_reserves_status.h
deleted file mode 100644
index 831b270f7..000000000
--- a/src/exchange/taler-exchange-httpd_reserves_status.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2014-2020 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 MERCHANTABILITY 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-exchange-httpd_reserves_status.h
- * @brief Handle /reserves/$RESERVE_PUB STATUS requests
- * @author Florian Dold
- * @author Benedikt Mueller
- * @author Christian Grothoff
- */
-#ifndef TALER_EXCHANGE_HTTPD_RESERVES_STATUS_H
-#define TALER_EXCHANGE_HTTPD_RESERVES_STATUS_H
-
-#include <microhttpd.h>
-#include "taler-exchange-httpd.h"
-
-
-/**
- * Handle a POST "/reserves/$RID/status" 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
-TEH_handler_reserves_status (struct TEH_RequestContext *rc,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const json_t *root);
-
-#endif
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 13c654e60..4c8b385bf 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -32,491 +32,6 @@
#include "taler-exchange-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 *
-TEH_RESPONSE_compile_transaction_history (
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_EXCHANGEDB_TransactionList *tl)
-{
- json_t *history;
-
- history = json_array ();
- if (NULL == history)
- {
- GNUNET_break (0); /* out of memory!? */
- return NULL;
- }
- for (const struct TALER_EXCHANGEDB_TransactionList *pos = tl;
- NULL != pos;
- pos = pos->next)
- {
- switch (pos->type)
- {
- case TALER_EXCHANGEDB_TT_DEPOSIT:
- {
- const struct TALER_EXCHANGEDB_DepositListEntry *deposit =
- pos->details.deposit;
- struct TALER_MerchantWireHashP h_wire;
-
- TALER_merchant_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... */
- TEH_METRICS_num_verifications[TEH_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->merchant_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 ("merchant_pub",
- &deposit->merchant_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 TALER_EXCHANGEDB_TT_MELT:
- {
- const struct TALER_EXCHANGEDB_MeltListEntry *melt =
- pos->details.melt;
- const struct TALER_AgeCommitmentHash *phac = NULL;
-
-#if ENABLE_SANITY_CHECKS
- TEH_METRICS_num_verifications[TEH_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 TALER_EXCHANGEDB_TT_REFUND:
- {
- const struct TALER_EXCHANGEDB_RefundListEntry *refund =
- pos->details.refund;
- struct TALER_Amount value;
-
-#if ENABLE_SANITY_CHECKS
- TEH_METRICS_num_verifications[TEH_MT_SIGNATURE_EDDSA]++;
- if (GNUNET_OK !=
- TALER_merchant_refund_verify (
- coin_pub,
- &refund->h_contract_terms,
- refund->rtransaction_id,
- &refund->refund_amount,
- &refund->merchant_pub,
- &refund->merchant_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 ("merchant_pub",
- &refund->merchant_pub),
- GNUNET_JSON_pack_uint64 ("rtransaction_id",
- refund->rtransaction_id),
- GNUNET_JSON_pack_data_auto ("merchant_sig",
- &refund->merchant_sig))))
- {
- GNUNET_break (0);
- json_decref (history);
- return NULL;
- }
- }
- break;
- case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
- {
- struct TALER_EXCHANGEDB_RecoupRefreshListEntry *pr =
- pos->details.old_coin_recoup;
- struct TALER_ExchangePublicKeyP epub;
- struct TALER_ExchangeSignatureP esig;
-
- if (TALER_EC_NONE !=
- TALER_exchange_online_confirm_recoup_refresh_sign (
- &TEH_keys_exchange_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 ("exchange_sig",
- &esig),
- GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_RECOUP:
- {
- const struct TALER_EXCHANGEDB_RecoupListEntry *recoup =
- pos->details.recoup;
- struct TALER_ExchangePublicKeyP epub;
- struct TALER_ExchangeSignatureP esig;
-
- if (TALER_EC_NONE !=
- TALER_exchange_online_confirm_recoup_sign (
- &TEH_keys_exchange_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 ("exchange_sig",
- &esig),
- GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
- {
- struct TALER_EXCHANGEDB_RecoupRefreshListEntry *pr =
- pos->details.recoup_refresh;
- struct TALER_ExchangePublicKeyP epub;
- struct TALER_ExchangeSignatureP esig;
-
- if (TALER_EC_NONE !=
- TALER_exchange_online_confirm_recoup_refresh_sign (
- &TEH_keys_exchange_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 ("exchange_sig",
- &esig),
- GNUNET_JSON_pack_data_auto ("exchange_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 TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
- {
- struct TALER_EXCHANGEDB_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 ("exchange_base_url",
- NULL == pd->exchange_base_url
- ? TEH_base_url
- : pd->exchange_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 TALER_EXCHANGEDB_TT_PURSE_REFUND:
- {
- const struct TALER_EXCHANGEDB_PurseRefundListEntry *prefund =
- pos->details.purse_refund;
- struct TALER_Amount value;
- enum TALER_ErrorCode ec;
- struct TALER_ExchangePublicKeyP epub;
- struct TALER_ExchangeSignatureP esig;
-
- if (0 >
- TALER_amount_subtract (&value,
- &prefund->refund_amount,
- &prefund->refund_fee))
- {
- GNUNET_break (0);
- json_decref (history);
- return NULL;
- }
- ec = TALER_exchange_online_purse_refund_sign (
- &TEH_keys_exchange_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 ("exchange_sig",
- &esig),
- GNUNET_JSON_pack_data_auto ("exchange_pub",
- &epub),
- GNUNET_JSON_pack_data_auto ("purse_pub",
- &prefund->purse_pub))))
- {
- GNUNET_break (0);
- json_decref (history);
- return NULL;
- }
- }
- break;
-
- case TALER_EXCHANGEDB_TT_RESERVE_OPEN:
- {
- struct TALER_EXCHANGEDB_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
TEH_RESPONSE_reply_unknown_denom_pub_hash (
struct MHD_Connection *connection,
@@ -650,48 +165,6 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
const struct TALER_DenominationHashP *h_denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub)
{
- struct TALER_EXCHANGEDB_TransactionList *tl;
- enum GNUNET_DB_QueryStatus qs;
- json_t *history;
- uint64_t etag = 0;
-
- TEH_plugin->rollback (TEH_plugin->cls);
- if (GNUNET_OK !=
- TEH_plugin->start_read_only (TEH_plugin->cls,
- "get_coin_transactions"))
- {
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_START_FAILED,
- NULL);
- }
- qs = TEH_plugin->get_coin_transactions (TEH_plugin->cls,
- coin_pub,
- &etag,
- &tl);
- TEH_plugin->rollback (TEH_plugin->cls);
- if (0 > qs)
- {
- return TALER_MHD_reply_with_error (
- connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- NULL);
- }
-
- history = TEH_RESPONSE_compile_transaction_history (coin_pub,
- tl);
- TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
- tl);
- if (NULL == history)
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
- "Failed to generated proof of insufficient funds");
- }
return TALER_MHD_REPLY_JSON_PACK (
connection,
TALER_ErrorCode_get_http_status_safe (ec),
@@ -700,347 +173,7 @@ TEH_RESPONSE_reply_coin_insufficient_funds (
coin_pub),
// FIXME: to be kept only for some of the error types!
GNUNET_JSON_pack_data_auto ("h_denom_pub",
- h_denom_pub),
- // FIXME: to be removed!
- GNUNET_JSON_pack_array_steal ("history",
- history));
-}
-
-
-json_t *
-TEH_RESPONSE_compile_reserve_history (
- const struct TALER_EXCHANGEDB_ReserveHistory *rh)
-{
- json_t *json_history;
-
- json_history = json_array ();
- GNUNET_assert (NULL != json_history);
- for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
- NULL != pos;
- pos = pos->next)
- {
- switch (pos->type)
- {
- case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
- {
- const struct TALER_EXCHANGEDB_BankTransfer *bank =
- pos->details.bank;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "CREDIT"),
- GNUNET_JSON_pack_timestamp ("timestamp",
- bank->execution_date),
- GNUNET_JSON_pack_string ("sender_account_url",
- bank->sender_account_details),
- GNUNET_JSON_pack_uint64 ("wire_reference",
- bank->wire_reference),
- TALER_JSON_pack_amount ("amount",
- &bank->amount))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- break;
- }
- case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
- {
- const struct TALER_EXCHANGEDB_CollectableBlindcoin *withdraw
- = pos->details.withdraw;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "WITHDRAW"),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &withdraw->reserve_sig),
- GNUNET_JSON_pack_data_auto ("h_coin_envelope",
- &withdraw->h_coin_envelope),
- GNUNET_JSON_pack_data_auto ("h_denom_pub",
- &withdraw->denom_pub_hash),
- TALER_JSON_pack_amount ("withdraw_fee",
- &withdraw->withdraw_fee),
- TALER_JSON_pack_amount ("amount",
- &withdraw->amount_with_fee))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
- case TALER_EXCHANGEDB_RO_RECOUP_COIN:
- {
- const struct TALER_EXCHANGEDB_Recoup *recoup
- = pos->details.recoup;
- struct TALER_ExchangePublicKeyP pub;
- struct TALER_ExchangeSignatureP sig;
-
- if (TALER_EC_NONE !=
- TALER_exchange_online_confirm_recoup_sign (
- &TEH_keys_exchange_sign_,
- recoup->timestamp,
- &recoup->value,
- &recoup->coin.coin_pub,
- &recoup->reserve_pub,
- &pub,
- &sig))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "RECOUP"),
- GNUNET_JSON_pack_data_auto ("exchange_pub",
- &pub),
- GNUNET_JSON_pack_data_auto ("exchange_sig",
- &sig),
- GNUNET_JSON_pack_timestamp ("timestamp",
- recoup->timestamp),
- TALER_JSON_pack_amount ("amount",
- &recoup->value),
- GNUNET_JSON_pack_data_auto ("coin_pub",
- &recoup->coin.coin_pub))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
- case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
- {
- const struct TALER_EXCHANGEDB_ClosingTransfer *closing =
- pos->details.closing;
- struct TALER_ExchangePublicKeyP pub;
- struct TALER_ExchangeSignatureP sig;
-
- if (TALER_EC_NONE !=
- TALER_exchange_online_reserve_closed_sign (
- &TEH_keys_exchange_sign_,
- closing->execution_date,
- &closing->amount,
- &closing->closing_fee,
- closing->receiver_account_details,
- &closing->wtid,
- &pos->details.closing->reserve_pub,
- &pub,
- &sig))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "CLOSING"),
- GNUNET_JSON_pack_string ("receiver_account_details",
- closing->receiver_account_details),
- GNUNET_JSON_pack_data_auto ("wtid",
- &closing->wtid),
- GNUNET_JSON_pack_data_auto ("exchange_pub",
- &pub),
- GNUNET_JSON_pack_data_auto ("exchange_sig",
- &sig),
- GNUNET_JSON_pack_timestamp ("timestamp",
- closing->execution_date),
- TALER_JSON_pack_amount ("amount",
- &closing->amount),
- TALER_JSON_pack_amount ("closing_fee",
- &closing->closing_fee))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
- case TALER_EXCHANGEDB_RO_PURSE_MERGE:
- {
- const struct TALER_EXCHANGEDB_PurseMerge *merge =
- pos->details.merge;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "MERGE"),
- GNUNET_JSON_pack_data_auto ("h_contract_terms",
- &merge->h_contract_terms),
- GNUNET_JSON_pack_data_auto ("merge_pub",
- &merge->merge_pub),
- GNUNET_JSON_pack_uint64 ("min_age",
- merge->min_age),
- GNUNET_JSON_pack_uint64 ("flags",
- merge->flags),
- GNUNET_JSON_pack_data_auto ("purse_pub",
- &merge->purse_pub),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &merge->reserve_sig),
- GNUNET_JSON_pack_timestamp ("merge_timestamp",
- merge->merge_timestamp),
- GNUNET_JSON_pack_timestamp ("purse_expiration",
- merge->purse_expiration),
- TALER_JSON_pack_amount ("purse_fee",
- &merge->purse_fee),
- TALER_JSON_pack_amount ("amount",
- &merge->amount_with_fee),
- GNUNET_JSON_pack_bool ("merged",
- merge->merged))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
- case TALER_EXCHANGEDB_RO_HISTORY_REQUEST:
- {
- const struct TALER_EXCHANGEDB_HistoryRequest *history =
- pos->details.history;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "HISTORY"),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &history->reserve_sig),
- GNUNET_JSON_pack_timestamp ("request_timestamp",
- history->request_timestamp),
- TALER_JSON_pack_amount ("amount",
- &history->history_fee))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
-
- case TALER_EXCHANGEDB_RO_OPEN_REQUEST:
- {
- const struct TALER_EXCHANGEDB_OpenRequest *orq =
- pos->details.open_request;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "OPEN"),
- GNUNET_JSON_pack_uint64 ("requested_min_purses",
- orq->purse_limit),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &orq->reserve_sig),
- GNUNET_JSON_pack_timestamp ("request_timestamp",
- orq->request_timestamp),
- GNUNET_JSON_pack_timestamp ("requested_expiration",
- orq->reserve_expiration),
- TALER_JSON_pack_amount ("open_fee",
- &orq->open_fee))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
-
- case TALER_EXCHANGEDB_RO_CLOSE_REQUEST:
- {
- const struct TALER_EXCHANGEDB_CloseRequest *crq =
- pos->details.close_request;
-
- if (0 !=
- json_array_append_new (
- json_history,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("type",
- "CLOSE"),
- GNUNET_JSON_pack_data_auto ("reserve_sig",
- &crq->reserve_sig),
- GNUNET_is_zero (&crq->target_account_h_payto)
- ? GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_string ("h_payto",
- NULL))
- : GNUNET_JSON_pack_data_auto ("h_payto",
- &crq->target_account_h_payto),
- GNUNET_JSON_pack_timestamp ("request_timestamp",
- crq->request_timestamp))))
- {
- GNUNET_break (0);
- json_decref (json_history);
- return NULL;
- }
- }
- break;
- }
- }
-
- return json_history;
-}
-
-
-/**
- * Send reserve history information to client with the
- * message that we have insufficient funds for the
- * requested withdraw operation.
- *
- * @param connection connection to the client
- * @param ec error code to return
- * @param ebalance expected balance based on our database
- * @param withdraw_amount amount that the client requested to withdraw
- * @param rh reserve history to return
- * @return MHD result code
- */
-static MHD_RESULT
-reply_reserve_insufficient_funds (
- struct MHD_Connection *connection,
- enum TALER_ErrorCode ec,
- const struct TALER_Amount *ebalance,
- const struct TALER_Amount *withdraw_amount,
- const struct TALER_EXCHANGEDB_ReserveHistory *rh)
-{
- json_t *json_history;
-
- json_history = TEH_RESPONSE_compile_reserve_history (rh);
- if (NULL == json_history)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Failed to compile reserve history\n");
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_EXCHANGE_RESERVE_HISTORY_ERROR_INSUFFICIENT_FUNDS,
- NULL);
- }
- return TALER_MHD_REPLY_JSON_PACK (
- connection,
- MHD_HTTP_CONFLICT,
- TALER_JSON_pack_ec (ec),
- TALER_JSON_pack_amount ("balance",
- ebalance),
- TALER_JSON_pack_amount ("requested_amount",
- withdraw_amount),
- GNUNET_JSON_pack_array_steal ("history",
- json_history));
+ h_denom_pub));
}
@@ -1051,46 +184,30 @@ TEH_RESPONSE_reply_reserve_insufficient_balance (
const struct TALER_Amount *balance_required,
const struct TALER_ReservePublicKeyP *reserve_pub)
{
- struct TALER_EXCHANGEDB_ReserveHistory *rh = NULL;
struct TALER_Amount balance;
enum GNUNET_DB_QueryStatus qs;
- MHD_RESULT mhd_ret;
- if (GNUNET_OK !=
- TEH_plugin->start_read_only (TEH_plugin->cls,
- "get_reserve_history on insufficient balance"))
- {
- GNUNET_break (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_START_FAILED,
- NULL);
- }
- /* The reserve does not have the required amount (actual
- * amount + withdraw fee) */
- qs = TEH_plugin->get_reserve_history (TEH_plugin->cls,
+ // FIXME: pass balance as argument to this function,
+ // instead of getting it in another transaction!
+ qs = TEH_plugin->get_reserve_balance (TEH_plugin->cls,
reserve_pub,
- &balance,
- &rh);
- TEH_plugin->rollback (TEH_plugin->cls);
- if ( (qs < 0) ||
- (NULL == rh) )
+ &balance);
+ if (qs < 0)
{
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_FETCH_FAILED,
- "reserve history");
+ "reserve balance");
}
- mhd_ret = reply_reserve_insufficient_funds (
+ return TALER_MHD_REPLY_JSON_PACK (
connection,
- ec,
- &balance,
- balance_required,
- rh);
- TEH_plugin->free_reserve_history (TEH_plugin->cls,
- rh);
- return mhd_ret;
+ MHD_HTTP_CONFLICT,
+ TALER_JSON_pack_ec (ec),
+ TALER_JSON_pack_amount ("balance",
+ &balance),
+ TALER_JSON_pack_amount ("requested_amount",
+ balance_required));
}
diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h
index 9b525929b..3e55f0b07 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -34,17 +34,6 @@
/**
- * 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 *
-TEH_RESPONSE_compile_reserve_history (
- const struct TALER_EXCHANGEDB_ReserveHistory *rh);
-
-
-/**
* Send assertion that the given denomination key hash
* is unknown to us at this time.
*
@@ -214,19 +203,6 @@ TEH_RESPONSE_reply_purse_created (
/**
- * 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 *
-TEH_RESPONSE_compile_transaction_history (
- const struct TALER_CoinSpendPublicKeyP *coin_pub,
- const struct TALER_EXCHANGEDB_TransactionList *tl);
-
-
-/**
* Callback used to set headers in a response.
*
* @param cls closure