gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] 13/152: towards changing timestamp in deposit confirmat


From: gnunet
Subject: [taler-exchange] 13/152: towards changing timestamp in deposit confirmation (tests failing)
Date: Sun, 05 Jul 2020 20:46:09 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

commit 7ab9d526f23d52d87d47aa195351022db3748d2c
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Thu May 7 20:22:02 2020 +0200

    towards changing timestamp in deposit confirmation (tests failing)
---
 .../taler-auditor-httpd_deposit-confirmation.c     |   5 +-
 src/auditor/taler-helper-auditor-coins.c           |   8 +-
 src/auditor/taler-helper-auditor-deposits.c        |   9 +-
 src/auditordb/auditor-0001.sql                     |   2 +-
 src/auditordb/plugin_auditordb_postgres.c          |  10 +-
 src/exchange/taler-exchange-aggregator.c           |  12 ++
 src/exchange/taler-exchange-httpd_deposit.c        | 173 +++++++++++----------
 src/exchange/taler-exchange-httpd_responses.c      |   2 +-
 src/exchangedb/exchange-0001.sql                   |   3 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |  62 ++++++--
 src/exchangedb/test_exchangedb.c                   |  71 ++++++---
 src/include/taler_auditordb_plugin.h               |   4 +-
 src/include/taler_error_codes.h                    |  45 ++++--
 src/include/taler_exchange_service.h               |   2 +
 src/include/taler_exchangedb_plugin.h              |  18 ++-
 src/include/taler_signatures.h                     |   7 +-
 src/include/taler_testing_lib.h                    |  18 ++-
 src/lib/auditor_api_deposit_confirmation.c         |  17 +-
 src/lib/exchange_api_common.c                      |   2 +-
 src/lib/exchange_api_deposit.c                     |   9 +-
 src/lib/exchange_api_refund.c                      |   7 +-
 src/testing/test_taler_exchange_aggregator.c       |  24 +++
 .../testing_api_cmd_auditor_deposit_confirmation.c |   8 +-
 src/testing/testing_api_cmd_deposit.c              |  35 +++--
 src/testing/testing_api_cmd_insert_deposit.c       |  26 +++-
 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 5f84a725..1039164c 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 2e32c569..158baa8b 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 29155859..ed23c6a5 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 ff8867be..b511a4d5 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 467c4c6d..4f9101fd 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 21a29e50..69c73746 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 65251863..fe8fdf06 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));
 }
 
 
@@ -108,6 +111,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.
    */
@@ -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)
   {
@@ -251,45 +299,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
@@ -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 7924ad54..f6595161 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 bec9af5b..ad05e779 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 5bd674b2..93577feb 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 eea484e9..fe3ed785 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 9a7f6ed7..7c58e654 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 74660303..eded2333 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 82b9b83d..38928dc1 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 4fd58072..9fb93236 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 c346a6ce..38b895d7 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 acc218ac..6a4fa024 100644
--- a/src/include/taler_testing_lib.h
+++ b/src/include/taler_testing_lib.h
@@ -1903,6 +1903,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)
@@ -1910,14 +1911,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 cddfe8b1..1856a89f 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 dc44291d..bf8eb537 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 a5cf6c36..27605365 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 b1ea176b..6f91389f 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 eaa621cf..d5c392d3 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 247399a9..1442380b 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 9468e7ac..049f36f2 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.
@@ -126,6 +126,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 35652800..cff2884a 100644
--- a/src/testing/testing_api_cmd_insert_deposit.c
+++ b/src/testing/testing_api_cmd_insert_deposit.c
@@ -57,6 +57,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.
    */
@@ -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;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]