aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/auditor/taler-auditor-httpd_deposit-confirmation.c5
-rw-r--r--src/auditor/taler-helper-auditor-coins.c8
-rw-r--r--src/auditor/taler-helper-auditor-deposits.c9
-rw-r--r--src/auditordb/auditor-0001.sql2
-rw-r--r--src/auditordb/plugin_auditordb_postgres.c10
-rw-r--r--src/exchange/taler-exchange-aggregator.c12
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c173
-rw-r--r--src/exchange/taler-exchange-httpd_responses.c2
-rw-r--r--src/exchangedb/exchange-0001.sql3
-rw-r--r--src/exchangedb/plugin_exchangedb_postgres.c62
-rw-r--r--src/exchangedb/test_exchangedb.c71
-rw-r--r--src/include/taler_auditordb_plugin.h4
-rw-r--r--src/include/taler_error_codes.h45
-rw-r--r--src/include/taler_exchange_service.h2
-rw-r--r--src/include/taler_exchangedb_plugin.h18
-rw-r--r--src/include/taler_signatures.h7
-rw-r--r--src/include/taler_testing_lib.h18
-rw-r--r--src/lib/auditor_api_deposit_confirmation.c17
-rw-r--r--src/lib/exchange_api_common.c2
-rw-r--r--src/lib/exchange_api_deposit.c9
-rw-r--r--src/lib/exchange_api_refund.c7
-rw-r--r--src/testing/test_taler_exchange_aggregator.c24
-rw-r--r--src/testing/testing_api_cmd_auditor_deposit_confirmation.c8
-rw-r--r--src/testing/testing_api_cmd_deposit.c35
-rw-r--r--src/testing/testing_api_cmd_insert_deposit.c26
25 files changed, 390 insertions, 189 deletions
diff --git a/src/auditor/taler-auditor-httpd_deposit-confirmation.c b/src/auditor/taler-auditor-httpd_deposit-confirmation.c
index 5f84a7253..1039164c4 100644
--- a/src/auditor/taler-auditor-httpd_deposit-confirmation.c
+++ b/src/auditor/taler-auditor-httpd_deposit-confirmation.c
@@ -155,7 +155,7 @@ verify_and_execute_deposit_confirmation (
.purpose.size = htonl (sizeof (struct TALER_DepositConfirmationPS)),
.h_contract_terms = dc->h_contract_terms,
.h_wire = dc->h_wire,
- .timestamp = GNUNET_TIME_absolute_hton (dc->timestamp),
+ .exchange_timestamp = GNUNET_TIME_absolute_hton (dc->exchange_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (dc->refund_deadline),
.coin_pub = dc->coin_pub,
.merchant = dc->merchant
@@ -224,7 +224,8 @@ TAH_DEPOSIT_CONFIRMATION_handler (struct TAH_RequestHandler *rh,
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &dc.h_contract_terms),
GNUNET_JSON_spec_fixed_auto ("h_wire", &dc.h_wire),
- GNUNET_JSON_spec_absolute_time ("timestamp", &dc.timestamp),
+ GNUNET_JSON_spec_absolute_time ("exchange_timestamp",
+ &dc.exchange_timestamp),
GNUNET_JSON_spec_absolute_time ("refund_deadline", &dc.refund_deadline),
TALER_JSON_spec_amount ("amount_without_fee", &dc.amount_without_fee),
GNUNET_JSON_spec_fixed_auto ("coin_pub", &dc.coin_pub),
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
index 2e32c5698..158baa8b3 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -1535,7 +1535,8 @@ refresh_session_cb (void *cls,
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
- * @param timestamp when did the deposit happen
+ * @param exchange_timestamp when did the exchange get the deposit
+ * @param wallet_timestamp when did the contract signing happen
* @param merchant_pub public key of the merchant
* @param denom_pub denomination public key of @a coin_pub
* @param coin_pub public key of the coin
@@ -1553,7 +1554,8 @@ refresh_session_cb (void *cls,
static int
deposit_cb (void *cls,
uint64_t rowid,
- struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -1611,7 +1613,7 @@ deposit_cb (void *cls,
.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT),
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = *h_contract_terms,
- .timestamp = GNUNET_TIME_absolute_hton (timestamp),
+ .wallet_timestamp = GNUNET_TIME_absolute_hton (wallet_timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.deposit_fee = issue->fee_deposit,
.merchant = *merchant_pub,
diff --git a/src/auditor/taler-helper-auditor-deposits.c b/src/auditor/taler-helper-auditor-deposits.c
index 291558590..ed23c6a52 100644
--- a/src/auditor/taler-helper-auditor-deposits.c
+++ b/src/auditor/taler-helper-auditor-deposits.c
@@ -114,11 +114,15 @@ test_dc (void *cls,
.h_wire = dc->h_wire,
.refund_deadline = dc->refund_deadline
};
+ struct GNUNET_TIME_Absolute exchange_timestamp;
+ struct TALER_Amount deposit_fee;
qs = TALER_ARL_edb->have_deposit (TALER_ARL_edb->cls,
TALER_ARL_esession,
&dep,
- GNUNET_NO /* do not check refund deadline */);
+ GNUNET_NO /* do not check refund deadline */,
+ &deposit_fee,
+ &exchange_timestamp);
if (qs > 0)
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -137,7 +141,8 @@ test_dc (void *cls,
TALER_ARL_report (report_deposit_confirmation_inconsistencies,
json_pack ("{s:o, s:o, s:I, s:o}",
"timestamp",
- TALER_ARL_json_from_time_abs (dc->timestamp),
+ TALER_ARL_json_from_time_abs (
+ dc->exchange_timestamp),
"amount",
TALER_JSON_from_amount (&dc->amount_without_fee),
"rowid",
diff --git a/src/auditordb/auditor-0001.sql b/src/auditordb/auditor-0001.sql
index ff8867bee..b511a4d5b 100644
--- a/src/auditordb/auditor-0001.sql
+++ b/src/auditordb/auditor-0001.sql
@@ -251,7 +251,7 @@ CREATE TABLE IF NOT EXISTS deposit_confirmations
,serial_id BIGSERIAL UNIQUE
,h_contract_terms BYTEA CHECK (LENGTH(h_contract_terms)=64)
,h_wire BYTEA CHECK (LENGTH(h_wire)=64)
- ,timestamp INT8 NOT NULL
+ ,exchange_timestamp INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,amount_without_fee_val INT8 NOT NULL
,amount_without_fee_frac INT4 NOT NULL
diff --git a/src/auditordb/plugin_auditordb_postgres.c b/src/auditordb/plugin_auditordb_postgres.c
index 467c4c6db..4f9101fdc 100644
--- a/src/auditordb/plugin_auditordb_postgres.c
+++ b/src/auditordb/plugin_auditordb_postgres.c
@@ -269,7 +269,7 @@ postgres_get_session (void *cls)
"(master_pub"
",h_contract_terms"
",h_wire"
- ",timestamp"
+ ",exchange_timestamp"
",refund_deadline"
",amount_without_fee_val"
",amount_without_fee_frac"
@@ -286,7 +286,7 @@ postgres_get_session (void *cls)
" serial_id"
",h_contract_terms"
",h_wire"
- ",timestamp"
+ ",exchange_timestamp"
",refund_deadline"
",amount_without_fee_val"
",amount_without_fee_frac"
@@ -1126,7 +1126,7 @@ postgres_insert_deposit_confirmation (
GNUNET_PQ_query_param_auto_from_type (&dc->master_public_key),
GNUNET_PQ_query_param_auto_from_type (&dc->h_contract_terms),
GNUNET_PQ_query_param_auto_from_type (&dc->h_wire),
- TALER_PQ_query_param_absolute_time (&dc->timestamp),
+ TALER_PQ_query_param_absolute_time (&dc->exchange_timestamp),
TALER_PQ_query_param_absolute_time (&dc->refund_deadline),
TALER_PQ_query_param_amount (&dc->amount_without_fee),
GNUNET_PQ_query_param_auto_from_type (&dc->coin_pub),
@@ -1207,8 +1207,8 @@ deposit_confirmation_cb (void *cls,
&dc.h_contract_terms),
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&dc.h_wire),
- GNUNET_PQ_result_spec_absolute_time ("timestamp",
- &dc.timestamp),
+ GNUNET_PQ_result_spec_absolute_time ("exchange_timestamp",
+ &dc.exchange_timestamp),
GNUNET_PQ_result_spec_absolute_time ("refund_deadline",
&dc.refund_deadline),
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_without_fee",
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_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 65251863a..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,13 +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:o, s:o}",
- "exchange_sig",
- GNUNET_JSON_from_data_auto (&sig),
- "exchange_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));
}
@@ -109,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;
@@ -117,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
@@ -131,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)
@@ -166,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);
@@ -179,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;
@@ -238,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)
{
@@ -252,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
@@ -367,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))
@@ -401,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;
@@ -408,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");
@@ -502,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
@@ -528,7 +546,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
}
/* execute transaction */
- dc.deposit = &deposit;
{
MHD_RESULT mhd_ret;
@@ -557,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_responses.c b/src/exchange/taler-exchange-httpd_responses.c
index 7924ad54c..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,
diff --git a/src/exchangedb/exchange-0001.sql b/src/exchangedb/exchange-0001.sql
index bec9af5ba..ad05e7797 100644
--- a/src/exchangedb/exchange-0001.sql
+++ b/src/exchangedb/exchange-0001.sql
@@ -254,7 +254,8 @@ CREATE TABLE IF NOT EXISTS deposits
,coin_pub BYTEA NOT NULL REFERENCES known_coins (coin_pub) ON DELETE CASCADE
,amount_with_fee_val INT8 NOT NULL
,amount_with_fee_frac INT4 NOT NULL
- ,timestamp INT8 NOT NULL
+ ,wallet_timestamp INT8 NOT NULL
+ ,exchange_timestamp INT8 NOT NULL
,refund_deadline INT8 NOT NULL
,wire_deadline INT8 NOT NULL
,merchant_pub BYTEA NOT NULL CHECK (LENGTH(merchant_pub)=32)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c
index 5bd674b2d..93577feb4 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -796,7 +796,7 @@ postgres_get_session (void *cls)
"(coin_pub"
",amount_with_fee_val"
",amount_with_fee_frac"
- ",timestamp"
+ ",wallet_timestamp"
",refund_deadline"
",wire_deadline"
",merchant_pub"
@@ -804,22 +804,28 @@ postgres_get_session (void *cls)
",h_wire"
",coin_sig"
",wire"
+ ",exchange_timestamp"
") VALUES "
"($1, $2, $3, $4, $5, $6, $7, $8, $9, $10,"
- " $11);",
- 11),
+ " $11, $12);",
+ 12),
/* Fetch an existing deposit request, used to ensure idempotency
during /deposit processing. Used in #postgres_have_deposit(). */
GNUNET_PQ_make_prepare ("get_deposit",
"SELECT"
" amount_with_fee_val"
",amount_with_fee_frac"
- ",timestamp"
+ ",denominations.fee_deposit_val"
+ ",denominations.fee_deposit_frac"
+ ",wallet_timestamp"
+ ",exchange_timestamp"
",refund_deadline"
",wire_deadline"
",h_contract_terms"
",h_wire"
" FROM deposits"
+ " JOIN known_coins USING (coin_pub)"
+ " JOIN denominations USING (denom_pub_hash)"
" WHERE ((coin_pub=$1)"
" AND (merchant_pub=$3)"
" AND (h_contract_terms=$2))"
@@ -830,7 +836,8 @@ postgres_get_session (void *cls)
"SELECT"
" amount_with_fee_val"
",amount_with_fee_frac"
- ",timestamp"
+ ",wallet_timestamp"
+ ",exchange_timestamp"
",merchant_pub"
",denom.denom_pub"
",coin_pub"
@@ -881,6 +888,8 @@ postgres_get_session (void *cls)
",wire"
",merchant_pub"
",coin_pub"
+ ",exchange_timestamp"
+ ",wallet_timestamp"
" FROM deposits"
" JOIN known_coins USING (coin_pub)"
" JOIN denominations denom USING (denom_pub_hash)"
@@ -900,6 +909,8 @@ postgres_get_session (void *cls)
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
",wire_deadline"
+ ",exchange_timestamp"
+ ",wallet_timestamp"
",h_contract_terms"
",coin_pub"
" FROM deposits"
@@ -945,7 +956,7 @@ postgres_get_session (void *cls)
",amount_with_fee_frac"
",denom.fee_deposit_val"
",denom.fee_deposit_frac"
- ",timestamp"
+ ",wallet_timestamp"
",refund_deadline"
",wire_deadline"
",merchant_pub"
@@ -2571,6 +2582,8 @@ postgres_get_reserve_history (void *cls,
* @param session database connection
* @param deposit deposit to search for
* @param check_extras whether to check extra fields match or not
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received the deposit
* @return 1 if we know this operation,
* 0 if this exact deposit is unknown to us,
* otherwise transaction error status
@@ -2579,7 +2592,9 @@ static enum GNUNET_DB_QueryStatus
postgres_have_deposit (void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_EXCHANGEDB_Deposit *deposit,
- int check_extras)
+ int check_extras,
+ struct TALER_Amount *deposit_fee,
+ struct GNUNET_TIME_Absolute *exchange_timestamp)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
@@ -2592,12 +2607,16 @@ postgres_have_deposit (void *cls,
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit2.amount_with_fee),
- TALER_PQ_result_spec_absolute_time ("timestamp",
+ TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit2.timestamp),
+ TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
+ exchange_timestamp),
TALER_PQ_result_spec_absolute_time ("refund_deadline",
&deposit2.refund_deadline),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&deposit2.wire_deadline),
+ TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
+ deposit_fee),
GNUNET_PQ_result_spec_auto_from_type ("h_wire",
&deposit2.h_wire),
GNUNET_PQ_result_spec_end
@@ -2776,6 +2795,8 @@ postgres_get_ready_deposit (void *cls,
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
struct GNUNET_TIME_Absolute wire_deadline;
+ struct GNUNET_TIME_Absolute wallet_timestamp;
+ struct GNUNET_TIME_Absolute exchange_timestamp;
struct GNUNET_HashCode h_contract_terms;
struct TALER_MerchantPublicKeyP merchant_pub;
struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -2788,6 +2809,10 @@ postgres_get_ready_deposit (void *cls,
&amount_with_fee),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&deposit_fee),
+ TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
+ &exchange_timestamp),
+ TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
+ &wallet_timestamp),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&wire_deadline),
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
@@ -2817,6 +2842,8 @@ postgres_get_ready_deposit (void *cls,
qs = deposit_cb (deposit_cb_cls,
serial_id,
+ exchange_timestamp,
+ wallet_timestamp,
&merchant_pub,
&coin_pub,
&amount_with_fee,
@@ -2898,6 +2925,8 @@ match_deposit_cb (void *cls,
{
struct TALER_Amount amount_with_fee;
struct TALER_Amount deposit_fee;
+ struct GNUNET_TIME_Absolute exchange_timestamp;
+ struct GNUNET_TIME_Absolute wallet_timestamp;
struct GNUNET_TIME_Absolute wire_deadline;
struct GNUNET_HashCode h_contract_terms;
struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -2912,6 +2941,10 @@ match_deposit_cb (void *cls,
&deposit_fee),
TALER_PQ_result_spec_absolute_time ("wire_deadline",
&wire_deadline),
+ TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
+ &exchange_timestamp),
+ TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
+ &wallet_timestamp),
GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
&h_contract_terms),
GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
@@ -2930,6 +2963,8 @@ match_deposit_cb (void *cls,
}
qs = mdc->deposit_cb (mdc->deposit_cb_cls,
serial_id,
+ exchange_timestamp,
+ wallet_timestamp,
mdc->merchant_pub,
&coin_pub,
&amount_with_fee,
@@ -3210,12 +3245,14 @@ postgres_ensure_coin_known (void *cls,
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param session connection to the database
+ * @param exchange_timestamp time the exchange received the deposit request
* @param deposit deposit information to store
* @return query result status
*/
static enum GNUNET_DB_QueryStatus
postgres_insert_deposit (void *cls,
struct TALER_EXCHANGEDB_Session *session,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_EXCHANGEDB_Deposit *deposit)
{
struct GNUNET_PQ_QueryParam params[] = {
@@ -3229,6 +3266,7 @@ postgres_insert_deposit (void *cls,
GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire),
GNUNET_PQ_query_param_auto_from_type (&deposit->csig),
TALER_PQ_query_param_json (deposit->receiver_wire_account),
+ TALER_PQ_query_param_absolute_time (&exchange_timestamp),
GNUNET_PQ_query_param_end
};
@@ -4042,7 +4080,7 @@ add_coin_deposit (void *cls,
&deposit->amount_with_fee),
TALER_PQ_RESULT_SPEC_AMOUNT ("fee_deposit",
&deposit->deposit_fee),
- TALER_PQ_result_spec_absolute_time ("timestamp",
+ TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit->timestamp),
TALER_PQ_result_spec_absolute_time ("refund_deadline",
&deposit->refund_deadline),
@@ -5462,14 +5500,17 @@ deposit_serial_helper_cb (void *cls,
for (unsigned int i = 0; i<num_results; i++)
{
struct TALER_EXCHANGEDB_Deposit deposit;
+ struct GNUNET_TIME_Absolute exchange_timestamp;
struct TALER_DenominationPublicKey denom_pub;
uint8_t done = 0;
uint64_t rowid;
struct GNUNET_PQ_ResultSpec rs[] = {
TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
&deposit.amount_with_fee),
- TALER_PQ_result_spec_absolute_time ("timestamp",
+ TALER_PQ_result_spec_absolute_time ("wallet_timestamp",
&deposit.timestamp),
+ TALER_PQ_result_spec_absolute_time ("exchange_timestamp",
+ &exchange_timestamp),
GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
&deposit.merchant_pub),
GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
@@ -5505,6 +5546,7 @@ deposit_serial_helper_cb (void *cls,
}
ret = dsc->cb (dsc->cb_cls,
rowid,
+ exchange_timestamp,
deposit.timestamp,
&deposit.merchant_pub,
&denom_pub,
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index eea484e94..fe3ed7854 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -833,6 +833,8 @@ static uint64_t deposit_rowid;
* @param cls closure a `struct TALER_EXCHANGEDB_Deposit *`
* @param rowid unique ID for the deposit in our DB, used for marking
* it as 'tiny' or 'done'
+ * @param exchange_timestamp when did the deposit happen
+ * @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
@@ -846,6 +848,8 @@ static uint64_t deposit_rowid;
static enum GNUNET_DB_QueryStatus
deposit_cb (void *cls,
uint64_t rowid,
+ 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,
@@ -890,7 +894,8 @@ deposit_cb (void *cls,
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
- * @param timestamp when did the deposit happen
+ * @param exchange_timestamp when did the deposit happen
+ * @param wallet_timestamp when did the wallet sign the contract
* @param merchant_pub public key of the merchant
* @param denom_pub denomination of the @a coin_pub
* @param coin_pub public key of the coin
@@ -908,7 +913,8 @@ deposit_cb (void *cls,
static int
audit_deposit_cb (void *cls,
uint64_t rowid,
- struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -1878,15 +1884,27 @@ run (void *cls)
plugin->ensure_coin_known (plugin->cls,
session,
&deposit.coin));
- FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
- plugin->insert_deposit (plugin->cls,
+ {
+ struct GNUNET_TIME_Absolute now;
+ struct GNUNET_TIME_Absolute r;
+ struct TALER_Amount deposit_fee;
+
+ now = GNUNET_TIME_absolute_get ();
+ GNUNET_TIME_round_abs (&now);
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+ plugin->insert_deposit (plugin->cls,
+ session,
+ now,
+ &deposit));
+ FAILIF (1 !=
+ plugin->have_deposit (plugin->cls,
session,
- &deposit));
- FAILIF (1 !=
- plugin->have_deposit (plugin->cls,
- session,
- &deposit,
- GNUNET_YES));
+ &deposit,
+ GNUNET_YES,
+ &deposit_fee,
+ &r));
+ FAILIF (now.abs_value_us != r.abs_value_us);
+ }
{
struct GNUNET_TIME_Absolute start_range;
struct GNUNET_TIME_Absolute end_range;
@@ -1983,18 +2001,27 @@ run (void *cls)
session,
"test-2"));
RND_BLK (&deposit2.merchant_pub); /* should fail if merchant is different */
- FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
- plugin->have_deposit (plugin->cls,
- session,
- &deposit2,
- GNUNET_YES));
- deposit2.merchant_pub = deposit.merchant_pub;
- RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
- FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
- plugin->have_deposit (plugin->cls,
- session,
- &deposit2,
- GNUNET_YES));
+ {
+ struct GNUNET_TIME_Absolute r;
+ struct TALER_Amount deposit_fee;
+
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
+ plugin->have_deposit (plugin->cls,
+ session,
+ &deposit2,
+ GNUNET_YES,
+ &deposit_fee,
+ &r));
+ deposit2.merchant_pub = deposit.merchant_pub;
+ RND_BLK (&deposit2.coin.coin_pub); /* should fail if coin is different */
+ FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
+ plugin->have_deposit (plugin->cls,
+ session,
+ &deposit2,
+ GNUNET_YES,
+ &deposit_fee,
+ &r));
+ }
FAILIF (GNUNET_OK !=
test_melting (session));
FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
diff --git a/src/include/taler_auditordb_plugin.h b/src/include/taler_auditordb_plugin.h
index 9a7f6ed7a..7c58e654e 100644
--- a/src/include/taler_auditordb_plugin.h
+++ b/src/include/taler_auditordb_plugin.h
@@ -300,9 +300,9 @@ struct TALER_AUDITORDB_DepositConfirmation
struct GNUNET_HashCode h_wire;
/**
- * Time when this confirmation was generated.
+ * Time when this deposit confirmation was generated by the exchange.
*/
- struct GNUNET_TIME_Absolute timestamp;
+ struct GNUNET_TIME_Absolute exchange_timestamp;
/**
* How much time does the @e merchant have to issue a refund
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index 74660303d..eded23339 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -1542,73 +1542,92 @@ enum TALER_ErrorCode
* This response is provided with HTTP status code
* #MHD_HTTP_SERVICE_UNAVAILABLE.
*/
- TALER_EC_TRACK_TRANSFER_EXCHANGE_TIMEOUT = 2400,
+ TALER_EC_POST_TRANSFERS_EXCHANGE_TIMEOUT = 2400,
/**
* We failed to obtain an acceptable /keys response from the exchange
* for the /track/transfer request. This response is provided with
* HTTP status code #MHD_HTTP_FAILED_DEPENDENCY.
*/
- TALER_EC_TRACK_TRANSFER_EXCHANGE_KEYS_FAILURE = 2401,
+ TALER_EC_POST_TRANSFERS_EXCHANGE_KEYS_FAILURE = 2401,
/**
* We failed to persist coin wire transfer information in our merchant
* database. The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
- TALER_EC_TRACK_TRANSFER_DB_STORE_COIN_ERROR = 2402,
+ TALER_EC_POST_TRANSFERS_DB_STORE_COIN_ERROR = 2402,
/**
* We internally failed to execute the /track/transfer request. The
* response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
- TALER_EC_TRACK_TRANSFER_REQUEST_ERROR = 2403,
+ TALER_EC_POST_TRANSFERS_REQUEST_ERROR = 2403,
/**
* We failed to persist wire transfer information in our merchant
* database. The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
- TALER_EC_TRACK_TRANSFER_DB_STORE_TRANSFER_ERROR = 2404,
+ TALER_EC_POST_TRANSFERS_DB_STORE_TRANSFER_ERROR = 2404,
/**
* The exchange returned an error from /track/transfer. The response
* is provided with HTTP status code #MHD_HTTP_FAILED_DEPENDENCY.
*/
- TALER_EC_TRACK_TRANSFER_EXCHANGE_ERROR = 2405,
+ TALER_EC_POST_TRANSFERS_EXCHANGE_ERROR = 2405,
/**
* We failed to fetch deposit information from our merchant database.
* The response is provided with HTTP status code
* #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
- TALER_EC_TRACK_TRANSFER_DB_FETCH_DEPOSIT_ERROR = 2406,
+ TALER_EC_POST_TRANSFERS_DB_FETCH_DEPOSIT_ERROR = 2406,
/**
* We encountered an internal logic error. The response is provided
* with HTTP status code #MHD_HTTP_INTERNAL_SERVER_ERROR.
*/
- TALER_EC_TRACK_TRANSFER_DB_INTERNAL_LOGIC_ERROR = 2407,
+ TALER_EC_POST_TRANSFERS_DB_INTERNAL_LOGIC_ERROR = 2407,
/**
* The exchange gave conflicting information about a coin which has
* been wire transferred. The response is provided with HTTP status
* code #MHD_HTTP_FAILED_DEPENDENCY.
*/
- TALER_EC_TRACK_TRANSFER_CONFLICTING_REPORTS = 2408,
+ TALER_EC_POST_TRANSFERS_CONFLICTING_REPORTS = 2408,
/**
* The merchant backend had problems in creating the JSON response.
*/
- TALER_EC_TRACK_TRANSFER_JSON_RESPONSE_ERROR = 2409,
+ TALER_EC_POST_TRANSFERS_JSON_RESPONSE_ERROR = 2409,
/**
* The exchange charged a different wire fee than what it originally
- * advertised, and it is higher. The response is provied with an HTTP
- * status of #MHD_HTTP_FAILED_DEPENDENCY.
+ * advertised, and it is higher. The response is provided with an
+ * HTTP status of #MHD_HTTP_FAILED_DEPENDENCY.
*/
- TALER_EC_TRACK_TRANSFER_JSON_BAD_WIRE_FEE = 2410,
+ TALER_EC_POST_TRANSFERS_JSON_BAD_WIRE_FEE = 2410,
+
+ /**
+ * We did not find the account that the transfer was made to. The
+ * response is provided with an HTTP status of #MHD_HTTP_NOT_FOUND.
+ */
+ TALER_EC_POST_TRANSFERS_ACCOUNT_NOT_FOUND = 2411,
+
+ /**
+ * We did failed to store information in our database. The response is
+ * provided with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR.
+ */
+ TALER_EC_POST_TRANSFERS_DB_STORE_ERROR = 2412,
+
+ /**
+ * We did failed to retrieve information from our database. The
+ * response is provided with an HTTP status of
+ * #MHD_HTTP_INTERNAL_SERVER_ERROR.
+ */
+ TALER_EC_POST_TRANSFERS_DB_LOOKUP_ERROR = 2413,
/**
* The merchant backend cannot create an instance under the given
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 82b9b83df..38928dc18 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -756,6 +756,7 @@ struct TALER_EXCHANGE_DepositHandle;
*
* @param cls closure
* @param hr HTTP response data
+ * @param deposit_timestamp time when the exchange generated the deposit confirmation
* @param exchange_sig signature provided by the exchange
* @param exchange_pub exchange key used to sign @a obj, or NULL
*/
@@ -763,6 +764,7 @@ typedef void
(*TALER_EXCHANGE_DepositResultCallback) (
void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
+ struct GNUNET_TIME_Absolute deposit_timestamp,
const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *exchange_pub);
diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h
index 4fd580724..9fb932362 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -975,6 +975,8 @@ struct TALER_EXCHANGEDB_Session;
* @param cls closure
* @param rowid unique ID for the deposit in our DB, used for marking
* it as 'tiny' or 'done'
+ * @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
@@ -990,6 +992,8 @@ typedef enum GNUNET_DB_QueryStatus
(*TALER_EXCHANGEDB_DepositIterator)(
void *cls,
uint64_t rowid,
+ 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,
@@ -1022,7 +1026,8 @@ typedef void
*
* @param cls closure
* @param rowid unique serial ID for the deposit in our DB
- * @param timestamp when did the deposit happen
+ * @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 denom_pub denomination public key of @a coin_pub
* @param coin_pub public key of the coin
@@ -1042,7 +1047,8 @@ typedef int
(*TALER_EXCHANGEDB_DepositCallback)(
void *cls,
uint64_t rowid,
- struct GNUNET_TIME_Absolute timestamp,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Absolute wallet_timestamp,
const struct TALER_MerchantPublicKeyP *merchant_pub,
const struct TALER_DenominationPublicKey *denom_pub,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -1841,6 +1847,8 @@ struct TALER_EXCHANGEDB_Plugin
* @param session database connection
* @param deposit deposit to search for
* @param check_extras whether to check extra fields or not
+ * @param[out] deposit_fee set to the deposit fee the exchange charged
+ * @param[out] exchange_timestamp set to the time when the exchange received the deposit
* @return 1 if we know this operation,
* 0 if this exact deposit is unknown to us,
* otherwise transaction error status
@@ -1849,7 +1857,9 @@ struct TALER_EXCHANGEDB_Plugin
(*have_deposit)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
const struct TALER_EXCHANGEDB_Deposit *deposit,
- int check_extras);
+ int check_extras,
+ struct TALER_Amount *deposit_fee,
+ struct GNUNET_TIME_Absolute *exchange_timestamp);
/**
@@ -1857,12 +1867,14 @@ struct TALER_EXCHANGEDB_Plugin
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param session connection to the database
+ * @param exchange_timestamp time the exchange received the deposit request
* @param deposit deposit information to store
* @return query result status
*/
enum GNUNET_DB_QueryStatus
(*insert_deposit)(void *cls,
struct TALER_EXCHANGEDB_Session *session,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_EXCHANGEDB_Deposit *deposit);
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index c346a6cee..38b895d7f 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -363,7 +363,7 @@ struct TALER_DepositRequestPS
* deposit request in a timely fashion (so back-dating is not
* prevented).
*/
- struct GNUNET_TIME_AbsoluteNBO timestamp;
+ struct GNUNET_TIME_AbsoluteNBO wallet_timestamp;
/**
* How much time does the merchant have to issue a refund request?
@@ -429,9 +429,10 @@ struct TALER_DepositConfirmationPS
struct GNUNET_HashCode h_wire GNUNET_PACKED;
/**
- * Time when this confirmation was generated.
+ * Time when this confirmation was generated / when the exchange received
+ * the deposit request.
*/
- struct GNUNET_TIME_AbsoluteNBO timestamp;
+ struct GNUNET_TIME_AbsoluteNBO exchange_timestamp;
/**
* How much time does the @e merchant have to issue a refund
diff --git a/src/include/taler_testing_lib.h b/src/include/taler_testing_lib.h
index 9abb0cca7..53a004c8c 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -1917,6 +1917,7 @@ TALER_TESTING_cmd_connect_with_state (const char *label,
* @param dbc collects plugin and session handles
* @param merchant_name Human-readable name of the merchant.
* @param merchant_account merchant's account name (NOT a payto:// URI)
+ * @param exchange_timestamp when did the exchange receive the deposit
* @param wire_deadline point in time where the aggregator should have
* wired money to the merchant.
* @param amount_with_fee amount to deposit (inclusive of deposit fee)
@@ -1924,14 +1925,15 @@ TALER_TESTING_cmd_connect_with_state (const char *label,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_insert_deposit (const char *label,
- const struct
- TALER_TESTING_DatabaseConnection *dbc,
- const char *merchant_name,
- const char *merchant_account,
- struct GNUNET_TIME_Relative wire_deadline,
- const char *amount_with_fee,
- const char *deposit_fee);
+TALER_TESTING_cmd_insert_deposit (
+ const char *label,
+ const struct TALER_TESTING_DatabaseConnection *dbc,
+ const char *merchant_name,
+ const char *merchant_account,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Relative wire_deadline,
+ const char *amount_with_fee,
+ const char *deposit_fee);
/**
diff --git a/src/lib/auditor_api_deposit_confirmation.c b/src/lib/auditor_api_deposit_confirmation.c
index cddfe8b14..1856a89f4 100644
--- a/src/lib/auditor_api_deposit_confirmation.c
+++ b/src/lib/auditor_api_deposit_confirmation.c
@@ -148,7 +148,7 @@ handle_deposit_confirmation_finished (void *cls,
*
* @param h_wire hash of merchant wire details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor)
- * @param timestamp timestamp when the contract was finalized, must not be too far in the future
+ * @param exchange_timestamp timestamp when the deposit was received by the wallet
* @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline
* @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant
* @param coin_pub coin’s public key
@@ -165,7 +165,7 @@ handle_deposit_confirmation_finished (void *cls,
static int
verify_signatures (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_Amount *amount_without_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -184,7 +184,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
.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_pub
@@ -256,7 +256,7 @@ verify_signatures (const struct GNUNET_HashCode *h_wire,
* @param auditor the auditor handle; the auditor must be ready to operate
* @param h_wire hash of merchant wire details
* @param h_contract_terms hash of the contact of the merchant with the customer (further details are never disclosed to the auditor)
- * @param timestamp timestamp when the contract was finalized, must not be too far in the future
+ * @param exchange_timestamp timestamp when deposit was received by the exchange
* @param refund_deadline date until which the merchant can issue a refund to the customer via the auditor (can be zero if refunds are not allowed); must not be after the @a wire_deadline
* @param amount_without_fee the amount confirmed to be wired by the exchange to the merchant
* @param coin_pub coin’s public key
@@ -278,7 +278,7 @@ TALER_AUDITOR_deposit_confirmation (
struct TALER_AUDITOR_Handle *auditor,
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_Amount *amount_without_fee,
const struct TALER_CoinSpendPublicKeyP *coin_pub,
@@ -298,7 +298,7 @@ TALER_AUDITOR_deposit_confirmation (
json_t *deposit_confirmation_obj;
CURL *eh;
- (void) GNUNET_TIME_round_abs (&timestamp);
+ (void) GNUNET_TIME_round_abs (&exchange_timestamp);
(void) GNUNET_TIME_round_abs (&refund_deadline);
(void) GNUNET_TIME_round_abs (&ep_start);
(void) GNUNET_TIME_round_abs (&ep_expire);
@@ -308,7 +308,7 @@ TALER_AUDITOR_deposit_confirmation (
if (GNUNET_OK !=
verify_signatures (h_wire,
h_contract_terms,
- timestamp,
+ exchange_timestamp,
refund_deadline,
amount_without_fee,
coin_pub,
@@ -336,7 +336,8 @@ TALER_AUDITOR_deposit_confirmation (
"h_wire", GNUNET_JSON_from_data_auto (h_wire),
"h_contract_terms", GNUNET_JSON_from_data_auto (
h_contract_terms),
- "timestamp", GNUNET_JSON_from_time_abs (timestamp),
+ "exchange_timestamp", GNUNET_JSON_from_time_abs (
+ exchange_timestamp),
"refund_deadline", GNUNET_JSON_from_time_abs (refund_deadline),
"amount_without_fee", TALER_JSON_from_amount (
amount_without_fee),
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index dc44291d0..bf8eb5376 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -524,7 +524,7 @@ TALER_EXCHANGE_verify_coin_history (
GNUNET_JSON_spec_fixed_auto ("h_wire",
&dr.h_wire),
GNUNET_JSON_spec_absolute_time_nbo ("timestamp",
- &dr.timestamp),
+ &dr.wallet_timestamp),
GNUNET_JSON_spec_absolute_time_nbo ("refund_deadline",
&dr.refund_deadline),
TALER_JSON_spec_amount_nbo ("deposit_fee",
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index a5cf6c36a..276053658 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -160,7 +160,7 @@ auditor_cb (void *cls,
ah,
&dh->depconf.h_wire,
&dh->depconf.h_contract_terms,
- GNUNET_TIME_absolute_ntoh (dh->depconf.timestamp),
+ GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp),
GNUNET_TIME_absolute_ntoh (dh->depconf.refund_deadline),
&amount_without_fee,
&dh->depconf.coin_pub,
@@ -198,6 +198,8 @@ verify_deposit_signature_ok (struct TALER_EXCHANGE_DepositHandle *dh,
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_absolute_time_nbo ("exchange_timestamp",
+ &dh->depconf.exchange_timestamp),
GNUNET_JSON_spec_end ()
};
@@ -386,6 +388,7 @@ handle_deposit_finished (void *cls,
}
dh->cb (dh->cb_cls,
&hr,
+ GNUNET_TIME_absolute_ntoh (dh->depconf.exchange_timestamp),
es,
ep);
TALER_EXCHANGE_deposit_cancel (dh);
@@ -429,7 +432,7 @@ verify_signatures (const struct TALER_EXCHANGE_DenomPublicKey *dki,
.purpose.size = htonl (sizeof (dr)),
.h_contract_terms = *h_contract_terms,
.h_wire = *h_wire,
- .timestamp = GNUNET_TIME_absolute_hton (timestamp),
+ .wallet_timestamp = GNUNET_TIME_absolute_hton (timestamp),
.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline),
.merchant = *merchant_pub,
.coin_pub = *coin_pub
@@ -658,7 +661,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle *exchange,
TALER_SIGNATURE_EXCHANGE_CONFIRM_DEPOSIT);
dh->depconf.h_contract_terms = *h_contract_terms;
dh->depconf.h_wire = h_wire;
- dh->depconf.timestamp = GNUNET_TIME_absolute_hton (timestamp);
+ /* dh->depconf.exchange_timestamp; -- initialized later from exchange reply! */
dh->depconf.refund_deadline = GNUNET_TIME_absolute_hton (refund_deadline);
TALER_amount_hton (&dh->depconf.amount_without_fee,
&amount_without_fee);
diff --git a/src/lib/exchange_api_refund.c b/src/lib/exchange_api_refund.c
index b1ea176bf..6f91389f1 100644
--- a/src/lib/exchange_api_refund.c
+++ b/src/lib/exchange_api_refund.c
@@ -148,7 +148,8 @@ handle_refund_finished (void *cls,
struct TALER_ExchangeSignatureP exchange_sig;
struct TALER_ExchangePublicKeyP *ep = NULL;
struct TALER_ExchangeSignatureP *es = NULL;
- struct TALER_Amount *rf = NULL;
+ struct TALER_Amount ra;
+ const struct TALER_Amount *rf = NULL;
const json_t *j = response;
struct TALER_EXCHANGE_HttpResponse hr = {
.reply = j,
@@ -176,7 +177,9 @@ handle_refund_finished (void *cls,
{
ep = &exchange_pub;
es = &exchange_sig;
- rf = &rh->depconf.refund_fee;
+ TALER_amount_ntoh (&ra,
+ &rh->depconf.refund_fee);
+ rf = &ra;
}
break;
case MHD_HTTP_BAD_REQUEST:
diff --git a/src/testing/test_taler_exchange_aggregator.c b/src/testing/test_taler_exchange_aggregator.c
index eaa621cfe..d5c392d3a 100644
--- a/src/testing/test_taler_exchange_aggregator.c
+++ b/src/testing/test_taler_exchange_aggregator.c
@@ -108,6 +108,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -126,6 +127,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -134,6 +136,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -153,6 +156,7 @@ run (void *cls,
&dbc,
"bob",
"4",
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -160,6 +164,7 @@ run (void *cls,
&dbc,
"bob",
"5",
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -167,6 +172,7 @@ run (void *cls,
&dbc,
"alice",
"4",
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:1",
"EUR:0.1"),
@@ -195,6 +201,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -204,6 +211,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -229,6 +237,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
10),
@@ -239,6 +248,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -263,6 +273,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@@ -274,6 +285,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@@ -281,6 +293,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@@ -292,6 +305,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.102",
"EUR:0.1"),
@@ -303,6 +317,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.112",
"EUR:0.1"),
@@ -319,6 +334,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.109",
"EUR:0.1"),
@@ -330,6 +346,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.119",
"EUR:0.1"),
@@ -346,6 +363,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.122",
"EUR:0.1"),
@@ -362,6 +380,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -375,6 +394,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -390,6 +410,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.122",
"EUR:0.1"),
@@ -406,6 +427,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -419,6 +441,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_relative_multiply
(GNUNET_TIME_UNIT_SECONDS,
5),
@@ -434,6 +457,7 @@ run (void *cls,
&dbc,
"bob",
USER42_ACCOUNT,
+ GNUNET_TIME_absolute_get (),
GNUNET_TIME_UNIT_ZERO,
"EUR:0.112",
"EUR:0.1"),
diff --git a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
index 247399a9d..1442380bf 100644
--- a/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
+++ b/src/testing/testing_api_cmd_auditor_deposit_confirmation.c
@@ -203,6 +203,7 @@ deposit_confirmation_run (void *cls,
const struct TALER_TESTING_Command *deposit_cmd;
struct GNUNET_HashCode h_wire;
struct GNUNET_HashCode h_contract_terms;
+ const struct GNUNET_TIME_Absolute *exchange_timestamp = NULL;
struct GNUNET_TIME_Absolute timestamp;
struct GNUNET_TIME_Absolute refund_deadline;
struct TALER_Amount amount_without_fee;
@@ -238,6 +239,11 @@ deposit_confirmation_run (void *cls,
TALER_TESTING_get_trait_exchange_sig (deposit_cmd,
dcs->coin_index,
&exchange_sig));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_TESTING_get_trait_absolute_time (deposit_cmd,
+ dcs->coin_index,
+ &exchange_timestamp));
+ GNUNET_assert (NULL != exchange_timestamp);
keys = TALER_EXCHANGE_get_keys (dcs->is->exchange);
GNUNET_assert (NULL != keys);
spk = TALER_EXCHANGE_get_signing_key_info (keys,
@@ -309,7 +315,7 @@ deposit_confirmation_run (void *cls,
dcs->dc = TALER_AUDITOR_deposit_confirmation (dcs->auditor,
&h_wire,
&h_contract_terms,
- timestamp,
+ *exchange_timestamp,
refund_deadline,
&amount_without_fee,
&coin_pub,
diff --git a/src/testing/testing_api_cmd_deposit.c b/src/testing/testing_api_cmd_deposit.c
index 9468e7acb..049f36f25 100644
--- a/src/testing/testing_api_cmd_deposit.c
+++ b/src/testing/testing_api_cmd_deposit.c
@@ -91,9 +91,9 @@ struct DepositState
struct TALER_EXCHANGE_DepositHandle *dh;
/**
- * Timestamp of the /deposit operation.
+ * Timestamp of the /deposit operation in the wallet (contract signing time).
*/
- struct GNUNET_TIME_Absolute timestamp;
+ struct GNUNET_TIME_Absolute wallet_timestamp;
/**
* Interpreter state.
@@ -127,6 +127,11 @@ struct DepositState
int deposit_succeeded;
/**
+ * When did the exchange receive the deposit?
+ */
+ struct GNUNET_TIME_Absolute exchange_timestamp;
+
+ /**
* Signing key used by the exchange to sign the
* deposit confirmation.
*/
@@ -198,6 +203,7 @@ do_retry (void *cls)
*
* @param cls closure.
* @param hr HTTP response details
+ * @param exchange_timestamp when did the exchange receive the deposit permission
* @param exchange_sig signature provided by the exchange
* (NULL on errors)
* @param exchange_pub public key of the exchange,
@@ -206,6 +212,7 @@ do_retry (void *cls)
static void
deposit_cb (void *cls,
const struct TALER_EXCHANGE_HttpResponse *hr,
+ const struct GNUNET_TIME_Absolute exchange_timestamp,
const struct TALER_ExchangeSignatureP *exchange_sig,
const struct TALER_ExchangePublicKeyP *exchange_pub)
{
@@ -254,6 +261,7 @@ deposit_cb (void *cls,
if (MHD_HTTP_OK == hr->http_status)
{
ds->deposit_succeeded = GNUNET_YES;
+ ds->exchange_timestamp = exchange_timestamp;
ds->exchange_pub = *exchange_pub;
ds->exchange_sig = *exchange_sig;
}
@@ -305,7 +313,7 @@ deposit_run (void *cls,
ds->coin_index = ods->coin_index;
ds->wire_details = json_incref (ods->wire_details);
ds->contract_terms = json_incref (ods->contract_terms);
- ds->timestamp = ods->timestamp;
+ ds->wallet_timestamp = ods->wallet_timestamp;
ds->refund_deadline = ods->refund_deadline;
ds->amount = ods->amount;
ds->merchant_priv = ods->merchant_priv;
@@ -379,7 +387,7 @@ deposit_run (void *cls,
}
else
{
- ds->refund_deadline = ds->timestamp;
+ ds->refund_deadline = ds->wallet_timestamp;
wire_deadline = GNUNET_TIME_relative_to_absolute
(GNUNET_TIME_UNIT_ZERO);
}
@@ -388,6 +396,7 @@ deposit_run (void *cls,
(void) GNUNET_TIME_round_abs (&wire_deadline);
+ // FIXME: This should be part of TALER_EXCHANGE_deposit()!
{
struct TALER_DepositRequestPS dr;
@@ -400,7 +409,7 @@ deposit_run (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_JSON_merchant_wire_signature_hash (ds->wire_details,
&dr.h_wire));
- dr.timestamp = GNUNET_TIME_absolute_hton (ds->timestamp);
+ dr.wallet_timestamp = GNUNET_TIME_absolute_hton (ds->wallet_timestamp);
dr.refund_deadline = GNUNET_TIME_absolute_hton
(ds->refund_deadline);
TALER_amount_hton (&dr.amount_with_fee,
@@ -421,7 +430,7 @@ deposit_run (void *cls,
&coin_pub,
denom_pub_sig,
&denom_pub->key,
- ds->timestamp,
+ ds->wallet_timestamp,
&merchant_pub,
ds->refund_deadline,
&coin_sig,
@@ -534,6 +543,8 @@ deposit_traits (void *cls,
&ds->merchant_priv),
TALER_TESTING_make_trait_amount_obj (0,
&ds->amount),
+ TALER_TESTING_make_trait_absolute_time (0,
+ &ds->exchange_timestamp),
TALER_TESTING_trait_end ()
};
@@ -599,12 +610,12 @@ TALER_TESTING_cmd_deposit (const char *label,
label);
GNUNET_assert (0);
}
- ds->timestamp = GNUNET_TIME_absolute_get ();
- (void) GNUNET_TIME_round_abs (&ds->timestamp);
+ ds->wallet_timestamp = GNUNET_TIME_absolute_get ();
+ (void) GNUNET_TIME_round_abs (&ds->wallet_timestamp);
json_object_set_new (ds->contract_terms,
"timestamp",
- GNUNET_JSON_from_time_abs (ds->timestamp));
+ GNUNET_JSON_from_time_abs (ds->wallet_timestamp));
if (0 != refund_deadline.rel_value_us)
{
ds->refund_deadline = GNUNET_TIME_relative_to_absolute (refund_deadline);
@@ -687,12 +698,12 @@ TALER_TESTING_cmd_deposit_with_ref (const char *label,
label);
GNUNET_assert (0);
}
- ds->timestamp = GNUNET_TIME_absolute_get ();
- (void) GNUNET_TIME_round_abs (&ds->timestamp);
+ ds->wallet_timestamp = GNUNET_TIME_absolute_get ();
+ (void) GNUNET_TIME_round_abs (&ds->wallet_timestamp);
json_object_set_new (ds->contract_terms,
"timestamp",
- GNUNET_JSON_from_time_abs (ds->timestamp));
+ GNUNET_JSON_from_time_abs (ds->wallet_timestamp));
if (0 != refund_deadline.rel_value_us)
{
ds->refund_deadline = GNUNET_TIME_relative_to_absolute (refund_deadline);
diff --git a/src/testing/testing_api_cmd_insert_deposit.c b/src/testing/testing_api_cmd_insert_deposit.c
index 356528009..cff2884aa 100644
--- a/src/testing/testing_api_cmd_insert_deposit.c
+++ b/src/testing/testing_api_cmd_insert_deposit.c
@@ -58,6 +58,11 @@ struct InsertDepositState
struct GNUNET_TIME_Relative wire_deadline;
/**
+ * When did the exchange receive the deposit?
+ */
+ struct GNUNET_TIME_Absolute exchange_timestamp;
+
+ /**
* Amount to deposit, inclusive of deposit fee.
*/
const char *amount_with_fee;
@@ -210,6 +215,7 @@ insert_deposit_run (void *cls,
(GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
ids->dbc->plugin->insert_deposit (ids->dbc->plugin->cls,
ids->dbc->session,
+ ids->exchange_timestamp,
&deposit)) ||
(GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
ids->dbc->plugin->commit (ids->dbc->plugin->cls,
@@ -275,6 +281,7 @@ insert_deposit_traits (void *cls,
* @param dbc collects database plugin and session handles.
* @param merchant_name Human-readable name of the merchant.
* @param merchant_account merchant's account name (NOT a payto:// URI)
+ * @param exchange_timestamp when did the exchange receive the deposit
* @param wire_deadline point in time where the aggregator should have
* wired money to the merchant.
* @param amount_with_fee amount to deposit (inclusive of deposit fee)
@@ -282,21 +289,24 @@ insert_deposit_traits (void *cls,
* @return the command.
*/
struct TALER_TESTING_Command
-TALER_TESTING_cmd_insert_deposit (const char *label,
- const struct
- TALER_TESTING_DatabaseConnection *dbc,
- const char *merchant_name,
- const char *merchant_account,
- struct GNUNET_TIME_Relative wire_deadline,
- const char *amount_with_fee,
- const char *deposit_fee)
+TALER_TESTING_cmd_insert_deposit (
+ const char *label,
+ const struct TALER_TESTING_DatabaseConnection *dbc,
+ const char *merchant_name,
+ const char *merchant_account,
+ struct GNUNET_TIME_Absolute exchange_timestamp,
+ struct GNUNET_TIME_Relative wire_deadline,
+ const char *amount_with_fee,
+ const char *deposit_fee)
{
struct InsertDepositState *ids;
+ GNUNET_TIME_round_abs (&exchange_timestamp);
ids = GNUNET_new (struct InsertDepositState);
ids->dbc = dbc;
ids->merchant_name = merchant_name;
ids->merchant_account = merchant_account;
+ ids->exchange_timestamp = exchange_timestamp;
ids->wire_deadline = wire_deadline;
ids->amount_with_fee = amount_with_fee;
ids->deposit_fee = deposit_fee;