summaryrefslogtreecommitdiff
path: root/src/exchange
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-07-05 20:43:28 +0200
committerChristian Grothoff <christian@grothoff.org>2020-07-05 20:43:28 +0200
commit6de49ea2c02e311e5f5366005bd3497a9bb25187 (patch)
treea221b9c784b4e004eb5972e18516653d1aea6a5c /src/exchange
parente428783e2e0295186dc4eae273df8a3f8b75df60 (diff)
parented5b98a2c2308fbd44b906a30286d2689fd304dd (diff)
downloadexchange-6de49ea2c02e311e5f5366005bd3497a9bb25187.tar.gz
exchange-6de49ea2c02e311e5f5366005bd3497a9bb25187.tar.bz2
exchange-6de49ea2c02e311e5f5366005bd3497a9bb25187.zip
Merge branch 'protocolv8'
Diffstat (limited to 'src/exchange')
-rw-r--r--src/exchange/taler-exchange-aggregator.c12
-rw-r--r--src/exchange/taler-exchange-httpd.c65
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c193
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.c9
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c99
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c4
-rw-r--r--src/exchange/taler-exchange-httpd_wire.c4
-rw-r--r--src/exchange/taler-exchange-httpd_withdraw.c4
8 files changed, 213 insertions, 177 deletions
diff --git a/src/exchange/taler-exchange-aggregator.c b/src/exchange/taler-exchange-aggregator.c
index 21a29e506..69c73746c 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -330,6 +330,8 @@ refund_by_coin_cb (void *cls,
*
* @param cls a `struct AggregationUnit`
* @param row_id identifies database entry
+ * @param exchange_timestamp when did the deposit happen
+ * @param wallet_timestamp when did the contract happen
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@@ -343,6 +345,8 @@ refund_by_coin_cb (void *cls,
static enum GNUNET_DB_QueryStatus
deposit_cb (void *cls,
uint64_t row_id,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@@ -358,6 +362,8 @@ deposit_cb (void *cls,
/* NOTE: potential optimization: use custom SQL API to not
fetch this one: */
(void) wire_deadline; /* already checked by SQL query */
+ (void) exchange_timestamp;
+ (void) wallet_timestamp;
au->merchant_pub = *merchant_pub;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Aggregator processing payment %s with amount %s\n",
@@ -501,6 +507,8 @@ deposit_cb (void *cls,
*
* @param cls a `struct AggregationUnit`
* @param row_id identifies database entry
+ * @param exchange_timestamp when did the exchange receive the deposit
+ * @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param coin_pub public key of the coin
* @param amount_with_fee amount that was deposited including fee
@@ -514,6 +522,8 @@ deposit_cb (void *cls,
static enum GNUNET_DB_QueryStatus
aggregate_cb (void *cls,
uint64_t row_id,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct TALER_Amount *amount_with_fee,
@@ -529,6 +539,8 @@ aggregate_cb (void *cls,
/* NOTE: potential optimization: use custom SQL API to not
fetch these: */
(void) wire_deadline; /* checked by SQL */
+ (void) exchange_timestamp;
+ (void) wallet_timestamp;
(void) wire; /* must match */
GNUNET_break (0 == GNUNET_memcmp (&au->merchant_pub,
merchant_pub));
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index 339303d53..c614b711e 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -421,6 +421,45 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
/**
+ * Handle a "/seed" request.
+ *
+ * @param rh context of the handler
+ * @param connection the MHD connection to handle
+ * @param args array of additional options (must be empty for this function)
+ * @return MHD result code
+ */
+static MHD_RESULT
+handler_seed (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const char *const args[])
+{
+#define SEED_SIZE 32
+ char *body;
+ MHD_RESULT ret;
+ struct MHD_Response *resp;
+
+ (void) rh;
+ body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() */
+ if (NULL == body)
+ return MHD_NO;
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ body,
+ SEED_SIZE);
+ resp = MHD_create_response_from_buffer (SEED_SIZE,
+ body,
+ MHD_RESPMEM_MUST_FREE);
+ TALER_MHD_add_global_headers (resp);
+ ret = MHD_queue_response (connection,
+ MHD_HTTP_OK,
+ resp);
+ GNUNET_break (MHD_YES == ret);
+ MHD_destroy_response (resp);
+ return ret;
+#undef SEED_SIZE
+}
+
+
+/**
* Handle incoming HTTP request.
*
* @param cls closure for MHD daemon (unused)
@@ -472,6 +511,11 @@ handle_mhd_request (void *cls,
.method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_handler_agpl_redirect
},
+ {
+ .url = "seed",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &handler_seed
+ },
/* Terms of service */
{
.url = "terms",
@@ -654,9 +698,10 @@ handle_mhd_request (void *cls,
{
struct TEH_RequestHandler *rh = &handlers[i];
- if (0 != strncmp (tok,
- rh->url,
- tok_size))
+ if ( (0 != strncmp (tok,
+ rh->url,
+ tok_size)) ||
+ (tok_size != strlen (rh->url) ) )
continue;
found = GNUNET_YES;
/* The URL is a match! What we now do depends on the method. */
@@ -782,8 +827,8 @@ exchange_serve_process_config (void)
&TEH_master_public_key.
eddsa_pub))
{
- fprintf (stderr,
- "Invalid master public key given in exchange configuration.");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Invalid master public key given in exchange configuration.");
GNUNET_free (master_public_key_str);
return GNUNET_SYSERR;
}
@@ -795,14 +840,18 @@ exchange_serve_process_config (void)
if (GNUNET_OK !=
TEH_WIRE_init (TEH_cfg))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to setup wire subsystem\n");
return GNUNET_SYSERR;
+ }
if (NULL ==
(TEH_plugin = TALER_EXCHANGEDB_plugin_load (TEH_cfg)))
{
- fprintf (stderr,
- "Failed to initialize DB subsystem\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to initialize DB subsystem\n");
TEH_WIRE_done ();
return GNUNET_SYSERR;
}
@@ -814,6 +863,8 @@ exchange_serve_process_config (void)
&serve_unixpath,
&unixpath_mode))
{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to setup HTTPd subsystem\n");
TEH_WIRE_done ();
return GNUNET_SYSERR;
}
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 3f895857b..fe8fdf061 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -47,7 +47,7 @@
* @param coin_pub public key of the coin
* @param h_wire hash of wire details
* @param h_contract_terms hash of contract details
- * @param timestamp client's timestamp
+ * @param exchange_timestamp exchange's timestamp
* @param refund_deadline until when this deposit be refunded
* @param merchant merchant public key
* @param amount_without_fee fraction of coin value to deposit, without the fee
@@ -58,7 +58,7 @@ reply_deposit_success (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const struct GNUNET_HashCode *h_wire,
const struct GNUNET_HashCode *h_contract_terms,
- struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
struct GNUNET_TIME_Absolute refund_deadline,
const struct TALER_MerchantPublicKeyP *merchant,
const struct TALER_Amount *amount_without_fee)
@@ -70,7 +70,7 @@ reply_deposit_success (struct MHD_Connection *connection,
.purpose.size = htonl (sizeof (dc)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
- .timestamp = GNUNET_TIME_absolute_hton (timestamp),
+ .exchange_timestamp = GNUNET_TIME_absolute_hton (exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.coin_pub = *coin_pub,
.merchant = *merchant
@@ -88,12 +88,16 @@ reply_deposit_success (struct MHD_Connection *connection,
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
"no keys");
}
- return TALER_MHD_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:s, s:o, s:o}",
- "status", "DEPOSIT_OK",
- "sig", GNUNET_JSON_from_data_auto (&sig),
- "pub", GNUNET_JSON_from_data_auto (&pub));
+ return TALER_MHD_reply_json_pack (
+ connection,
+ MHD_HTTP_OK,
+ "{s:o, s:o, s:o}",
+ "exchange_timestamp",
+ GNUNET_JSON_from_time_abs (exchange_timestamp),
+ "exchange_sig",
+ GNUNET_JSON_from_data_auto (&sig),
+ "exchange_pub",
+ GNUNET_JSON_from_data_auto (&pub));
}
@@ -108,6 +112,11 @@ struct DepositContext
const struct TALER_EXCHANGEDB_Deposit *deposit;
/**
+ * Our timestamp (when we received the request).
+ */
+ struct GNUNET_TIME_Absolute exchange_timestamp;
+
+ /**
* Value of the coin.
*/
struct TALER_Amount value;
@@ -116,12 +125,11 @@ struct DepositContext
/**
- * Execute database transaction for /deposit. 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.
+ * Check if /deposit is already in the database. 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. We do return a "hard" error also if we found the deposit in the
+ * database and generated a regular response.
*
* @param cls a `struct DepositContext`
* @param connection MHD request context
@@ -130,20 +138,22 @@ struct DepositContext
* @return transaction status
*/
static enum GNUNET_DB_QueryStatus
-deposit_transaction (void *cls,
- struct MHD_Connection *connection,
- struct TALER_EXCHANGEDB_Session *session,
- MHD_RESULT *mhd_ret)
+deposit_precheck (void *cls,
+ struct MHD_Connection *connection,
+ struct TALER_EXCHANGEDB_Session *session,
+ MHD_RESULT *mhd_ret)
{
struct DepositContext *dc = cls;
const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit;
- struct TALER_Amount spent;
+ struct TALER_Amount deposit_fee;
enum GNUNET_DB_QueryStatus qs;
qs = TEH_plugin->have_deposit (TEH_plugin->cls,
session,
deposit,
- GNUNET_YES /* check refund deadline */);
+ GNUNET_YES /* check refund deadline */,
+ &deposit_fee,
+ &dc->exchange_timestamp);
if (qs < 0)
{
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
@@ -165,12 +175,12 @@ deposit_transaction (void *cls,
GNUNET_assert (0 <=
TALER_amount_subtract (&amount_without_fee,
&deposit->amount_with_fee,
- &deposit->deposit_fee));
+ &deposit_fee));
*mhd_ret = reply_deposit_success (connection,
&deposit->coin.coin_pub,
&deposit->h_wire,
&deposit->h_contract_terms,
- deposit->timestamp,
+ dc->exchange_timestamp,
deposit->refund_deadline,
&deposit->merchant_pub,
&amount_without_fee);
@@ -178,6 +188,44 @@ deposit_transaction (void *cls,
never try again. */
return GNUNET_DB_STATUS_HARD_ERROR;
}
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+}
+
+
+/**
+ * Execute database transaction for /deposit. 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 DepositContext`
+ * @param connection MHD request context
+ * @param session database session and transaction to use
+ * @param[out] mhd_ret set to MHD status on error
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+deposit_transaction (void *cls,
+ struct MHD_Connection *connection,
+ struct TALER_EXCHANGEDB_Session *session,
+ MHD_RESULT *mhd_ret)
+{
+ struct DepositContext *dc = cls;
+ const struct TALER_EXCHANGEDB_Deposit *deposit = dc->deposit;
+ struct TALER_Amount spent;
+ enum GNUNET_DB_QueryStatus qs;
+
+ /* Theoretically, someone other threat may have received
+ and committed the deposit in the meantime. Check now
+ that we are in the transaction scope. */
+ qs = deposit_precheck (cls,
+ connection,
+ session,
+ mhd_ret);
+ if (qs < 0)
+ return qs;
/* Start with fee for THIS transaction */
spent = deposit->amount_with_fee;
@@ -237,6 +285,7 @@ deposit_transaction (void *cls,
}
qs = TEH_plugin->insert_deposit (TEH_plugin->cls,
session,
+ dc->exchange_timestamp,
deposit);
if (GNUNET_DB_STATUS_HARD_ERROR == qs)
{
@@ -251,45 +300,6 @@ deposit_transaction (void *cls,
/**
- * Check that @a ts is reasonably close to our own RTC.
- *
- * @param ts timestamp to check
- * @return #GNUNET_OK if @a ts is reasonable
- */
-static int
-check_timestamp_current (struct GNUNET_TIME_Absolute ts)
-{
- struct GNUNET_TIME_Relative r;
- struct GNUNET_TIME_Relative tolerance;
-
- /* Let's be VERY generous (after all, this is basically about
- which year the deposit counts for in terms of tax purposes) */
- tolerance = GNUNET_TIME_UNIT_MONTHS;
- r = GNUNET_TIME_absolute_get_duration (ts);
- if (r.rel_value_us > tolerance.rel_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Deposit timestamp too old: %llu vs %llu > %llu\n",
- (unsigned long long) ts.abs_value_us,
- (unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us,
- (unsigned long long) tolerance.rel_value_us);
- return GNUNET_SYSERR;
- }
- r = GNUNET_TIME_absolute_get_remaining (ts);
- if (r.rel_value_us > tolerance.rel_value_us)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Deposit timestamp too new: %llu vs %llu < - %llu\n",
- (unsigned long long) ts.abs_value_us,
- (unsigned long long) GNUNET_TIME_absolute_get ().abs_value_us,
- (unsigned long long) tolerance.rel_value_us);
- return GNUNET_SYSERR;
- }
- return GNUNET_OK;
-}
-
-
-/**
* Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
* successful, passes the JSON data to #deposit_transaction() to
* further check the details of the operation specified. If everything checks
@@ -312,15 +322,22 @@ TEH_handler_deposit (struct MHD_Connection *connection,
struct GNUNET_HashCode my_h_wire;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_json ("wire", &wire),
- TALER_JSON_spec_amount ("contribution", &deposit.amount_with_fee),
+ TALER_JSON_spec_amount ("contribution",
+ &deposit.amount_with_fee),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&deposit.coin.denom_pub_hash),
- TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("h_wire", &deposit.h_wire),
- GNUNET_JSON_spec_fixed_auto ("coin_sig", &deposit.csig),
- GNUNET_JSON_spec_absolute_time ("timestamp", &deposit.timestamp),
+ TALER_JSON_spec_denomination_signature ("ub_sig",
+ &deposit.coin.denom_sig),
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &deposit.merchant_pub),
+ GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
+ &deposit.h_contract_terms),
+ GNUNET_JSON_spec_fixed_auto ("h_wire",
+ &deposit.h_wire),
+ GNUNET_JSON_spec_fixed_auto ("coin_sig",
+ &deposit.csig),
+ GNUNET_JSON_spec_absolute_time ("timestamp",
+ &deposit.timestamp),
GNUNET_JSON_spec_absolute_time ("refund_deadline",
&deposit.refund_deadline),
GNUNET_JSON_spec_absolute_time ("wire_transfer_deadline",
@@ -359,17 +376,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
TALER_EC_DEPOSIT_REFUND_DEADLINE_AFTER_WIRE_DEADLINE,
"refund_deadline");
}
-
- if (GNUNET_OK !=
- check_timestamp_current (deposit.timestamp))
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_DEPOSIT_INVALID_TIMESTAMP,
- "timestamp");
- }
if (GNUNET_OK !=
TALER_JSON_merchant_wire_signature_hash (wire,
&my_h_wire))
@@ -393,6 +399,26 @@ TEH_handler_deposit (struct MHD_Connection *connection,
"h_wire");
}
+ /* Check for idempotency: did we get this request before? */
+ dc.deposit = &deposit;
+ {
+ MHD_RESULT mhd_ret;
+
+ if (GNUNET_OK !=
+ TEH_DB_run_transaction (connection,
+ "precheck deposit",
+ &mhd_ret,
+ &deposit_precheck,
+ &dc))
+ {
+ GNUNET_JSON_parse_free (spec);
+ return mhd_ret;
+ }
+ }
+
+ /* new deposit */
+ dc.exchange_timestamp = GNUNET_TIME_absolute_get ();
+ (void) GNUNET_TIME_round_abs (&dc.exchange_timestamp);
/* check denomination exists and is valid */
{
struct TEH_KS_StateHandle *key_state;
@@ -400,7 +426,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
enum TALER_ErrorCode ec;
unsigned int hc;
- key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
+ key_state = TEH_KS_acquire (dc.exchange_timestamp);
if (NULL == key_state)
{
TALER_LOG_ERROR ("Lacking keys to operate\n");
@@ -494,7 +520,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = deposit.h_contract_terms,
.h_wire = deposit.h_wire,
- .timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
+ .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit.timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (deposit.refund_deadline),
.merchant = deposit.merchant_pub,
.coin_pub = deposit.coin.coin_pub
@@ -520,7 +546,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
/* execute transaction */
- dc.deposit = &deposit;
{
MHD_RESULT mhd_ret;
@@ -549,7 +574,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
&deposit.coin.coin_pub,
&deposit.h_wire,
&deposit.h_contract_terms,
- deposit.timestamp,
+ dc.exchange_timestamp,
deposit.refund_deadline,
&deposit.merchant_pub,
&amount_without_fee);
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c
index 152d2dad5..fbb5da356 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014--2019 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
@@ -44,7 +44,7 @@
* #TALER_PROTOCOL_CURRENT and #TALER_PROTOCOL_AGE in
* exchange_api_handle.c!
*/
-#define EXCHANGE_PROTOCOL_VERSION "7:0:0"
+#define EXCHANGE_PROTOCOL_VERSION "8:0:0"
/**
@@ -801,7 +801,7 @@ reload_keys_denom_iter (void *cls,
handle_signal (SIGTERM);
return GNUNET_SYSERR;
}
-
+ GNUNET_assert (NULL != dki->denom_priv.rsa_private_key);
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Adding denomination key `%s' (%s) to active set\n",
alias,
@@ -1660,6 +1660,9 @@ reload_public_denoms_cb (
GNUNET_h2s (&issue->properties.denom_hash));
return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Loaded denomination key %s from DB, no private key (hopefully revoked!)\n",
+ GNUNET_h2s (&issue->properties.denom_hash));
/* we can assert here as we checked for duplicates just above */
GNUNET_assert (GNUNET_OK == ret);
}
diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c
index 7c2b149f2..a6a2c3d6f 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -73,12 +73,13 @@ reply_refund_success (struct MHD_Connection *connection,
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
"no online signing key");
}
- return TALER_MHD_reply_json_pack (connection,
- MHD_HTTP_OK,
- "{s:s, s:o, s:o}",
- "status", "REFUND_OK",
- "sig", GNUNET_JSON_from_data_auto (&sig),
- "pub", GNUNET_JSON_from_data_auto (&pub));
+ return TALER_MHD_reply_json_pack (
+ connection,
+ MHD_HTTP_OK,
+ "{s:o, s:o, s:o}",
+ "refund_fee", TALER_JSON_from_amount (&refund->refund_fee),
+ "exchange_sig", GNUNET_JSON_from_data_auto (&sig),
+ "exchange_pub", GNUNET_JSON_from_data_auto (&pub));
}
@@ -246,18 +247,15 @@ refund_transaction (void *cls,
}
/* check currency is compatible */
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund->details.refund_amount,
- &dep->amount_with_fee)) ||
- (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund->details.refund_fee,
- &dep->deposit_fee)) )
+ if (GNUNET_YES !=
+ TALER_amount_cmp_currency (&refund->details.refund_amount,
+ &dep->amount_with_fee))
{
GNUNET_break_op (0); /* currency mismatch */
TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
tl);
*mhd_ret = TALER_MHD_reply_with_error (connection,
- MHD_HTTP_PRECONDITION_FAILED,
+ MHD_HTTP_BAD_REQUEST,
TALER_EC_REFUND_CURRENCY_MISMATCH,
"currencies involved do not match");
return GNUNET_DB_STATUS_HARD_ERROR;
@@ -339,15 +337,14 @@ refund_transaction (void *cls,
* the fee structure, so this is not done here.
*
* @param connection the MHD connection to handle
- * @param refund information about the refund
+ * @param[in,out] refund information about the refund
* @return MHD result code
*/
static MHD_RESULT
verify_and_execute_refund (struct MHD_Connection *connection,
- const struct TALER_EXCHANGEDB_Refund *refund)
+ struct TALER_EXCHANGEDB_Refund *refund)
{
struct GNUNET_HashCode denom_hash;
- struct TALER_Amount expect_fee;
{
struct TALER_RefundRequestPS rr = {
@@ -361,8 +358,6 @@ verify_and_execute_refund (struct MHD_Connection *connection,
TALER_amount_hton (&rr.refund_amount,
&refund->details.refund_amount);
- TALER_amount_hton (&rr.refund_fee,
- &refund->details.refund_fee);
if (GNUNET_OK !=
GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
&rr,
@@ -429,43 +424,12 @@ verify_and_execute_refund (struct MHD_Connection *connection,
ec,
"denomination not found, but coin known");
}
- TALER_amount_ntoh (&expect_fee,
+ TALER_amount_ntoh (&refund->details.refund_fee,
&dki->issue.properties.fee_refund);
}
TEH_KS_release (key_state);
}
- /* Check refund fee matches fee of denomination key! */
- if (GNUNET_YES !=
- TALER_amount_cmp_currency (&expect_fee,
- &refund->details.refund_fee) )
- {
- GNUNET_break_op (0);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_REFUND_FEE_CURRENCY_MISMATCH,
- "refund_fee");
- }
- {
- int fee_cmp;
-
- fee_cmp = TALER_amount_cmp (&refund->details.refund_fee,
- &expect_fee);
- if (-1 == fee_cmp)
- {
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_REFUND_FEE_TOO_LOW,
- "refund_fee");
- }
- if (1 == fee_cmp)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Refund fee proposed by merchant is higher than necessary.\n");
- }
- }
-
-
/* Finally run the actual transaction logic */
{
MHD_RESULT mhd_ret;
@@ -502,16 +466,20 @@ TEH_handler_refund (struct MHD_Connection *connection,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
const json_t *root)
{
- struct TALER_EXCHANGEDB_Refund refund;
+ struct TALER_EXCHANGEDB_Refund refund = {
+ .details.refund_fee.currency = {0} /* set to invalid, just to be sure */
+ };
struct GNUNET_JSON_Specification spec[] = {
- TALER_JSON_spec_amount ("refund_amount", &refund.details.refund_amount),
- TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee),
+ TALER_JSON_spec_amount ("refund_amount",
+ &refund.details.refund_amount),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&refund.details.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.details.merchant_pub),
+ GNUNET_JSON_spec_fixed_auto ("merchant_pub",
+ &refund.details.merchant_pub),
GNUNET_JSON_spec_uint64 ("rtransaction_id",
&refund.details.rtransaction_id),
- GNUNET_JSON_spec_fixed_auto ("merchant_sig", &refund.details.merchant_sig),
+ GNUNET_JSON_spec_fixed_auto ("merchant_sig",
+ &refund.details.merchant_sig),
GNUNET_JSON_spec_end ()
};
@@ -527,27 +495,6 @@ TEH_handler_refund (struct MHD_Connection *connection,
if (GNUNET_NO == res)
return MHD_YES; /* failure */
}
- if (GNUNET_YES !=
- TALER_amount_cmp_currency (&refund.details.refund_amount,
- &refund.details.refund_fee) )
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_REFUND_FEE_CURRENCY_MISMATCH,
- "refund_amount or refund_fee");
- }
- if (-1 == TALER_amount_cmp (&refund.details.refund_amount,
- &refund.details.refund_fee) )
- {
- GNUNET_break_op (0);
- GNUNET_JSON_parse_free (spec);
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_BAD_REQUEST,
- TALER_EC_REFUND_FEE_ABOVE_AMOUNT,
- "refund_amount");
- }
{
MHD_RESULT res;
diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 06673afc1..f65951614 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -66,7 +66,7 @@ TEH_RESPONSE_compile_transaction_history (
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = deposit->h_contract_terms,
.h_wire = deposit->h_wire,
- .timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
+ .wallet_timestamp = GNUNET_TIME_absolute_hton (deposit->timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (
deposit->refund_deadline),
.merchant = deposit->merchant_pub,
@@ -185,8 +185,6 @@ TEH_RESPONSE_compile_transaction_history (
TALER_amount_hton (&rr.refund_amount,
&refund->refund_amount);
- TALER_amount_hton (&rr.refund_fee,
- &refund->refund_fee);
#if ENABLE_SANITY_CHECKS
/* internal sanity check before we hand out a bogus sig... */
if (GNUNET_OK !=
diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c
index 38bbad4ad..471fa4fad 100644
--- a/src/exchange/taler-exchange-httpd_wire.c
+++ b/src/exchange/taler-exchange-httpd_wire.c
@@ -341,6 +341,8 @@ TEH_WIRE_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
&ret);
if (GNUNET_OK != ret)
{
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Error setting up bank accounts\n");
TEH_WIRE_done ();
return GNUNET_SYSERR;
}
@@ -349,6 +351,8 @@ TEH_WIRE_init (const struct GNUNET_CONFIGURATION_Handle *cfg)
(0 == json_object_size (wire_fee_object)) )
{
TEH_WIRE_done ();
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "No bank accounts configured\n");
return GNUNET_SYSERR;
}
wire_methods = json_pack ("{s:O, s:O, s:o}",
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c b/src/exchange/taler-exchange-httpd_withdraw.c
index 4d662e712..c4c72d6a4 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -306,8 +306,6 @@ withdraw_transaction (void *cls,
#endif
wc->collectable.denom_pub_hash = wc->denom_pub_hash;
wc->collectable.amount_with_fee = wc->amount_required;
- TALER_amount_ntoh (&wc->collectable.withdraw_fee,
- &wc->dki->issue.properties.fee_withdraw);
wc->collectable.reserve_pub = wc->wsrd.reserve_pub;
wc->collectable.h_coin_envelope = wc->wsrd.h_coin_envelope;
wc->collectable.reserve_sig = wc->signature;
@@ -436,8 +434,6 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
}
TALER_amount_hton (&wc.wsrd.amount_with_fee,
&wc.amount_required);
- TALER_amount_hton (&wc.wsrd.withdraw_fee,
- &fee_withdraw);
}
/* verify signature! */