gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated: more work on audito


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: more work on auditor, towards coin/denomination key checks
Date: Wed, 15 Mar 2017 19:28:07 +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 6b5bfc5  more work on auditor, towards coin/denomination key checks
6b5bfc5 is described below

commit 6b5bfc57b59cd98cdbec74eabd61ee177659328f
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Mar 15 19:28:05 2017 +0100

    more work on auditor, towards coin/denomination key checks
---
 src/auditor/taler-auditor.c                 | 320 ++++++++++++++++++++++++++--
 src/exchangedb/plugin_exchangedb_postgres.c |   7 +-
 src/include/taler_exchangedb_plugin.h       |  14 +-
 3 files changed, 318 insertions(+), 23 deletions(-)

diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index b4bd376..b9edcf6 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -46,6 +46,16 @@
 
 
 /**
+ * How many coin histories do we keep in RAM at any given point in
+ * time? Used bound memory consumption of the auditor. Larger values
+ * reduce database accesses.
+ *
+ * Set to a VERY low value here for testing. Practical values may be
+ * in the millions.
+ */
+#define MAX_COIN_SUMMARIES 4
+
+/**
  * Return value from main().
  */
 static int global_ret;
@@ -202,9 +212,9 @@ static struct GNUNET_CONTAINER_MultiHashMap *denominations;
  * Obtain information about a @a denom_pub.
  *
  * @param denom_pub key to look up
- * @param[out] set to the hash of @a denom_pub, may be NULL
  * @param[out] dki set to detailed information about @a denom_pub, NULL if not 
found, must
  *                 NOT be freed by caller
+ * @param[out] dh set to the hash of @a denom_pub, may be NULL
  * @return #GNUNET_OK on success, #GNUNET_NO for not found, #GNUNET_SYSERR for 
DB error
  */
 static int
@@ -566,7 +576,7 @@ handle_reserve_out (void *cls,
   }
   if (GNUNET_NO == ret)
   {
-    report_row_inconsistency ("reserve_out",
+    report_row_inconsistency ("withdraw",
                               rowid,
                               "denomination key not found (foreign key 
constraint violated)");
     return GNUNET_OK;
@@ -578,7 +588,7 @@ handle_reserve_out (void *cls,
   if ( (valid_start.abs_value_us > execution_date.abs_value_us) ||
        (expire_withdraw.abs_value_us < execution_date.abs_value_us) )
   {
-    report_row_minor_inconsistency ("reserve_out",
+    report_row_minor_inconsistency ("withdraw",
                                     rowid,
                                     "denomination key not valid at time of 
withdrawal");
   }
@@ -596,9 +606,9 @@ handle_reserve_out (void *cls,
                                   &reserve_sig->eddsa_signature,
                                   &reserve_pub->eddsa_pub))
   {
-    report_row_inconsistency ("reserve_out",
+    report_row_inconsistency ("withdraw",
                               rowid,
-                              "invalid signature for reserve withdrawal");
+                              "invalid signature for withdrawal");
     return GNUNET_OK;
   }
 
@@ -917,7 +927,12 @@ struct CoinSummary
   /**
    * Denomination of the coin with fee structure.
    */
-  struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
+  const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
+
+  /**
+   * Hash of @e coin_pub.
+   */
+  struct GNUNET_HashCode coin_hash;
 
   /**
    * Public key of the coin.
@@ -925,10 +940,9 @@ struct CoinSummary
   struct TALER_CoinSpendPublicKeyP coin_pub;
 
   /**
-   * Total value lost of the coin (deposits, refreshs and fees minus refunds).
-   * Must be smaller than the coin's total (origional) value.
+   * List of transactions this coin was involved in.
    */
-  struct TALER_Amount spent;
+  struct TALER_EXCHANGEDB_TransactionList *tl;
 
 };
 
@@ -999,6 +1013,13 @@ struct CoinContext
   struct GNUNET_CONTAINER_MultiHashMap *coins;
 
   /**
+   * Array of the coins in @e coins.  Used to expire coins
+   * in a circular ring-buffer like fashion (to keep the
+   * working set in @e coins bounded).
+   */
+  struct CoinSummary summaries[MAX_COIN_SUMMARIES];
+
+  /**
    * Map for tracking information about denominations.
    */
   struct GNUNET_CONTAINER_MultiHashMap *denominations;
@@ -1029,6 +1050,11 @@ struct CoinContext
    */
   struct TALER_Amount risk;
 
+  /**
+   * Current write/replace offset in the circular @e summaries buffer.
+   */
+  unsigned int summaries_off;
+
 };
 
 
@@ -1178,6 +1204,114 @@ sync_denomination (void *cls,
 
 
 /**
+ * Release memory occupied by a coin summary.  Note that
+ * the actual @a value is NOT allocated (comes from the
+ * ring buffer), only the members of the struct need to be
+ * freed.
+ *
+ * @param cls the `struct CoinContext`
+ * @param key the hash of the coin's public key
+ * @param value a `struct DenominationSummary`
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+free_coin (void *cls,
+           const struct GNUNET_HashCode *denom_hash,
+           void *value)
+{
+  struct CoinContext *cc = cls;
+  struct CoinSummary *cs = value;
+
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (cc->coins,
+                                                       &cs->coin_hash,
+                                                       cs));
+  edb->free_coin_transaction_list (edb->cls,
+                                   cs->tl);
+  cs->tl = NULL;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Obtain information about the coin from the cache or the database.
+ *
+ * @param cc caching information
+ * @param coin_pub public key of the coin to get information about
+ * @return NULL on error
+ */
+static struct CoinSummary *
+get_coin_summary (struct CoinContext *cc,
+                  const struct TALER_CoinSpendPublicKeyP *coin_pub)
+{
+  struct CoinSummary *cs;
+  struct GNUNET_HashCode chash;
+  struct TALER_EXCHANGEDB_TransactionList *tl;
+  const struct TALER_CoinPublicInfo *coin;
+
+  GNUNET_CRYPTO_hash (coin_pub,
+                      sizeof (*coin_pub),
+                      &chash);
+  cs = GNUNET_CONTAINER_multihashmap_get (cc->coins,
+                                          &chash);
+  if (NULL != cs)
+    return cs; /* cache hit */
+  tl = edb->get_coin_transactions (edb->cls,
+                                   esession,
+                                   coin_pub);
+  if (NULL == tl)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  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->coin;
+    break;
+  case TALER_EXCHANGEDB_TT_REFUND:
+    coin = &tl->details.refund->coin;
+    break;
+  }
+  GNUNET_assert (NULL != coin); /* hard check that switch worked */
+  if (GNUNET_OK !=
+      get_denomination_info (&coin->denom_pub,
+                             &cs->dki,
+                             NULL))
+  {
+    GNUNET_break (0);
+    edb->free_coin_transaction_list (edb->cls,
+                                     tl);
+    return NULL;
+  }
+
+  /* allocate coin slot in ring buffer */
+  if (MAX_COIN_SUMMARIES >= cc->summaries_off)
+    cc->summaries_off = 0;
+  cs = &cc->summaries[cc->summaries_off++];
+  GNUNET_assert (GNUNET_OK ==
+                 free_coin (cc,
+                            &cs->coin_hash,
+                            cs));
+
+  /* initialize 'cs' and add to cache */
+  cs->coin_pub = *coin_pub;
+  cs->coin_hash = chash;
+  cs->tl = tl;
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_put (cc->coins,
+                                                    &cs->coin_hash,
+                                                    cs,
+                                                    
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  return cs;
+}
+
+
+/**
  * Function called with details about all withdraw operations.
  *
  * @param cls our `struct CoinContext`
@@ -1186,7 +1320,7 @@ sync_denomination (void *cls,
  * @param denom_pub public denomination key of the deposited coin
  * @param denom_sig signature over the deposited coin
  * @param reserve_pub public key of the reserve
- * @param reserve_sig signature over the withdraw operation
+ * @param reserve_sig signature over the withdraw operation (verified 
elsewhere)
  * @param execution_date when did the wallet withdraw the coin
  * @param amount_with_fee amount that was withdrawn
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
@@ -1218,11 +1352,168 @@ withdraw_cb (void *cls,
   ds = get_denomination_summary (cc,
                                  &dh);
   // FIXME: use ds, dki, etc.
+  // FIXME: update 'cc'
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about coins that were melted,
+ * with the goal of auditing the refresh's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refresh session in our DB
+ * @param coin_pub public key of the coin
+ * @param coin_sig signature from the coin
+ * @param amount_with_fee amount that was deposited including fee
+ * @param num_newcoins how many coins were issued
+ * @param noreveal_index which index was picked by the exchange in 
cut-and-choose
+ * @param session_hash what is the session hash
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static int
+refresh_session_cb (void *cls,
+                    uint64_t rowid,
+                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
+                    const struct TALER_CoinSpendSignatureP *coin_sig,
+                    const struct TALER_Amount *amount_with_fee,
+                    uint16_t num_newcoins,
+                    uint16_t noreveal_index,
+                    const struct GNUNET_HashCode *session_hash)
+{
+  struct CoinContext *cc = cls;
+  struct TALER_RefreshMeltCoinAffirmationPS rmc;
+  struct CoinSummary *cs;
+  const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
+
+  cs = get_coin_summary (cc,
+                         coin_pub);
+  if (NULL == cs)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  dki = cs->dki;
+  rmc.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_MELT);
+  rmc.purpose.size = htonl (sizeof (rmc));
+  rmc.session_hash = *session_hash;
+  TALER_amount_hton (&rmc.amount_with_fee,
+                     amount_with_fee);
+  rmc.melt_fee = dki->properties.fee_refresh;
+  rmc.coin_pub = *coin_pub;
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_MELT,
+                                  &rmc.purpose,
+                                  &coin_sig->eddsa_signature,
+                                  &coin_pub->eddsa_pub))
+  {
+    report_row_inconsistency ("melt",
+                              rowid,
+                              "invalid signature for coin melt");
+    return GNUNET_OK;
+  }
+
+  // TODO: update risk, denomination outstanding amounts, etc.
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about deposits that have been made,
+ * with the goal of auditing the deposit's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param merchant_pub public key of the merchant
+ * @param coin_pub public key of the coin
+ * @param coin_sig signature from the coin
+ * @param amount_with_fee amount that was deposited including fee
+ * @param h_proposal_data hash of the proposal data known to merchant and 
customer
+ * @param refund_deadline by which the merchant adviced that he might want
+ *        to get a refund
+ * @param wire_deadline by which the merchant adviced that he would like the
+ *        wire transfer to be executed
+ * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
+ * @param done flag set if the deposit was already executed (or not)
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static int
+deposit_cb (void *cls,
+            uint64_t rowid,
+            const struct TALER_MerchantPublicKeyP *merchant_pub,
+            const struct TALER_CoinSpendPublicKeyP *coin_pub,
+            const struct TALER_CoinSpendSignatureP *coin_sig,
+            const struct TALER_Amount *amount_with_fee,
+            const struct GNUNET_HashCode *h_proposal_data,
+            struct GNUNET_TIME_Absolute refund_deadline,
+            struct GNUNET_TIME_Absolute wire_deadline,
+            const json_t *receiver_wire_account,
+            int done)
+{
+  struct CoinContext *cc = cls;
+  struct CoinSummary *cs;
+  const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
+
+  cs = get_coin_summary (cc,
+                         coin_pub);
+  if (NULL == cs)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  dki = cs->dki;
+
+  // TODO: verify signature
+
+  // TODO: update expected amounts in 'cc'
   return GNUNET_OK;
 }
 
 
+/**
+ * Function called with details about coins that were refunding,
+ * with the goal of auditing the refund's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refund in our DB
+ * @param coin_pub public key of the coin
+ * @param merchant_pub public key of the merchant
+ * @param merchant_sig signature of the merchant
+ * @param h_proposal_data hash of the proposal data known to merchant and 
customer
+ * @param rtransaction_id refund transaction ID chosen by the merchant
+ * @param amount_with_fee amount that was deposited including fee
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static int
+refund_cb (void *cls,
+           uint64_t rowid,
+           const struct TALER_CoinSpendPublicKeyP *coin_pub,
+           const struct TALER_MerchantPublicKeyP *merchant_pub,
+           const struct TALER_MerchantSignatureP *merchant_sig,
+           const struct GNUNET_HashCode *h_proposal_data,
+           uint64_t rtransaction_id,
+           const struct TALER_Amount *amount_with_fee)
+{
+  struct CoinContext *cc = cls;
+  struct CoinSummary *cs;
+  const struct TALER_EXCHANGEDB_DenominationKeyInformationP *dki;
+
+  cs = get_coin_summary (cc,
+                         coin_pub);
+  if (NULL == cs)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  dki = cs->dki;
+
+  // TODO: verify signature
 
+  // TODO: update expected amounts in 'cc'
+  return GNUNET_OK;
+}
 
 
 /**
@@ -1301,7 +1592,7 @@ analyze_coins (void *cls)
       edb->select_refreshs_above_serial_id (edb->cls,
                                             esession,
                                             42LL, // FIXME
-                                            NULL, // FIXME
+                                            &refresh_session_cb,
                                             &cc))
   {
     // FIXME...
@@ -1312,7 +1603,7 @@ analyze_coins (void *cls)
       edb->select_deposits_above_serial_id (edb->cls,
                                             esession,
                                             42LL, // FIXME
-                                            NULL, // FIXME
+                                            &deposit_cb,
                                             &cc))
   {
     // FIXME...
@@ -1323,7 +1614,7 @@ analyze_coins (void *cls)
       edb->select_refunds_above_serial_id (edb->cls,
                                            esession,
                                            42LL, // FIXME
-                                           NULL, // FIXME
+                                           &refund_cb,
                                            &cc))
   {
     // FIXME...
@@ -1338,6 +1629,9 @@ analyze_coins (void *cls)
                                          &sync_denomination,
                                          &cc);
   GNUNET_CONTAINER_multihashmap_destroy (cc.denominations);
+  GNUNET_CONTAINER_multihashmap_iterate (cc.coins,
+                                         &free_coin,
+                                         &cc);
   GNUNET_CONTAINER_multihashmap_destroy (cc.coins);
 
   if (GNUNET_YES == rret)
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index e14e4aa..26d6b87 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -794,6 +794,7 @@ postgres_prepare (PGconn *db_conn)
            ",num_newcoins"
            ",noreveal_index"
            ",melt_serial_id"
+           ",session_hash"
            " FROM refresh_sessions"
            " WHERE melt_serial_id>=$1"
            " ORDER BY melt_serial_id ASC",
@@ -4832,6 +4833,7 @@ postgres_select_refreshs_above_serial_id (void *cls,
     uint16_t num_newcoins;
     uint16_t noreveal_index;
     uint64_t rowid;
+    struct GNUNET_HashCode session_hash;
 
     struct GNUNET_PQ_ResultSpec rs[] = {
       GNUNET_PQ_result_spec_auto_from_type ("old_coin_pub",
@@ -4846,6 +4848,8 @@ postgres_select_refreshs_above_serial_id (void *cls,
                                     &noreveal_index),
       GNUNET_PQ_result_spec_uint64 ("melt_serial_id",
                                     &rowid),
+      GNUNET_PQ_result_spec_auto_from_type ("session_hash",
+                                            &session_hash),
       GNUNET_PQ_result_spec_end
     };
     if (GNUNET_OK !=
@@ -4863,7 +4867,8 @@ postgres_select_refreshs_above_serial_id (void *cls,
         &coin_sig,
         &amount_with_fee,
         num_newcoins,
-        noreveal_index);
+        noreveal_index,
+        &session_hash);
     GNUNET_PQ_cleanup_result (rs);
   }
   PQclear (result);
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 2beb0e3..524025e 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -623,17 +623,12 @@ typedef int
  *
  * @param cls closure
  * @param rowid unique serial ID for the refresh session in our DB
- * @param merchant_pub public key of the merchant
  * @param coin_pub public key of the coin
  * @param coin_sig signature from the coin
  * @param amount_with_fee amount that was deposited including fee
- * @param h_proposal_data hash of the proposal data known to merchant and 
customer
- * @param refund_deadline by which the merchant adviced that he might want
- *        to get a refund
- * @param wire_deadline by which the merchant adviced that he would like the
- *        wire transfer to be executed
- * @param receiver_wire_account wire details for the merchant, NULL from 
iterate_matching_deposits()
- * @param done flag set if the deposit was already executed (or not)
+ * @param num_newcoins how many coins were issued
+ * @param noreveal_index which index was picked by the exchange in 
cut-and-choose
+ * @param session_hash what is the session hash
  * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
  */
 typedef int
@@ -643,7 +638,8 @@ typedef int
                                            const struct 
TALER_CoinSpendSignatureP *coin_sig,
                                            const struct TALER_Amount 
*amount_with_fee,
                                            uint16_t num_newcoins,
-                                           uint16_t noreveal_index);
+                                           uint16_t noreveal_index,
+                                           const struct GNUNET_HashCode 
*session_hash);
 
 
 /**

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



reply via email to

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