gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: kill another FIXME


From: gnunet
Subject: [taler-exchange] branch master updated: kill another FIXME
Date: Thu, 16 Jan 2020 23:49:36 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new d61c2e40 kill another FIXME
d61c2e40 is described below

commit d61c2e400ac07574fc326c8d2be6f51be7c2a25c
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu Jan 16 23:49:34 2020 +0100

    kill another FIXME
---
 src/auditor/taler-auditor.c                      |  51 ++---
 src/exchange/taler-exchange-httpd_deposit.c      |   2 +
 src/exchange/taler-exchange-httpd_payback.c      |   1 +
 src/exchange/taler-exchange-httpd_refresh_melt.c |   3 +-
 src/exchange/taler-exchange-httpd_refund.c       | 118 ++++++++----
 src/exchange/taler-exchange-httpd_responses.c    |  53 +++--
 src/exchange/taler-exchange-httpd_responses.h    |   8 +-
 src/exchangedb/exchangedb_transactions.c         |   7 +-
 src/exchangedb/plugin_exchangedb_common.c        |  12 --
 src/exchangedb/plugin_exchangedb_postgres.c      | 140 +++++---------
 src/exchangedb/test_exchangedb.c                 |  65 +++----
 src/include/taler_exchangedb_plugin.h            | 235 ++++++++++++++++++++---
 12 files changed, 435 insertions(+), 260 deletions(-)

diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 42724efb..a3f6eae2 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -2274,7 +2274,7 @@ check_transaction_history_for_deposit (const struct
       }
       break;
     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
-      amount_with_fee = &tl->details.melt->session.amount_with_fee;
+      amount_with_fee = &tl->details.melt->amount_with_fee;
       fee = &tl->details.melt->melt_fee;
       fee_dki = &issue->fee_refresh;
       if (GNUNET_OK !=
@@ -2489,7 +2489,7 @@ wire_transfer_information_cb (void *cls,
   struct TALER_Amount computed_value;
   struct TALER_Amount coin_value_without_fee;
   struct TALER_EXCHANGEDB_TransactionList *tl;
-  const struct TALER_CoinPublicInfo *coin;
+  struct TALER_CoinPublicInfo coin;
   enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_HashCode hw;
 
@@ -2525,36 +2525,26 @@ wire_transfer_information_cb (void *cls,
                               "no transaction history for coin claimed in 
aggregation");
     return;
   }
+  qs = edb->get_known_coin (edb->cls,
+                            esession,
+                            coin_pub,
+                            &coin);
+  if (qs < 0)
+  {
+    GNUNET_break (0); /* this should be a foreign key violation at this point! 
*/
+    wcc->qs = qs;
+    report_row_inconsistency ("aggregation",
+                              rowid,
+                              "could not get coin details for coin claimed in 
aggregation");
+    return;
+  }
 
-  /* Obtain general denomination information about the coin */
-  coin = NULL;
-  switch (tl->type)
-  {
-  case TALER_EXCHANGEDB_TT_DEPOSIT:
-    coin = &tl->details.deposit->coin;
-    break;
-  case TALER_EXCHANGEDB_TT_REFRESH_MELT:
-    coin = &tl->details.melt->session.coin;
-    break;
-  case TALER_EXCHANGEDB_TT_REFUND:
-    coin = &tl->details.refund->coin;
-    break;
-  case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
-    coin = &tl->details.payback_refresh->coin;
-    break;
-  case TALER_EXCHANGEDB_TT_PAYBACK:
-    coin = &tl->details.payback->coin;
-    break;
-  case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
-    coin = &tl->details.payback_refresh->coin;
-    break;
-  }
-  GNUNET_assert (NULL != coin); /* hard check that switch worked */
-  qs = get_denomination_info_by_hash (&coin->denom_pub_hash,
+  qs = get_denomination_info_by_hash (&coin.denom_pub_hash,
                                       &issue);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+    GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
     edb->free_coin_transaction_list (edb->cls,
                                      tl);
     wcc->qs = qs;
@@ -2564,7 +2554,7 @@ wire_transfer_information_cb (void *cls,
     return;
   }
   if (GNUNET_OK !=
-      TALER_test_coin_valid (coin,
+      TALER_test_coin_valid (&coin,
                              denom_pub))
   {
     report (report_bad_sig_losses,
@@ -2578,7 +2568,7 @@ wire_transfer_information_cb (void *cls,
                   TALER_amount_add (&total_bad_sig_loss,
                                     &total_bad_sig_loss,
                                     coin_value));
-
+    GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
     edb->free_coin_transaction_list (edb->cls,
                                      tl);
     wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
@@ -2587,7 +2577,8 @@ wire_transfer_information_cb (void *cls,
                               "coin denomination signature invalid");
     return;
   }
-
+  GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
+  coin.denom_sig.rsa_signature = NULL; /* just to be sure */
   GNUNET_assert (NULL != issue); /* mostly to help static analysis */
   /* Check transaction history to see if it supports aggregate
      valuation */
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 11f579ab..38cc4307 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -214,6 +214,8 @@ deposit_transaction (void *cls,
                 "Deposited coin has insufficient funds left!\n");
     *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
                                                            
TALER_EC_DEPOSIT_INSUFFICIENT_FUNDS,
+                                                           &deposit->coin.
+                                                           coin_pub,
                                                            tl);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
diff --git a/src/exchange/taler-exchange-httpd_payback.c 
b/src/exchange/taler-exchange-httpd_payback.c
index a05045b2..bfd0f413 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -346,6 +346,7 @@ payback_transaction (void *cls,
                           session);
     *mhd_ret = TEH_RESPONSE_reply_coin_insufficient_funds (connection,
                                                            
TALER_EC_PAYBACK_COIN_BALANCE_ZERO,
+                                                           &pc->coin->coin_pub,
                                                            tl);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 4f429012..e0a4d836 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -59,7 +59,8 @@ reply_refresh_melt_insufficient_funds (struct MHD_Connection 
*connection,
 {
   json_t *history;
 
-  history = TEH_RESPONSE_compile_transaction_history (tl);
+  history = TEH_RESPONSE_compile_transaction_history (coin_pub,
+                                                      tl);
   if (NULL == history)
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
diff --git a/src/exchange/taler-exchange-httpd_refund.c 
b/src/exchange/taler-exchange-httpd_refund.c
index 6a96ff98..cb0a0f15 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -40,12 +40,14 @@
  * Generate successful refund confirmation message.
  *
  * @param connection connection to the client
+ * @param coin_pub public key of the coin
  * @param refund details about the successful refund
  * @return MHD result code
  */
 static int
 reply_refund_success (struct MHD_Connection *connection,
-                      const struct TALER_EXCHANGEDB_Refund *refund)
+                      const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                      const struct TALER_EXCHANGEDB_RefundListEntry *refund)
 {
   struct TALER_RefundConfirmationPS rc;
   struct TALER_ExchangePublicKeyP pub;
@@ -54,7 +56,7 @@ reply_refund_success (struct MHD_Connection *connection,
   rc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_REFUND);
   rc.purpose.size = htonl (sizeof (struct TALER_RefundConfirmationPS));
   rc.h_contract_terms = refund->h_contract_terms;
-  rc.coin_pub = refund->coin.coin_pub;
+  rc.coin_pub = *coin_pub;
   rc.merchant = refund->merchant_pub;
   rc.rtransaction_id = GNUNET_htonll (refund->rtransaction_id);
   TALER_amount_hton (&rc.refund_amount,
@@ -107,11 +109,13 @@ reply_refund_failure (struct MHD_Connection *connection,
  * transaction list @a tl with the details about the conflict.
  *
  * @param connection connection to the client
+ * @param coin_pub public key this is about
  * @param tl transaction list showing the conflict
  * @return MHD result code
  */
 static int
 reply_refund_conflict (struct MHD_Connection *connection,
+                       const struct TALER_CoinSpendPublicKeyP *coin_pub,
                        const struct TALER_EXCHANGEDB_TransactionList *tl)
 {
   return TALER_MHD_reply_json_pack (connection,
@@ -122,6 +126,7 @@ reply_refund_conflict (struct MHD_Connection *connection,
                                     (json_int_t) TALER_EC_REFUND_CONFLICT,
                                     "history",
                                     TEH_RESPONSE_compile_transaction_history (
+                                      coin_pub,
                                       tl));
 }
 
@@ -152,8 +157,8 @@ refund_transaction (void *cls,
 {
   const struct TALER_EXCHANGEDB_Refund *refund = cls;
   struct TALER_EXCHANGEDB_TransactionList *tl;
-  const struct TALER_EXCHANGEDB_Deposit *dep;
-  const struct TALER_EXCHANGEDB_Refund *ref;
+  const struct TALER_EXCHANGEDB_DepositListEntry *dep;
+  const struct TALER_EXCHANGEDB_RefundListEntry *ref;
   struct TEH_KS_StateHandle *mks;
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
   struct TALER_Amount expect_fee;
@@ -163,6 +168,7 @@ refund_transaction (void *cls,
   int fee_cmp;
   unsigned int hc;
   enum TALER_ErrorCode ec;
+  struct TALER_CoinPublicInfo coin_info;
 
   dep = NULL;
   ref = NULL;
@@ -192,10 +198,10 @@ refund_transaction (void *cls,
       if (GNUNET_NO == deposit_found)
       {
         if ( (0 == memcmp (&tlp->details.deposit->merchant_pub,
-                           &refund->merchant_pub,
+                           &refund->details.merchant_pub,
                            sizeof (struct TALER_MerchantPublicKeyP))) &&
              (0 == memcmp (&tlp->details.deposit->h_contract_terms,
-                           &refund->h_contract_terms,
+                           &refund->details.h_contract_terms,
                            sizeof (struct GNUNET_HashCode))) )
         {
           dep = tlp->details.deposit;
@@ -212,12 +218,13 @@ refund_transaction (void *cls,
       {
         /* First, check if existing refund request is identical */
         if ( (0 == memcmp (&tlp->details.refund->merchant_pub,
-                           &refund->merchant_pub,
+                           &refund->details.merchant_pub,
                            sizeof (struct TALER_MerchantPublicKeyP))) &&
              (0 == memcmp (&tlp->details.refund->h_contract_terms,
-                           &refund->h_contract_terms,
+                           &refund->details.h_contract_terms,
                            sizeof (struct GNUNET_HashCode))) &&
-             (tlp->details.refund->rtransaction_id == refund->rtransaction_id) 
)
+             (tlp->details.refund->rtransaction_id ==
+              refund->details.rtransaction_id) )
         {
           ref = tlp->details.refund;
           refund_found = GNUNET_YES;
@@ -225,12 +232,13 @@ refund_transaction (void *cls,
         }
         /* Second, check if existing refund request conflicts */
         if ( (0 == memcmp (&tlp->details.refund->merchant_pub,
-                           &refund->merchant_pub,
+                           &refund->details.merchant_pub,
                            sizeof (struct TALER_MerchantPublicKeyP))) &&
              (0 == memcmp (&tlp->details.refund->h_contract_terms,
-                           &refund->h_contract_terms,
+                           &refund->details.h_contract_terms,
                            sizeof (struct GNUNET_HashCode))) &&
-             (tlp->details.refund->rtransaction_id != refund->rtransaction_id) 
)
+             (tlp->details.refund->rtransaction_id !=
+              refund->details.rtransaction_id) )
         {
           GNUNET_break_op (0); /* conflicting refund found */
           refund_found = GNUNET_SYSERR;
@@ -269,6 +277,7 @@ refund_transaction (void *cls,
   if (GNUNET_SYSERR == refund_found)
   {
     *mhd_ret = reply_refund_conflict (connection,
+                                      &refund->coin.coin_pub,
                                       tl);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
@@ -279,6 +288,7 @@ refund_transaction (void *cls,
   {
     /* /refund already done, simply re-transmit confirmation */
     *mhd_ret = reply_refund_success (connection,
+                                     &refund->coin.coin_pub,
                                      ref);
     TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
                                             tl);
@@ -287,10 +297,10 @@ refund_transaction (void *cls,
 
   /* check currency is compatible */
   if ( (GNUNET_YES !=
-        TALER_amount_cmp_currency (&refund->refund_amount,
+        TALER_amount_cmp_currency (&refund->details.refund_amount,
                                    &dep->amount_with_fee)) ||
        (GNUNET_YES !=
-        TALER_amount_cmp_currency (&refund->refund_fee,
+        TALER_amount_cmp_currency (&refund->details.refund_fee,
                                    &dep->deposit_fee)) )
   {
     GNUNET_break_op (0); /* currency missmatch */
@@ -303,7 +313,10 @@ refund_transaction (void *cls,
   /* check if we already send the money for the /deposit */
   qs = TEH_plugin->test_deposit_done (TEH_plugin->cls,
                                       session,
-                                      dep);
+                                      &refund->coin.coin_pub,
+                                      &dep->merchant_pub,
+                                      &dep->h_contract_terms,
+                                      &dep->h_wire);
   if (GNUNET_DB_STATUS_HARD_ERROR == qs)
   {
     /* Internal error, we first had the deposit in the history,
@@ -332,7 +345,7 @@ refund_transaction (void *cls,
   }
 
   /* check refund amount is sufficiently low */
-  if (1 == TALER_amount_cmp (&refund->refund_amount,
+  if (1 == TALER_amount_cmp (&refund->details.refund_amount,
                              &dep->amount_with_fee) )
   {
     GNUNET_break_op (0); /* cannot refund more than original value */
@@ -343,7 +356,25 @@ refund_transaction (void *cls,
                                      TALER_EC_REFUND_INSUFFICIENT_FUNDS);
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-
+  qs = TEH_plugin->get_known_coin (TEH_plugin->cls,
+                                   session,
+                                   &refund->coin.coin_pub,
+                                   &coin_info);
+  if (0 > qs)
+  {
+    TEH_plugin->free_coin_transaction_list (TEH_plugin->cls,
+                                            tl);
+    if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+    {
+      GNUNET_break (0); /* should be impossible by foreign key constraint! */
+      *mhd_ret = reply_refund_failure (connection,
+                                       MHD_HTTP_NOT_FOUND,
+                                       TALER_EC_REFUND_COIN_NOT_FOUND);
+    }
+    return qs;
+  }
+  GNUNET_CRYPTO_rsa_signature_free (coin_info.denom_sig.rsa_signature);
+  coin_info.denom_sig.rsa_signature = NULL; /* just to be safe */
   // FIXME: do this outside of transaction function?
   /* Check refund fee matches fee of denomination key! */
   mks = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
@@ -359,7 +390,7 @@ refund_transaction (void *cls,
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
   dki = TEH_KS_denomination_key_lookup_by_hash (mks,
-                                                &dep->coin.denom_pub_hash,
+                                                &coin_info.denom_pub_hash,
                                                 TEH_KS_DKU_DEPOSIT,
                                                 &ec,
                                                 &hc);
@@ -379,7 +410,7 @@ refund_transaction (void *cls,
   }
   TALER_amount_ntoh (&expect_fee,
                      &dki->issue.properties.fee_refund);
-  fee_cmp = TALER_amount_cmp (&refund->refund_fee,
+  fee_cmp = TALER_amount_cmp (&refund->details.refund_fee,
                               &expect_fee);
   TEH_KS_release (mks);
 
@@ -436,19 +467,9 @@ verify_and_execute_refund (struct MHD_Connection 
*connection,
   struct TALER_RefundRequestPS rr;
   int mhd_ret;
 
-  rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
-  rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
-  rr.h_contract_terms = refund->h_contract_terms;
-  rr.coin_pub = refund->coin.coin_pub;
-  rr.merchant = refund->merchant_pub;
-  rr.rtransaction_id = GNUNET_htonll (refund->rtransaction_id);
-  TALER_amount_hton (&rr.refund_amount,
-                     &refund->refund_amount);
-  TALER_amount_hton (&rr.refund_fee,
-                     &refund->refund_fee);
   if (GNUNET_YES !=
-      TALER_amount_cmp_currency (&refund->refund_amount,
-                                 &refund->refund_fee) )
+      TALER_amount_cmp_currency (&refund->details.refund_amount,
+                                 &refund->details.refund_fee) )
   {
     GNUNET_break_op (0);
     return TALER_MHD_reply_with_error (connection,
@@ -456,8 +477,8 @@ verify_and_execute_refund (struct MHD_Connection 
*connection,
                                        TALER_EC_REFUND_FEE_CURRENCY_MISSMATCH,
                                        "refund_fee");
   }
-  if (-1 == TALER_amount_cmp (&refund->refund_amount,
-                              &refund->refund_fee) )
+  if (-1 == TALER_amount_cmp (&refund->details.refund_amount,
+                              &refund->details.refund_fee) )
   {
     GNUNET_break_op (0);
     return TALER_MHD_reply_with_error (connection,
@@ -465,11 +486,21 @@ verify_and_execute_refund (struct MHD_Connection 
*connection,
                                        TALER_EC_REFUND_FEE_ABOVE_AMOUNT,
                                        "refund_amount");
   }
+  rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
+  rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
+  rr.h_contract_terms = refund->details.h_contract_terms;
+  rr.coin_pub = refund->coin.coin_pub;
+  rr.merchant = refund->details.merchant_pub;
+  rr.rtransaction_id = GNUNET_htonll (refund->details.rtransaction_id);
+  TALER_amount_hton (&rr.refund_amount,
+                     &refund->details.refund_amount);
+  TALER_amount_hton (&rr.refund_fee,
+                     &refund->details.refund_fee);
   if (GNUNET_OK !=
       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_MERCHANT_REFUND,
                                   &rr.purpose,
-                                  &refund->merchant_sig.eddsa_sig,
-                                  &refund->merchant_pub.eddsa_pub))
+                                  &refund->details.merchant_sig.eddsa_sig,
+                                  &refund->details.merchant_pub.eddsa_pub))
   {
     TALER_LOG_WARNING ("Invalid signature on /refund request\n");
     return TALER_MHD_reply_with_error (connection,
@@ -485,7 +516,8 @@ verify_and_execute_refund (struct MHD_Connection 
*connection,
                               (void *) refund))
     return mhd_ret;
   return reply_refund_success (connection,
-                               refund);
+                               &refund->coin.coin_pub,
+                               &refund->details);
 }
 
 
@@ -514,13 +546,15 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
   int res;
   struct TALER_EXCHANGEDB_Refund refund;
   struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_amount ("refund_amount", &refund.refund_amount),
-    TALER_JSON_spec_amount ("refund_fee", &refund.refund_fee),
-    GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &refund.h_contract_terms),
+    TALER_JSON_spec_amount ("refund_amount", &refund.details.refund_amount),
+    TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee),
+    GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
+                                 &refund.details.h_contract_terms),
     GNUNET_JSON_spec_fixed_auto ("coin_pub", &refund.coin.coin_pub),
-    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.merchant_pub),
-    GNUNET_JSON_spec_uint64 ("rtransaction_id", &refund.rtransaction_id),
-    GNUNET_JSON_spec_fixed_auto ("merchant_sig", &refund.merchant_sig),
+    GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.details.merchant_pub),
+    GNUNET_JSON_spec_uint64 ("rtransaction_id",
+                             &refund.details.rtransaction_id),
+    GNUNET_JSON_spec_fixed_auto ("merchant_sig", &refund.details.merchant_sig),
     GNUNET_JSON_spec_end ()
   };
 
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 4ef0f2d1..d6e5c32a 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -42,11 +42,14 @@
 /**
  * Compile the transaction history of a coin into a JSON object.
  *
+ * @param coin_pub public key of the coin
  * @param tl transaction history to JSON-ify
  * @return json representation of the @a rh, NULL on error
  */
 json_t *
 TEH_RESPONSE_compile_transaction_history (const struct
+                                          TALER_CoinSpendPublicKeyP *coin_pub,
+                                          const struct
                                           TALER_EXCHANGEDB_TransactionList *tl)
 {
   json_t *history;
@@ -66,7 +69,8 @@ TEH_RESPONSE_compile_transaction_history (const struct
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       {
         struct TALER_DepositRequestPS dr;
-        const struct TALER_EXCHANGEDB_Deposit *deposit = pos->details.deposit;
+        const struct TALER_EXCHANGEDB_DepositListEntry *deposit =
+          pos->details.deposit;
 
         dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
         dr.purpose.size = htonl (sizeof (struct TALER_DepositRequestPS));
@@ -80,14 +84,14 @@ TEH_RESPONSE_compile_transaction_history (const struct
         TALER_amount_hton (&dr.deposit_fee,
                            &deposit->deposit_fee);
         dr.merchant = deposit->merchant_pub;
-        dr.coin_pub = deposit->coin.coin_pub;
+        dr.coin_pub = *coin_pub;
 #if SANITY_CHECKS_ON
         /* internal sanity check before we hand out a bogus sig... */
         if (GNUNET_OK !=
             GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_DEPOSIT,
                                         &dr.purpose,
                                         &deposit->csig.eddsa_signature,
-                                        &deposit->coin.coin_pub.eddsa_pub))
+                                        &coin_pub->eddsa_pub))
         {
           GNUNET_break (0);
           json_decref (history);
@@ -132,24 +136,25 @@ TEH_RESPONSE_compile_transaction_history (const struct
     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
       {
         struct TALER_RefreshMeltCoinAffirmationPS ms;
-        const struct TALER_EXCHANGEDB_RefreshMelt *melt = pos->details.melt;
+        const struct TALER_EXCHANGEDB_RefreshMeltListEntry *melt =
+          pos->details.melt;
 
         ms.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
         ms.purpose.size = htonl (sizeof (struct
                                          TALER_RefreshMeltCoinAffirmationPS));
-        ms.rc = melt->session.rc;
+        ms.rc = melt->rc;
         TALER_amount_hton (&ms.amount_with_fee,
-                           &melt->session.amount_with_fee);
+                           &melt->amount_with_fee);
         TALER_amount_hton (&ms.melt_fee,
                            &melt->melt_fee);
-        ms.coin_pub = melt->session.coin.coin_pub;
+        ms.coin_pub = *coin_pub;
 #if SANITY_CHECKS_ON
         /* internal sanity check before we hand out a bogus sig... */
         if (GNUNET_OK !=
             GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
                                         &ms.purpose,
-                                        
&melt->session.coin_sig.eddsa_signature,
-                                        
&melt->session.coin.coin_pub.eddsa_pub))
+                                        &melt->coin_sig.eddsa_signature,
+                                        &coin_pub->eddsa_pub))
         {
           GNUNET_break (0);
           json_decref (history);
@@ -161,15 +166,15 @@ TEH_RESPONSE_compile_transaction_history (const struct
                                    json_pack ("{s:s, s:o, s:o, s:o, s:o}",
                                               "type", "MELT",
                                               "amount", TALER_JSON_from_amount 
(
-                                                
&melt->session.amount_with_fee),
+                                                &melt->amount_with_fee),
                                               "melt_fee",
                                               TALER_JSON_from_amount (
                                                 &melt->melt_fee),
                                               "rc", GNUNET_JSON_from_data_auto 
(
-                                                &melt->session.rc),
+                                                &melt->rc),
                                               "coin_sig",
                                               GNUNET_JSON_from_data_auto (
-                                                &melt->session.coin_sig))))
+                                                &melt->coin_sig))))
         {
           GNUNET_break (0);
           json_decref (history);
@@ -180,7 +185,8 @@ TEH_RESPONSE_compile_transaction_history (const struct
     case TALER_EXCHANGEDB_TT_REFUND:
       {
         struct TALER_RefundRequestPS rr;
-        const struct TALER_EXCHANGEDB_Refund *refund = pos->details.refund;
+        const struct TALER_EXCHANGEDB_RefundListEntry *refund =
+          pos->details.refund;
         struct TALER_Amount value;
 
         if (GNUNET_OK !=
@@ -195,7 +201,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
         rr.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_REFUND);
         rr.purpose.size = htonl (sizeof (struct TALER_RefundRequestPS));
         rr.h_contract_terms = refund->h_contract_terms;
-        rr.coin_pub = refund->coin.coin_pub;
+        rr.coin_pub = *coin_pub;
         rr.merchant = refund->merchant_pub;
         rr.rtransaction_id = GNUNET_htonll (refund->rtransaction_id);
         TALER_amount_hton (&rr.refund_amount,
@@ -245,7 +251,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
       break;
     case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
       {
-        struct TALER_EXCHANGEDB_PaybackRefresh *pr =
+        struct TALER_EXCHANGEDB_PaybackRefreshListEntry *pr =
           pos->details.old_coin_payback;
         struct TALER_PaybackRefreshConfirmationPS pc;
         struct TALER_ExchangePublicKeyP epub;
@@ -257,7 +263,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
         pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
         TALER_amount_hton (&pc.payback_amount,
                            &pr->value);
-        pc.coin_pub = pr->coin.coin_pub;
+        pc.coin_pub = *coin_pub;
         pc.old_coin_pub = pr->old_coin_pub;
         if (GNUNET_OK !=
             TEH_KS_sign (&pc.purpose,
@@ -299,7 +305,8 @@ TEH_RESPONSE_compile_transaction_history (const struct
       }
     case TALER_EXCHANGEDB_TT_PAYBACK:
       {
-        const struct TALER_EXCHANGEDB_Payback *payback = pos->details.payback;
+        const struct TALER_EXCHANGEDB_PaybackListEntry *payback =
+          pos->details.payback;
         struct TALER_PaybackConfirmationPS pc;
         struct TALER_ExchangePublicKeyP epub;
         struct TALER_ExchangeSignatureP esig;
@@ -309,7 +316,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
         pc.timestamp = GNUNET_TIME_absolute_hton (payback->timestamp);
         TALER_amount_hton (&pc.payback_amount,
                            &payback->value);
-        pc.coin_pub = payback->coin.coin_pub;
+        pc.coin_pub = *coin_pub;
         pc.reserve_pub = payback->reserve_pub;
         if (GNUNET_OK !=
             TEH_KS_sign (&pc.purpose,
@@ -347,7 +354,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
       break;
     case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
       {
-        struct TALER_EXCHANGEDB_PaybackRefresh *pr =
+        struct TALER_EXCHANGEDB_PaybackRefreshListEntry *pr =
           pos->details.payback_refresh;
         struct TALER_PaybackRefreshConfirmationPS pc;
         struct TALER_ExchangePublicKeyP epub;
@@ -359,7 +366,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
         pc.timestamp = GNUNET_TIME_absolute_hton (pr->timestamp);
         TALER_amount_hton (&pc.payback_amount,
                            &pr->value);
-        pc.coin_pub = pr->coin.coin_pub;
+        pc.coin_pub = *coin_pub;
         pc.old_coin_pub = pr->old_coin_pub;
         if (GNUNET_OK !=
             TEH_KS_sign (&pc.purpose,
@@ -415,6 +422,7 @@ TEH_RESPONSE_compile_transaction_history (const struct
  *
  * @param connection connection to the client
  * @param ec error code to return
+ * @param coin_pub public key of the coin
  * @param tl transaction list to use to build reply
  * @return MHD result code
  */
@@ -422,11 +430,14 @@ int
 TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection,
                                             enum TALER_ErrorCode ec,
                                             const struct
+                                            TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                            const struct
                                             TALER_EXCHANGEDB_TransactionList 
*tl)
 {
   json_t *history;
 
-  history = TEH_RESPONSE_compile_transaction_history (tl);
+  history = TEH_RESPONSE_compile_transaction_history (coin_pub,
+                                                      tl);
   if (NULL == history)
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
diff --git a/src/exchange/taler-exchange-httpd_responses.h 
b/src/exchange/taler-exchange-httpd_responses.h
index ec051582..782e17dd 100644
--- a/src/exchange/taler-exchange-httpd_responses.h
+++ b/src/exchange/taler-exchange-httpd_responses.h
@@ -55,6 +55,7 @@ TEH_RESPONSE_compile_reserve_history (const struct
  *
  * @param connection connection to the client
  * @param ec error code to return
+ * @param coin_pub public key of the coin
  * @param tl transaction list to use to build reply
  * @return MHD result code
  */
@@ -62,17 +63,22 @@ int
 TEH_RESPONSE_reply_coin_insufficient_funds (struct MHD_Connection *connection,
                                             enum TALER_ErrorCode ec,
                                             const struct
+                                            TALER_CoinSpendPublicKeyP 
*coin_pub,
+                                            const struct
                                             TALER_EXCHANGEDB_TransactionList 
*tl);
 
 
 /**
  * Compile the transaction history of a coin into a JSON object.
  *
+ * @param coin_pub public key of the coin
  * @param tl transaction history to JSON-ify
- * @return json representation of the @a rh
+ * @return json representation of the @a rh, NULL on error
  */
 json_t *
 TEH_RESPONSE_compile_transaction_history (const struct
+                                          TALER_CoinSpendPublicKeyP *coin_pub,
+                                          const struct
                                           TALER_EXCHANGEDB_TransactionList 
*tl);
 
 
diff --git a/src/exchangedb/exchangedb_transactions.c 
b/src/exchangedb/exchangedb_transactions.c
index 2891f0ad..871061aa 100644
--- a/src/exchangedb/exchangedb_transactions.c
+++ b/src/exchangedb/exchangedb_transactions.c
@@ -46,8 +46,9 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (struct
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (spent.currency,
                                         &refunded));
-  for (struct TALER_EXCHANGEDB_TransactionList *pos = tl; NULL != pos; pos =
-         pos->next)
+  for (struct TALER_EXCHANGEDB_TransactionList *pos = tl;
+       NULL != pos;
+       pos = pos->next)
   {
     switch (pos->type)
     {
@@ -67,7 +68,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (struct
       if (GNUNET_OK !=
           TALER_amount_add (&spent,
                             &spent,
-                            &pos->details.melt->session.amount_with_fee))
+                            &pos->details.melt->amount_with_fee))
       {
         GNUNET_break (0);
         return GNUNET_SYSERR;
diff --git a/src/exchangedb/plugin_exchangedb_common.c 
b/src/exchangedb/plugin_exchangedb_common.c
index dac746b0..02f06cc1 100644
--- a/src/exchangedb/plugin_exchangedb_common.c
+++ b/src/exchangedb/plugin_exchangedb_common.c
@@ -92,15 +92,9 @@ common_free_coin_transaction_list (void *cls,
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       if (NULL != list->details.deposit->receiver_wire_account)
         json_decref (list->details.deposit->receiver_wire_account);
-      if (NULL != list->details.deposit->coin.denom_sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (
-          list->details.deposit->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.deposit);
       break;
     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
-      if (NULL != list->details.melt->session.coin.denom_sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (
-          list->details.melt->session.coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.melt);
       break;
     case TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK:
@@ -110,15 +104,9 @@ common_free_coin_transaction_list (void *cls,
       GNUNET_free (list->details.old_coin_payback);
       break;
     case TALER_EXCHANGEDB_TT_REFUND:
-      if (NULL != list->details.refund->coin.denom_sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (
-          list->details.refund->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.refund);
       break;
     case TALER_EXCHANGEDB_TT_PAYBACK:
-      if (NULL != list->details.payback->coin.denom_sig.rsa_signature)
-        GNUNET_CRYPTO_rsa_signature_free (
-          list->details.payback->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.payback);
       break;
     case TALER_EXCHANGEDB_TT_PAYBACK_REFRESH:
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 65e52e67..59f0efe4 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -1630,12 +1630,8 @@ postgres_get_session (void *cls)
                               ",amount_val"
                               ",amount_frac"
                               ",timestamp"
-                              ",coins.denom_pub_hash"
-                              ",coins.denom_sig"
                               ",payback_uuid"
                               " FROM payback"
-                              "    JOIN known_coins coins"
-                              "      USING (coin_pub)"
                               "    JOIN reserves_out ro"
                               "      USING (h_blind_ev)"
                               " WHERE payback.coin_pub=$1"
@@ -2982,7 +2978,10 @@ postgres_mark_deposit_tiny (void *cls,
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param session connection to the database
- * @param deposit the deposit to check
+ * @param coin_pub the coin to check for deposit
+ * @param merchant_pub merchant to receive the deposit
+ * @param h_contract_terms contract terms of the deposit
+ * @param h_wire hash of the merchant's wire details
  * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if is is marked done,
  *         #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if not,
  *         otherwise transaction error status (incl. deposit unknown)
@@ -2990,13 +2989,16 @@ postgres_mark_deposit_tiny (void *cls,
 static enum GNUNET_DB_QueryStatus
 postgres_test_deposit_done (void *cls,
                             struct TALER_EXCHANGEDB_Session *session,
-                            const struct TALER_EXCHANGEDB_Deposit *deposit)
+                            const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                            const struct TALER_MerchantPublicKeyP 
*merchant_pub,
+                            const struct GNUNET_HashCode *h_contract_terms,
+                            const struct GNUNET_HashCode *h_wire)
 {
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&deposit->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->h_contract_terms),
-    GNUNET_PQ_query_param_auto_from_type (&deposit->h_wire),
+    GNUNET_PQ_query_param_auto_from_type (coin_pub),
+    GNUNET_PQ_query_param_auto_from_type (merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_auto_from_type (h_wire),
     GNUNET_PQ_query_param_end
   };
   uint8_t done = 0;
@@ -3517,18 +3519,18 @@ postgres_insert_refund (void *cls,
 {
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&refund->coin.coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->merchant_pub),
-    GNUNET_PQ_query_param_auto_from_type (&refund->merchant_sig),
-    GNUNET_PQ_query_param_auto_from_type (&refund->h_contract_terms),
-    GNUNET_PQ_query_param_uint64 (&refund->rtransaction_id),
-    TALER_PQ_query_param_amount (&refund->refund_amount),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_pub),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.merchant_sig),
+    GNUNET_PQ_query_param_auto_from_type (&refund->details.h_contract_terms),
+    GNUNET_PQ_query_param_uint64 (&refund->details.rtransaction_id),
+    TALER_PQ_query_param_amount (&refund->details.refund_amount),
     GNUNET_PQ_query_param_end
   };
 
   (void) cls;
   GNUNET_assert (GNUNET_YES ==
-                 TALER_amount_cmp_currency (&refund->refund_amount,
-                                            &refund->refund_fee));
+                 TALER_amount_cmp_currency (&refund->details.refund_amount,
+                                            &refund->details.refund_fee));
   return GNUNET_PQ_eval_prepared_non_select (session->conn,
                                              "insert_refund",
                                              params);
@@ -4296,12 +4298,11 @@ add_coin_deposit (void *cls,
 
   for (unsigned int i = 0; i < num_results; i++)
   {
-    struct TALER_EXCHANGEDB_Deposit *deposit;
+    struct TALER_EXCHANGEDB_DepositListEntry *deposit;
     struct TALER_EXCHANGEDB_TransactionList *tl;
-    enum GNUNET_DB_QueryStatus qs;
     uint64_t serial_id;
 
-    deposit = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
+    deposit = GNUNET_new (struct TALER_EXCHANGEDB_DepositListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
         TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
@@ -4339,24 +4340,12 @@ add_coin_deposit (void *cls,
         chc->status = GNUNET_DB_STATUS_HARD_ERROR;
         return;
       }
-      deposit->coin.coin_pub = *chc->coin_pub;
     }
     tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_DEPOSIT;
     tl->details.deposit = deposit;
     tl->serial_id = serial_id;
-    qs = postgres_get_known_coin (chc->db_cls,
-                                  chc->session,
-                                  chc->coin_pub,
-                                  &deposit->coin);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      GNUNET_free (deposit);
-      chc->status = qs;
-      return;
-    }
     chc->head = tl;
   }
 }
@@ -4380,21 +4369,20 @@ add_coin_melt (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_RefreshMelt *melt;
+    struct TALER_EXCHANGEDB_RefreshMeltListEntry *melt;
     struct TALER_EXCHANGEDB_TransactionList *tl;
-    enum GNUNET_DB_QueryStatus qs;
     uint64_t serial_id;
 
-    melt = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMelt);
+    melt = GNUNET_new (struct TALER_EXCHANGEDB_RefreshMeltListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
         GNUNET_PQ_result_spec_auto_from_type ("rc",
-                                              &melt->session.rc),
+                                              &melt->rc),
         /* oldcoin_index not needed */
         GNUNET_PQ_result_spec_auto_from_type ("old_coin_sig",
-                                              &melt->session.coin_sig),
+                                              &melt->coin_sig),
         TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                     &melt->session.amount_with_fee),
+                                     &melt->amount_with_fee),
         TALER_PQ_RESULT_SPEC_AMOUNT ("fee_refresh",
                                      &melt->melt_fee),
         GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
@@ -4412,25 +4400,12 @@ add_coin_melt (void *cls,
         chc->status = GNUNET_DB_STATUS_HARD_ERROR;
         return;
       }
-      melt->session.coin.coin_pub = *chc->coin_pub;
     }
     tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_REFRESH_MELT;
     tl->details.melt = melt;
     tl->serial_id = serial_id;
-    /* FIXME: integrate via JOIN in main select, instead of using separate 
query */
-    qs = postgres_get_known_coin (chc->db_cls,
-                                  chc->session,
-                                  chc->coin_pub,
-                                  &melt->session.coin);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      GNUNET_free (melt);
-      chc->status = qs;
-      return;
-    }
     chc->head = tl;
   }
 }
@@ -4454,12 +4429,11 @@ add_coin_refund (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_Refund *refund;
+    struct TALER_EXCHANGEDB_RefundListEntry *refund;
     struct TALER_EXCHANGEDB_TransactionList *tl;
-    enum GNUNET_DB_QueryStatus qs;
     uint64_t serial_id;
 
-    refund = GNUNET_new (struct TALER_EXCHANGEDB_Refund);
+    refund = GNUNET_new (struct TALER_EXCHANGEDB_RefundListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
         GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
@@ -4489,24 +4463,12 @@ add_coin_refund (void *cls,
         chc->status = GNUNET_DB_STATUS_HARD_ERROR;
         return;
       }
-      refund->coin.coin_pub = *chc->coin_pub;
     }
     tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
     tl->next = chc->head;
     tl->type = TALER_EXCHANGEDB_TT_REFUND;
     tl->details.refund = refund;
     tl->serial_id = serial_id;
-    qs = postgres_get_known_coin (chc->db_cls,
-                                  chc->session,
-                                  chc->coin_pub,
-                                  &refund->coin);
-    if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
-    {
-      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
-      GNUNET_free (refund);
-      chc->status = qs;
-      return;
-    }
     chc->head = tl;
   }
 }
@@ -4530,11 +4492,11 @@ add_old_coin_payback (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_PaybackRefresh *payback;
+    struct TALER_EXCHANGEDB_PaybackRefreshListEntry *payback;
     struct TALER_EXCHANGEDB_TransactionList *tl;
     uint64_t serial_id;
 
-    payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefresh);
+    payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefreshListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
         GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
@@ -4597,28 +4559,23 @@ add_coin_payback (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_Payback *payback;
+    struct TALER_EXCHANGEDB_PaybackListEntry *payback;
     struct TALER_EXCHANGEDB_TransactionList *tl;
     uint64_t serial_id;
 
-    payback = GNUNET_new (struct TALER_EXCHANGEDB_Payback);
+    payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
-        TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
-                                     &payback->value),
         GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
                                               &payback->reserve_pub),
-        GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
-                                              &payback->coin_blind),
         GNUNET_PQ_result_spec_auto_from_type ("coin_sig",
                                               &payback->coin_sig),
+        GNUNET_PQ_result_spec_auto_from_type ("coin_blind",
+                                              &payback->coin_blind),
+        TALER_PQ_RESULT_SPEC_AMOUNT ("amount",
+                                     &payback->value),
         TALER_PQ_result_spec_absolute_time ("timestamp",
                                             &payback->timestamp),
-        GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
-                                              &payback->coin.denom_pub_hash),
-        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                             &payback->coin.denom_sig.
-                                             rsa_signature),
         GNUNET_PQ_result_spec_uint64 ("payback_uuid",
                                       &serial_id),
         GNUNET_PQ_result_spec_end
@@ -4634,7 +4591,6 @@ add_coin_payback (void *cls,
         chc->status = GNUNET_DB_STATUS_HARD_ERROR;
         return;
       }
-      payback->coin.coin_pub = *chc->coin_pub;
     }
     tl = GNUNET_new (struct TALER_EXCHANGEDB_TransactionList);
     tl->next = chc->head;
@@ -4664,11 +4620,11 @@ add_coin_payback_refresh (void *cls,
 
   for (unsigned int i = 0; i<num_results; i++)
   {
-    struct TALER_EXCHANGEDB_PaybackRefresh *payback;
+    struct TALER_EXCHANGEDB_PaybackRefreshListEntry *payback;
     struct TALER_EXCHANGEDB_TransactionList *tl;
     uint64_t serial_id;
 
-    payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefresh);
+    payback = GNUNET_new (struct TALER_EXCHANGEDB_PaybackRefreshListEntry);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
         GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
@@ -6066,19 +6022,19 @@ refunds_serial_helper_cb (void *cls,
     uint64_t rowid;
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("merchant_pub",
-                                            &refund.merchant_pub),
+                                            &refund.details.merchant_pub),
       GNUNET_PQ_result_spec_auto_from_type ("merchant_sig",
-                                            &refund.merchant_sig),
+                                            &refund.details.merchant_sig),
       GNUNET_PQ_result_spec_auto_from_type ("h_contract_terms",
-                                            &refund.h_contract_terms),
+                                            &refund.details.h_contract_terms),
       GNUNET_PQ_result_spec_uint64 ("rtransaction_id",
-                                    &refund.rtransaction_id),
+                                    &refund.details.rtransaction_id),
       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
                                             &denom_pub.rsa_public_key),
       GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                             &refund.coin.coin_pub),
       TALER_PQ_RESULT_SPEC_AMOUNT ("amount_with_fee",
-                                   &refund.refund_amount),
+                                   &refund.details.refund_amount),
       GNUNET_PQ_result_spec_uint64 ("refund_serial_id",
                                     &rowid),
       GNUNET_PQ_result_spec_end
@@ -6098,11 +6054,11 @@ refunds_serial_helper_cb (void *cls,
                    rowid,
                    &denom_pub,
                    &refund.coin.coin_pub,
-                   &refund.merchant_pub,
-                   &refund.merchant_sig,
-                   &refund.h_contract_terms,
-                   refund.rtransaction_id,
-                   &refund.refund_amount);
+                   &refund.details.merchant_pub,
+                   &refund.details.merchant_sig,
+                   &refund.details.h_contract_terms,
+                   refund.details.rtransaction_id,
+                   &refund.details.refund_amount);
     GNUNET_PQ_cleanup_result (rs);
     if (GNUNET_OK != ret)
       break;
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index 73d89e0b..e9fe67b4 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1432,36 +1432,36 @@ check_refund_cb (void *cls,
   const struct TALER_EXCHANGEDB_Refund *refund = cls;
 
   if (0 != GNUNET_memcmp (merchant_pub,
-                          &refund->merchant_pub))
+                          &refund->details.merchant_pub))
   {
     GNUNET_break (0);
     result = 66;
   }
   if (0 != GNUNET_memcmp (merchant_sig,
-                          &refund->merchant_sig))
+                          &refund->details.merchant_sig))
   {
     GNUNET_break (0);
     result = 66;
   }
   if (0 != GNUNET_memcmp (h_contract,
-                          &refund->h_contract_terms))
+                          &refund->details.h_contract_terms))
   {
     GNUNET_break (0);
     result = 66;
   }
-  if (rtransaction_id != refund->rtransaction_id)
+  if (rtransaction_id != refund->details.rtransaction_id)
   {
     GNUNET_break (0);
     result = 66;
   }
   if (0 != TALER_amount_cmp (amount_with_fee,
-                             &refund->refund_amount))
+                             &refund->details.refund_amount))
   {
     GNUNET_break (0);
     result = 66;
   }
   if (0 != TALER_amount_cmp (refund_fee,
-                             &refund->refund_fee))
+                             &refund->details.refund_fee))
   {
     GNUNET_break (0);
     result = 66;
@@ -1925,7 +1925,10 @@ run (void *cls)
   FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->test_deposit_done (plugin->cls,
                                      session,
-                                     &deposit));
+                                     &deposit.coin.coin_pub,
+                                     &deposit.merchant_pub,
+                                     &deposit.h_contract_terms,
+                                     &deposit.h_wire));
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->mark_deposit_done (plugin->cls,
                                      session,
@@ -1936,7 +1939,10 @@ run (void *cls)
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->test_deposit_done (plugin->cls,
                                      session,
-                                     &deposit));
+                                     &deposit.coin.coin_pub,
+                                     &deposit.merchant_pub,
+                                     &deposit.h_contract_terms,
+                                     &deposit.h_wire));
 
   result = 10;
   deposit2 = deposit;
@@ -1966,13 +1972,14 @@ run (void *cls)
 
   /* test insert_refund! */
   refund.coin = deposit.coin;
-  refund.merchant_pub = deposit.merchant_pub;
-  RND_BLK (&refund.merchant_sig);
-  refund.h_contract_terms = deposit.h_contract_terms;
-  refund.rtransaction_id = GNUNET_CRYPTO_random_u64 
(GNUNET_CRYPTO_QUALITY_WEAK,
-                                                     UINT64_MAX);
-  refund.refund_amount = deposit.amount_with_fee;
-  refund.refund_fee = fee_refund;
+  refund.details.merchant_pub = deposit.merchant_pub;
+  RND_BLK (&refund.details.merchant_sig);
+  refund.details.h_contract_terms = deposit.h_contract_terms;
+  refund.details.rtransaction_id
+    = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                UINT64_MAX);
+  refund.details.refund_amount = deposit.amount_with_fee;
+  refund.details.refund_fee = fee_refund;
   FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->insert_refund (plugin->cls,
                                  session,
@@ -2064,11 +2071,8 @@ run (void *cls)
     {
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       {
-        struct TALER_EXCHANGEDB_Deposit *have = tlp->details.deposit;
+        struct TALER_EXCHANGEDB_DepositListEntry *have = tlp->details.deposit;
 
-        FAILIF (0 != memcmp (&have->coin.coin_pub,
-                             &deposit.coin.coin_pub,
-                             sizeof (struct TALER_CoinSpendPublicKeyP)));
         /* Note: we're not comparing the denomination keys, as there is
            still the question of whether we should even bother exporting
            them here. */
@@ -2108,31 +2112,29 @@ run (void *cls)
 #endif
     case TALER_EXCHANGEDB_TT_REFUND:
       {
-        struct TALER_EXCHANGEDB_Refund *have = tlp->details.refund;
+        struct TALER_EXCHANGEDB_RefundListEntry *have = tlp->details.refund;
 
-        FAILIF (0 != memcmp (&have->coin.coin_pub,
-                             &refund.coin.coin_pub,
-                             sizeof (struct TALER_CoinSpendPublicKeyP)));
         /* Note: we're not comparing the denomination keys, as there is
            still the question of whether we should even bother exporting
            them here. */
         FAILIF (0 != GNUNET_memcmp (&have->merchant_pub,
-                                    &refund.merchant_pub));
+                                    &refund.details.merchant_pub));
         FAILIF (0 != GNUNET_memcmp (&have->merchant_sig,
-                                    &refund.merchant_sig));
+                                    &refund.details.merchant_sig));
         FAILIF (0 != GNUNET_memcmp (&have->h_contract_terms,
-                                    &refund.h_contract_terms));
-        FAILIF (have->rtransaction_id != refund.rtransaction_id);
+                                    &refund.details.h_contract_terms));
+        FAILIF (have->rtransaction_id != refund.details.rtransaction_id);
         FAILIF (0 != TALER_amount_cmp (&have->refund_amount,
-                                       &refund.refund_amount));
+                                       &refund.details.refund_amount));
         FAILIF (0 != TALER_amount_cmp (&have->refund_fee,
-                                       &refund.refund_fee));
+                                       &refund.details.refund_fee));
         matched |= 4;
         break;
       }
     case TALER_EXCHANGEDB_TT_PAYBACK:
       {
-        struct TALER_EXCHANGEDB_Payback *payback = tlp->details.payback;
+        struct TALER_EXCHANGEDB_PaybackListEntry *payback =
+          tlp->details.payback;
 
         FAILIF (0 != GNUNET_memcmp (&payback->coin_sig,
                                     &coin_sig));
@@ -2140,9 +2142,6 @@ run (void *cls)
                                     &coin_blind));
         FAILIF (0 != GNUNET_memcmp (&payback->reserve_pub,
                                     &reserve_pub));
-        FAILIF (0 != memcmp (&payback->coin.coin_pub,
-                             &deposit.coin.coin_pub,
-                             sizeof (deposit.coin.coin_pub)));
         FAILIF (0 != TALER_amount_cmp (&payback->value,
                                        &value));
         matched |= 8;
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index cb5d6cc6..3178209d 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -275,7 +275,8 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin
 
 
 /**
- * Information the exchange records about a /payback request.
+ * Information the exchange records about a /payback request
+ * in a reserve history.
  */
 struct TALER_EXCHANGEDB_Payback
 {
@@ -316,13 +317,52 @@ struct TALER_EXCHANGEDB_Payback
 
 
 /**
- * Information the exchange records about a /payback-refresh request.
+ * Information the exchange records about a /payback request
+ * in a coin history.
  */
-struct TALER_EXCHANGEDB_PaybackRefresh
+struct TALER_EXCHANGEDB_PaybackListEntry
 {
 
   /**
-   * Information about the coin that was paid back.
+   * Blinding factor supplied to prove to the exchange that
+   * the coin came from this reserve.
+   */
+  struct TALER_DenominationBlindingKeyP coin_blind;
+
+  /**
+   * Signature of the coin of type
+   * #TALER_SIGNATURE_WALLET_COIN_PAYBACK.
+   */
+  struct TALER_CoinSpendSignatureP coin_sig;
+
+  /**
+   * Public key of the reserve the coin was paid back into.
+   */
+  struct TALER_ReservePublicKeyP reserve_pub;
+
+  /**
+   * How much was the coin still worth at this time?
+   */
+  struct TALER_Amount value;
+
+  /**
+   * When did the /payback operation happen?
+   */
+  struct GNUNET_TIME_Absolute timestamp;
+
+};
+
+
+/**
+ * Information the exchange records about a /payback-refresh request in
+ * a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_PaybackRefreshListEntry
+{
+
+  /**
+   * Information about the coin that was paid back
+   * (NOT the coin we are considering the history of!)
    */
   struct TALER_CoinPublicInfo coin;
 
@@ -534,22 +574,95 @@ struct TALER_EXCHANGEDB_Deposit
 
 
 /**
- * @brief Specification for a /refund operation.  The combination of
- * the coin's public key, the merchant's public key and the
- * transaction ID must be unique.  While a coin can (theoretically) be
- * deposited at the same merchant twice (with partial spending), the
- * merchant must either use a different public key or a different
- * transaction ID for the two transactions.  The same goes for
- * refunds, hence we also have a "rtransaction" ID which is disjoint
- * from the transaction ID.  The same coin must not be used twice at
- * the same merchant for the same transaction or rtransaction ID.
+ * @brief Specification for a /deposit operation in the
+ * `struct TALER_EXCHANGEDB_TransactionList`.
  */
-struct TALER_EXCHANGEDB_Refund
+struct TALER_EXCHANGEDB_DepositListEntry
 {
+
   /**
-   * Information about the coin that is being refunded.
+   * ECDSA signature affirming that the customer intends
+   * this coin to be deposited at the merchant identified
+   * by @e h_wire in relation to the proposal data identified
+   * by @e h_contract_terms.
    */
-  struct TALER_CoinPublicInfo coin;
+  struct TALER_CoinSpendSignatureP csig;
+
+  /**
+   * Public key of the merchant.  Enables later identification
+   * of the merchant in case of a need to rollback transactions.
+   */
+  struct TALER_MerchantPublicKeyP merchant_pub;
+
+  /**
+   * Hash over the proposa data between merchant and customer
+   * (remains unknown to the Exchange).
+   */
+  struct GNUNET_HashCode h_contract_terms;
+
+  /**
+   * Hash of the (canonical) representation of @e wire, used
+   * to check the signature on the request.  Generated by
+   * the exchange from the detailed wire data provided by the
+   * merchant.
+   */
+  struct GNUNET_HashCode h_wire;
+
+  /**
+   * Detailed information about the receiver for executing the transaction.
+   * Includes URL in payto://-format and salt.
+   */
+  json_t *receiver_wire_account;
+
+  /**
+   * Time when this request was generated.  Used, for example, to
+   * assess when (roughly) the income was achieved for tax purposes.
+   * Note that the Exchange will only check that the timestamp is not "too
+   * far" into the future (i.e. several days).  The fact that the
+   * timestamp falls within the validity period of the coin's
+   * denomination key is irrelevant for the validity of the deposit
+   * request, as obviously the customer and merchant could conspire to
+   * set any timestamp.  Also, the Exchange must accept very old deposit
+   * requests, as the merchant might have been unable to transmit the
+   * deposit request in a timely fashion (so back-dating is not
+   * prevented).
+   */
+  struct GNUNET_TIME_Absolute timestamp;
+
+  /**
+   * How much time does the merchant have to issue a refund request?
+   * Zero if refunds are not allowed.  After this time, the coin
+   * cannot be refunded.
+   */
+  struct GNUNET_TIME_Absolute refund_deadline;
+
+  /**
+   * How much time does the merchant have to execute the wire transfer?
+   * This time is advisory for aggregating transactions, not a hard
+   * constraint (as the merchant can theoretically pick any time,
+   * including one in the past).
+   */
+  struct GNUNET_TIME_Absolute wire_deadline;
+
+  /**
+   * Fraction of the coin's remaining value to be deposited, including
+   * depositing fee (if any).  The coin is identified by @e coin_pub.
+   */
+  struct TALER_Amount amount_with_fee;
+
+  /**
+   * Depositing fee.
+   */
+  struct TALER_Amount deposit_fee;
+
+};
+
+
+/**
+ * @brief Specification for a /refund operation in a coin's transaction list.
+ */
+struct TALER_EXCHANGEDB_RefundListEntry
+{
 
   /**
    * Public key of the merchant.
@@ -587,6 +700,32 @@ struct TALER_EXCHANGEDB_Refund
 };
 
 
+/**
+ * @brief Specification for a /refund operation.  The combination of
+ * the coin's public key, the merchant's public key and the
+ * transaction ID must be unique.  While a coin can (theoretically) be
+ * deposited at the same merchant twice (with partial spending), the
+ * merchant must either use a different public key or a different
+ * transaction ID for the two transactions.  The same goes for
+ * refunds, hence we also have a "rtransaction" ID which is disjoint
+ * from the transaction ID.  The same coin must not be used twice at
+ * the same merchant for the same transaction or rtransaction ID.
+ */
+struct TALER_EXCHANGEDB_Refund
+{
+  /**
+   * Information about the coin that is being refunded.
+   */
+  struct TALER_CoinPublicInfo coin;
+
+  /**
+   * Details about the refund.
+   */
+  struct TALER_EXCHANGEDB_RefundListEntry details;
+
+};
+
+
 /**
  * @brief Specification for coin in a /refresh/melt operation.
  */
@@ -627,7 +766,47 @@ struct TALER_EXCHANGEDB_RefreshSession
 
 
 /**
- * Information about a /refresh/melt operation in the transaction history.
+ * Information about a /refresh/melt operation in a coin transaction history.
+ */
+struct TALER_EXCHANGEDB_RefreshMeltListEntry
+{
+
+  /**
+   * Signature over the melting operation.
+   */
+  struct TALER_CoinSpendSignatureP coin_sig;
+
+  /**
+   * Refresh commitment this coin is melted into.
+   */
+  struct TALER_RefreshCommitmentP rc;
+
+  /**
+   * How much value is being melted?  This amount includes the fees,
+   * so the final amount contributed to the melt is this value minus
+   * the fee for melting the coin.  We include the fee in what is
+   * being signed so that we can verify a reserve's remaining total
+   * balance without needing to access the respective denomination key
+   * information each time.
+   */
+  struct TALER_Amount amount_with_fee;
+
+  /**
+   * Melt fee the exchange charged.
+   */
+  struct TALER_Amount melt_fee;
+
+  /**
+   * Index (smaller #TALER_CNC_KAPPA) which the exchange has chosen to not
+   * have revealed during cut and choose.
+   */
+  uint32_t noreveal_index;
+
+};
+
+
+/**
+ * Information about a /refresh/melt operation.
  */
 struct TALER_EXCHANGEDB_RefreshMelt
 {
@@ -744,39 +923,39 @@ struct TALER_EXCHANGEDB_TransactionList
      * Details if transaction was a /deposit operation.
      * (#TALER_EXCHANGEDB_TT_DEPOSIT)
      */
-    struct TALER_EXCHANGEDB_Deposit *deposit;
+    struct TALER_EXCHANGEDB_DepositListEntry *deposit;
 
     /**
      * Details if transaction was a /refresh/melt operation.
      * (#TALER_EXCHANGEDB_TT_REFRESH_MELT)
      */
-    struct TALER_EXCHANGEDB_RefreshMelt *melt;
+    struct TALER_EXCHANGEDB_RefreshMeltListEntry *melt;
 
     /**
      * Details if transaction was a /refund operation.
      * (#TALER_EXCHANGEDB_TT_REFUND)
      */
-    struct TALER_EXCHANGEDB_Refund *refund;
+    struct TALER_EXCHANGEDB_RefundListEntry *refund;
 
     /**
      * Details if transaction was a /payback-refund operation where
      * this coin was the OLD coin.
      * (#TALER_EXCHANGEDB_TT_OLD_COIN_PAYBACK).
      */
-    struct TALER_EXCHANGEDB_PaybackRefresh *old_coin_payback;
+    struct TALER_EXCHANGEDB_PaybackRefreshListEntry *old_coin_payback;
 
     /**
      * Details if transaction was a /payback operation.
      * (#TALER_EXCHANGEDB_TT_PAYBACK)
      */
-    struct TALER_EXCHANGEDB_Payback *payback;
+    struct TALER_EXCHANGEDB_PaybackListEntry *payback;
 
     /**
      * Details if transaction was a /payback-refund operation where
      * this coin was the REFRESHED coin.
      * (#TALER_EXCHANGEDB_TT_PAYBACK_REFRESH)
      */
-    struct TALER_EXCHANGEDB_PaybackRefresh *payback_refresh;
+    struct TALER_EXCHANGEDB_PaybackRefreshListEntry *payback_refresh;
 
   } details;
 
@@ -1790,7 +1969,10 @@ struct TALER_EXCHANGEDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to the database
-   * @param deposit the deposit to check
+   * @param coin_pub the coin to check for deposit
+   * @param merchant_pub merchant to receive the deposit
+   * @param h_contract_terms contract terms of the deposit
+   * @param h_wire hash of the merchant's wire details
    * @return #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if is is marked done,
    *         #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if not,
    *         otherwise transaction error status (incl. deposit unknown)
@@ -1798,7 +1980,10 @@ struct TALER_EXCHANGEDB_Plugin
   enum GNUNET_DB_QueryStatus
   (*test_deposit_done)(void *cls,
                        struct TALER_EXCHANGEDB_Session *session,
-                       const struct TALER_EXCHANGEDB_Deposit *deposit);
+                       const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                       const struct TALER_MerchantPublicKeyP *merchant_pub,
+                       const struct GNUNET_HashCode *h_contract_terms,
+                       const struct GNUNET_HashCode *h_wire);
 
 
   /**

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

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