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: implement check_tra


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: implement check_transaction_history()
Date: Sun, 19 Mar 2017 06:50:11 +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 424b327  implement check_transaction_history()
424b327 is described below

commit 424b327395a403464ab32d056b780ba761a44770
Author: Christian Grothoff <address@hidden>
AuthorDate: Sun Mar 19 06:50:08 2017 +0100

    implement check_transaction_history()
---
 src/auditor/taler-auditor.c | 201 ++++++++++++++++++++++++++++++++------------
 1 file changed, 147 insertions(+), 54 deletions(-)

diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 1dd9a87..c6b0fbf 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -23,9 +23,6 @@
  *   the wire transfers from the bank. This needs to be checked separately!
  * - Similarly, we do not check that the outgoing wire transfers match those
  *   given in the 'wire_out' table. This needs to be checked separately!
- *
- * TODO:
- * - FIXME: do proper transaction history check in #check_transaction_history()
  */
 #include "platform.h"
 #include <gnunet/gnunet_util_lib.h>
@@ -2002,16 +1999,17 @@ struct WireCheckContext
 
 /**
  * Check coin's transaction history for plausibility.  Does NOT check
- * the signatures (those are checked independently), but does check
- * that the amounts add up to the picture claimed by the aggregation table.
+ * the signatures (those are checked independently), but does calculate
+ * the amounts for the aggregation table and checks that the total
+ * claimed coin value is within the value of the coin's denomination.
  *
  * @param coin_pub public key of the coin (for reporting)
  * @param h_proposal_data hash of the proposal for which we calculate the 
amount
  * @param merchant_pub public key of the merchant (who is allowed to issue 
refunds)
  * @param dki denomination information about the coin
  * @param tl_head head of transaction history to verify
- * @param[out] final amount the coin contributes to the transaction
- * @param[out] final fees the exchange charged for the transaction
+ * @param[out] merchant_gain amount the coin contributes to the wire transfer 
to the merchant
+ * @param[out] merchant_fees fees the exchange charged the merchant for the 
transaction(s)
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
  */
 static int
@@ -2020,12 +2018,14 @@ check_transaction_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
                            const struct TALER_MerchantPublicKeyP *merchant_pub,
                            const struct 
TALER_EXCHANGEDB_DenominationKeyInformationP *dki,
                            const struct TALER_EXCHANGEDB_TransactionList 
*tl_head,
-                           struct TALER_Amount *final_expenditures,
-                           struct TALER_Amount *final_fees)
+                           struct TALER_Amount *merchant_gain,
+                           struct TALER_Amount *merchant_fees)
 {
   struct TALER_Amount expenditures;
   struct TALER_Amount refunds;
-  struct TALER_Amount fees;
+  struct TALER_Amount spent;
+  struct TALER_Amount value;
+  struct TALER_Amount merchant_loss;
 
   GNUNET_assert (NULL != tl_head);
   TALER_amount_get_zero (currency,
@@ -2033,16 +2033,22 @@ check_transaction_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
   TALER_amount_get_zero (currency,
                          &refunds);
   TALER_amount_get_zero (currency,
-                         &fees);
+                         merchant_gain);
+  TALER_amount_get_zero (currency,
+                         merchant_fees);
+  TALER_amount_get_zero (currency,
+                         &merchant_loss);
+  /* Go over transaction history to compute totals; note that we do not
+     know the order, so instead of subtracting we compute positive
+     (deposit, melt) and negative (refund) values separately here,
+     and then subtract the negative from the positive after the loop. */
   for (const struct TALER_EXCHANGEDB_TransactionList *tl = tl_head;NULL != 
tl;tl = tl->next)
   {
     const struct TALER_Amount *amount_with_fee;
     const struct TALER_Amount *fee;
     const struct TALER_AmountNBO *fee_dki;
-    struct TALER_Amount *add_to;
     struct TALER_Amount tmp;
 
-    add_to = NULL;
     // FIXME:
     // - for refunds/deposits that apply to this merchant and this contract
     //   we need to update the total expenditures/refunds/fees
@@ -2053,80 +2059,167 @@ check_transaction_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
       amount_with_fee = &tl->details.deposit->amount_with_fee;
       fee = &tl->details.deposit->deposit_fee;
       fee_dki = &dki->properties.fee_deposit;
-      add_to = &expenditures;
+      if (GNUNET_OK !=
+          TALER_amount_add (&expenditures,
+                            &expenditures,
+                            amount_with_fee))
+      {
+        GNUNET_break (0);
+        return GNUNET_SYSERR;
+      }
+      /* Check if this deposit is within the remit of the aggregation
+         we are investigating, if so, include it in the totals. */
+      if ( (0 == memcmp (merchant_pub,
+                         &tl->details.deposit->merchant_pub,
+                         sizeof (struct TALER_MerchantPublicKeyP))) &&
+           (0 == memcmp (h_proposal_data,
+                         &tl->details.deposit->h_proposal_data,
+                         sizeof (struct GNUNET_HashCode))) )
+      {
+        struct TALER_Amount amount_without_fee;
+
+        if (GNUNET_OK !=
+            TALER_amount_subtract (&amount_without_fee,
+                                   amount_with_fee,
+                                   fee))
+        {
+          GNUNET_break (0);
+          return GNUNET_SYSERR;
+        }
+        if (GNUNET_OK !=
+            TALER_amount_add (merchant_gain,
+                              merchant_gain,
+                              &amount_without_fee))
+        {
+          GNUNET_break (0);
+          return GNUNET_SYSERR;
+        }
+        if (GNUNET_OK !=
+            TALER_amount_add (merchant_fees,
+                              merchant_fees,
+                              fee))
+        {
+          GNUNET_break (0);
+          return GNUNET_SYSERR;
+        }
+      }
       break;
     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
       amount_with_fee = &tl->details.melt->amount_with_fee;
       fee = &tl->details.melt->melt_fee;
       fee_dki = &dki->properties.fee_refresh;
-      add_to = &expenditures;
+      if (GNUNET_OK !=
+          TALER_amount_add (&expenditures,
+                            &expenditures,
+                            amount_with_fee))
+      {
+        GNUNET_break (0);
+        return GNUNET_SYSERR;
+      }
       break;
     case TALER_EXCHANGEDB_TT_REFUND:
       amount_with_fee = &tl->details.refund->refund_amount;
       fee = &tl->details.refund->refund_fee;
       fee_dki = &dki->properties.fee_refund;
-      add_to = &refunds;
-      // FIXME: where do we check that the refund(s)
-      // of the coin match the deposit(s) of the coin (by merchant, timestamp, 
etc.)?
+      if (GNUNET_OK !=
+          TALER_amount_add (&refunds,
+                            &refunds,
+                            amount_with_fee))
+      {
+        GNUNET_break (0);
+        return GNUNET_SYSERR;
+      }
+      if (GNUNET_OK !=
+          TALER_amount_add (&expenditures,
+                            &expenditures,
+                            fee))
+      {
+        GNUNET_break (0);
+        return GNUNET_SYSERR;
+      }
+      /* Check if this refund is within the remit of the aggregation
+         we are investigating, if so, include it in the totals. */
+      if ( (0 == memcmp (merchant_pub,
+                         &tl->details.refund->merchant_pub,
+                         sizeof (struct TALER_MerchantPublicKeyP))) &&
+           (0 == memcmp (h_proposal_data,
+                         &tl->details.refund->h_proposal_data,
+                         sizeof (struct GNUNET_HashCode))) )
+      {
+        if (GNUNET_OK !=
+            TALER_amount_add (&merchant_loss,
+                              &merchant_loss,
+                              amount_with_fee))
+        {
+          GNUNET_break (0);
+          return GNUNET_SYSERR;
+        }
+        if (GNUNET_OK !=
+            TALER_amount_add (merchant_fees,
+                              merchant_fees,
+                              fee))
+        {
+          GNUNET_break (0);
+          return GNUNET_SYSERR;
+        }
+      }
       break;
     }
-    GNUNET_assert (NULL != add_to); /* check switch was exhaustive */
-    if (GNUNET_OK !=
-        TALER_amount_add (add_to,
-                          add_to,
-                          amount_with_fee))
-    {
-      /* overflow in history already!? inconceivable! Bad DB! */
-      GNUNET_break (0);
-      report_coin_inconsistency (coin_pub,
-                                 add_to,
-                                 amount_with_fee,
-                                 "could not add coin's contribution to total");
-      return GNUNET_SYSERR;
-    }
+
+    /* Check that the fees given in the transaction list and in dki match */
     TALER_amount_ntoh (&tmp,
                        fee_dki);
     if (0 !=
         TALER_amount_cmp (&tmp,
                           fee))
     {
-      /* Disagreement in fee structure within DB! */
-      GNUNET_break (0);
-      report_coin_inconsistency (coin_pub,
-                                 &tmp,
-                                 fee,
-                                 "coin's fee in transaction and in 
denomination data differ");
-      return GNUNET_SYSERR;
-    }
-    if (GNUNET_OK !=
-        TALER_amount_add (&fees,
-                          &fees,
-                          fee))
-    {
-      /* overflow in fee total? inconceivable! Bad DB! */
+      /* Disagreement in fee structure within DB, should be impossible! */
       GNUNET_break (0);
-      report_coin_inconsistency (coin_pub,
-                                 fee,
-                                 &fees,
-                                 "could not add coin's fee to total fees");
       return GNUNET_SYSERR;
     }
   } /* for 'tl' */
 
-  /* Finally, calculate total balance change, i.e. expenditures minus refunds 
*/
+  /* Calculate total balance change, i.e. expenditures minus refunds */
   if (GNUNET_SYSERR ==
-      TALER_amount_subtract (final_expenditures,
+      TALER_amount_subtract (&spent,
                              &expenditures,
                              &refunds))
   {
-    /* refunds above expenditures? inconceivable! Bad DB! */
-    GNUNET_break (0);
+    /* refunds above expenditures? Bad! */
     report_coin_inconsistency (coin_pub,
                                &expenditures,
                                &refunds,
                                "could not subtract refunded amount from 
expenditures");
     return GNUNET_SYSERR;
   }
+
+  /* Now check that 'spent' is less or equal than total coin value */
+  TALER_amount_ntoh (&value,
+                     &dki->properties.value);
+  if (1 == TALER_amount_cmp (&spent,
+                             &value))
+  {
+    /* spent > value */
+    report_coin_inconsistency (coin_pub,
+                               &spent,
+                               &value,
+                               "accepted deposits (minus refunds) exceeds 
denomination value");
+    return GNUNET_SYSERR;
+  }
+
+  /* Finally, update @a merchant_gain by subtracting what he "lost" from 
refunds */
+  if (GNUNET_SYSERR ==
+      TALER_amount_subtract (merchant_gain,
+                             merchant_gain,
+                             &merchant_loss))
+  {
+    /* refunds above deposits? Bad! */
+    report_coin_inconsistency (coin_pub,
+                               merchant_gain,
+                               &merchant_loss,
+                               "merchant was granted more refunds than he 
deposited");
+    return GNUNET_SYSERR;
+  }
   return GNUNET_OK;
 }
 

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



reply via email to

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