gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated (87a8d2d2 -> d7cfb11f)


From: gnunet
Subject: [taler-exchange] branch master updated (87a8d2d2 -> d7cfb11f)
Date: Sun, 15 Mar 2020 00:56:00 +0100

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

grothoff pushed a change to branch master
in repository exchange.

    from 87a8d2d2 remove unused code
     new d292b8ed code cleanup and additional error checking logic for #6124, 
but no actual semantic change
     new b3a52548 Merge branch 'master' of git+ssh://git.taler.net/exchange
     new f8095d72 fix shutdown logic of test
     new d7cfb11f fix new ag logic

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 doc/prebuilt                                  |  2 +-
 src/exchange/taler-exchange-aggregator.c      | 31 ++++++++++++--------
 src/exchange/taler-exchange-httpd_responses.c | 42 ++++++++++++++++++---------
 src/exchange/taler-exchange-httpd_withdraw.c  | 31 +++++++++++++-------
 src/include/taler_error_codes.h               |  7 +++++
 src/testing/test_taler_exchange_aggregator.c  | 32 +++++++++++++++-----
 6 files changed, 100 insertions(+), 45 deletions(-)

diff --git a/doc/prebuilt b/doc/prebuilt
index ca53235c..934a6a18 160000
--- a/doc/prebuilt
+++ b/doc/prebuilt
@@ -1 +1 @@
-Subproject commit ca53235ccfa0458ebf11c204888ca370e20ec3f5
+Subproject commit 934a6a18301e81c4fd1b3a8cda2dc13dca4741cc
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index c3b94b3d..c44d0f70 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -523,8 +523,9 @@ aggregate_cb (void *cls,
               const json_t *wire)
 {
   struct AggregationUnit *au = cls;
-  struct TALER_Amount delta;
+  struct TALER_Amount old;
   enum GNUNET_DB_QueryStatus qs;
+  struct TALER_Amount delta;
 
   /* NOTE: potential optimization: use custom SQL API to not
      fetch these: */
@@ -541,12 +542,16 @@ aggregate_cb (void *cls,
     return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
   }
 
-  /* compute contribution of this coin after fees */
   /* add to total */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Adding transaction amount %s from row %llu to aggregation\n",
               TALER_amount2s (amount_with_fee),
               (unsigned long long) row_id);
+  /* save the existing total aggregate in 'old', for later */
+  old = au->total_amount;
+  /* we begin with the total contribution of the current coin */
+  au->total_amount = *amount_with_fee;
+  /* compute contribution of this coin (after fees) */
   au->have_refund = GNUNET_NO;
   qs = db_plugin->select_refunds_by_coin (db_plugin->cls,
                                           au->session,
@@ -562,43 +567,45 @@ aggregate_cb (void *cls,
   }
   if (GNUNET_NO == au->have_refund)
   {
+    struct TALER_Amount tmp;
+
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Subtracting deposit fee %s for non-refunded coin\n",
                 TALER_amount2s (deposit_fee));
     if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&delta,
-                               amount_with_fee,
+        TALER_amount_subtract (&tmp,
+                               &au->total_amount,
                                deposit_fee))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Fatally malformed record at %llu over amount %s (deposit 
fee exceeds deposited value)\n",
                   (unsigned long long) row_id,
                   TALER_amount2s (&au->total_amount));
+      GNUNET_assert (GNUNET_OK ==
+                     TALER_amount_get_zero (old.currency,
+                                            &au->total_amount));
     }
     else
     {
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_get_zero (au->total_amount.currency,
-                                            &delta));
+      au->total_amount = tmp;
     }
   }
-  else
-  {
-    delta = *amount_with_fee;
-  }
 
+  /* now add the au->total_amount with the (remaining) contribution of
+     the current coin to the 'old' value with the current aggregate value */
   {
     struct TALER_Amount tmp;
 
     if (GNUNET_OK !=
         TALER_amount_add (&tmp,
                           &au->total_amount,
-                          &delta))
+                          &old))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                   "Overflow or currency incompatibility during aggregation at 
%llu\n",
                   (unsigned long long) row_id);
       /* Skip this one, but keep going! */
+      au->total_amount = old;
       return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
     }
     au->total_amount = tmp;
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 0e7704e4..e2a20243 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -433,10 +433,13 @@ TEH_RESPONSE_reply_coin_insufficient_funds (struct 
MHD_Connection *connection,
   history = TEH_RESPONSE_compile_transaction_history (coin_pub,
                                                       tl);
   if (NULL == history)
+  {
+    GNUNET_break (0);
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_COIN_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
                                        "failed to convert transaction history 
to JSON");
+  }
   return TALER_MHD_reply_json_pack (connection,
                                     MHD_HTTP_CONFLICT,
                                     "{s:s, s:I, s:o}",
@@ -462,10 +465,17 @@ TEH_RESPONSE_compile_reserve_history (const struct
   struct TALER_Amount deposit_total;
   struct TALER_Amount withdraw_total;
   json_t *json_history;
-  int ret;
+  enum InitAmounts
+  {
+    /** Nothing initialized */
+    IA_NONE = 0,
+    /** deposit_total initialized */
+    IA_DEPOSIT = 1,
+    /** withdraw_total initialized */
+    IA_WITHDRAW = 2
+  } init = IA_NONE;
 
   json_history = json_array ();
-  ret = 0;
   for (const struct TALER_EXCHANGEDB_ReserveHistory *pos = rh;
        NULL != pos;
        pos = pos->next)
@@ -473,8 +483,11 @@ TEH_RESPONSE_compile_reserve_history (const struct
     switch (pos->type)
     {
     case TALER_EXCHANGEDB_RO_BANK_TO_EXCHANGE:
-      if (0 == (1 & ret))
+      if (0 == (IA_DEPOSIT & init))
+      {
         deposit_total = pos->details.bank->amount;
+        init |= IA_DEPOSIT;
+      }
       else if (GNUNET_OK !=
                TALER_amount_add (&deposit_total,
                                  &deposit_total,
@@ -484,7 +497,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
         json_decref (json_history);
         return NULL;
       }
-      ret |= 1;
       if (0 !=
           json_array_append_new (json_history,
                                  json_pack ("{s:s, s:o, s:s, s:o, s:o}",
@@ -514,9 +526,10 @@ TEH_RESPONSE_compile_reserve_history (const struct
         struct TALER_Amount value;
 
         value = pos->details.withdraw->amount_with_fee;
-        if (0 == (2 & ret))
+        if (0 == (IA_WITHDRAW & init))
         {
           withdraw_total = value;
+          init |= IA_WITHDRAW;
         }
         else
         {
@@ -530,7 +543,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
             return NULL;
           }
         }
-        ret |= 2;
         if (0 !=
             json_array_append_new (json_history,
                                    json_pack ("{s:s, s:o, s:o, s:o, s:o, s:o}",
@@ -568,8 +580,11 @@ TEH_RESPONSE_compile_reserve_history (const struct
         struct TALER_ExchangeSignatureP sig;
 
         recoup = pos->details.recoup;
-        if (0 == (1 & ret))
+        if (0 == (IA_DEPOSIT & init))
+        {
           deposit_total = recoup->value;
+          init |= IA_DEPOSIT;
+        }
         else if (GNUNET_OK !=
                  TALER_amount_add (&deposit_total,
                                    &deposit_total,
@@ -579,7 +594,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
           json_decref (json_history);
           return NULL;
         }
-        ret |= 1;
         pc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_CONFIRM_RECOUP);
         pc.purpose.size = htonl (sizeof (struct TALER_RecoupConfirmationPS));
         pc.timestamp = GNUNET_TIME_absolute_hton (recoup->timestamp);
@@ -628,9 +642,10 @@ TEH_RESPONSE_compile_reserve_history (const struct
         struct TALER_Amount value;
 
         value = pos->details.closing->amount;
-        if (0 == (2 & ret))
+        if (0 == (IA_WITHDRAW & init))
         {
           withdraw_total = value;
+          init |= IA_WITHDRAW;
         }
         else
         {
@@ -644,7 +659,6 @@ TEH_RESPONSE_compile_reserve_history (const struct
             return NULL;
           }
         }
-        ret |= 2;
         rcc.purpose.purpose = htonl (TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED);
         rcc.purpose.size = htonl (sizeof (struct
                                           TALER_ReserveCloseConfirmationPS));
@@ -703,15 +717,17 @@ TEH_RESPONSE_compile_reserve_history (const struct
     }
   }
 
-  if (0 == (1 & ret))
+  if (0 == (IA_DEPOSIT & init))
   {
+    /* We should not have gotten here, without deposits no reserve
+       should exist! */
     GNUNET_break (0);
     json_decref (json_history);
     return NULL;
   }
-  if (0 == (2 & ret))
+  if (0 == (IA_WITHDRAW & init))
   {
-    /* did not encounter any withdraw operations, set to zero */
+    /* did not encounter any withdraw operations, set withdraw_total to zero */
     GNUNET_assert (GNUNET_OK ==
                    TALER_amount_get_zero (deposit_total.currency,
                                           &withdraw_total));
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c 
b/src/exchange/taler-exchange-httpd_withdraw.c
index ddb543c8..1abf1932 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -44,33 +44,40 @@
 /**
  * Send reserve status information to client with the
  * message that we have insufficient funds for the
- * requested /reserve/withdraw operation.
+ * requested withdraw operation.
  *
  * @param connection connection to the client
+ * @param ebalance expected balance based on our database
  * @param rh reserve history to return
  * @return MHD result code
  */
 static int
 reply_reserve_withdraw_insufficient_funds (struct MHD_Connection *connection,
+                                           const struct TALER_Amount *ebalance,
                                            const struct
                                            TALER_EXCHANGEDB_ReserveHistory *rh)
 {
-  json_t *json_balance;
   json_t *json_history;
   struct TALER_Amount balance;
 
   json_history = TEH_RESPONSE_compile_reserve_history (rh,
                                                        &balance);
-  if ((NULL == json_history)
-      /* Address the case where the ptr is not null, but
-       * it fails "internally" to dump as string (= corrupted).  */
-      || (0 == json_dumpb (json_history, NULL, 0, 0)))
+  if (NULL == json_history)
     return TALER_MHD_reply_with_error (connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_WITHDRAW_HISTORY_DB_ERROR_INSUFFICIENT_FUNDS,
                                        "balance calculation failure");
-  json_balance = TALER_JSON_from_amount (&balance);
-
+  if (0 !=
+      TALER_amount_cmp (&balance,
+                        ebalance))
+  {
+    GNUNET_break (0);
+    json_decref (json_history);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                       
TALER_EC_WITHDRAW_HISTORY_RESERVE_BALANCE_CORRUPT,
+                                       "internal balance inconsistency error");
+  }
   return TALER_MHD_reply_json_pack (connection,
                                     MHD_HTTP_CONFLICT,
                                     "{s:s, s:I, s:o, s:o}",
@@ -78,7 +85,8 @@ reply_reserve_withdraw_insufficient_funds (struct 
MHD_Connection *connection,
                                     "code",
                                     (json_int_t)
                                     TALER_EC_WITHDRAW_INSUFFICIENT_FUNDS,
-                                    "balance", json_balance,
+                                    "balance", TALER_JSON_from_amount (
+                                      &balance),
                                     "history", json_history);
 }
 
@@ -285,6 +293,7 @@ withdraw_transaction (void *cls,
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
     *mhd_ret = reply_reserve_withdraw_insufficient_funds (connection,
+                                                          &r.balance,
                                                           rh);
     TEH_plugin->free_reserve_history (TEH_plugin->cls,
                                       rh);
@@ -455,7 +464,7 @@ TEH_RESERVE_handler_reserve_withdraw (const struct 
TEH_RequestHandler *rh,
                                   &wc.wsrd.reserve_pub.eddsa_pub))
   {
     TALER_LOG_WARNING (
-      "Client supplied invalid signature for /reserve/withdraw request\n");
+      "Client supplied invalid signature for withdraw request\n");
     GNUNET_JSON_parse_free (spec);
     TEH_KS_release (wc.key_state);
     return TALER_MHD_reply_with_error (connection,
@@ -484,7 +493,7 @@ TEH_RESERVE_handler_reserve_withdraw (const struct 
TEH_RequestHandler *rh,
 
   if (GNUNET_OK !=
       TEH_DB_run_transaction (connection,
-                              "run reserve withdraw",
+                              "run withdraw",
                               &mhd_ret,
                               &withdraw_transaction,
                               &wc))
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index f485f2da..e6bd7364 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -381,6 +381,13 @@ enum TALER_ErrorCode
    */
   TALER_EC_DENOMINATION_KEY_LOST = 1116,
 
+  /**
+   * The exchange's database entry with the reserve balance summary
+   * is inconsistent with its own history of the reserve.
+   * Returned with an HTTP status of #MHD_HTTP_INTERNAL_SERVER_ERROR.
+   */
+  TALER_EC_WITHDRAW_HISTORY_RESERVE_BALANCE_CORRUPT = 1117,
+
   /**
    * The exchange failed to obtain the transaction history of the given
    * reserve from the database. This response is provided with HTTP
diff --git a/src/testing/test_taler_exchange_aggregator.c 
b/src/testing/test_taler_exchange_aggregator.c
index 66cdecff..fe96d635 100644
--- a/src/testing/test_taler_exchange_aggregator.c
+++ b/src/testing/test_taler_exchange_aggregator.c
@@ -71,6 +71,24 @@ static char *config_filename;
   TALER_TESTING_cmd_exec_transfer (label "-transfer", cfg_fn)
 
 
+/**
+ * Function run on shutdown to unload the DB plugin.
+ *
+ * @param cls NULL
+ */
+static void
+unload_db (void *cls)
+{
+  (void) cls;
+  if (NULL != dbc.plugin)
+  {
+    dbc.plugin->drop_tables (dbc.plugin->cls);
+    TALER_EXCHANGEDB_plugin_unload (dbc.plugin);
+    dbc.plugin = NULL;
+  }
+}
+
+
 /**
  * Collects all the tests.
  */
@@ -431,6 +449,8 @@ run (void *cls,
     TALER_TESTING_cmd_end ()
   };
 
+  GNUNET_SCHEDULER_add_shutdown (&unload_db,
+                                 NULL);
   TALER_TESTING_run_with_fakebank (is,
                                    all,
                                    bc.exchange_auth.wire_gateway_url);
@@ -473,8 +493,6 @@ prepare_database (void *cls,
                                 cfg,
                                 NULL, // no exchange process handle.
                                 GNUNET_NO); // do not try to connect to the 
exchange
-
-
   return GNUNET_OK;
 }
 
@@ -524,18 +542,16 @@ main (int argc,
     return 77;
   }
 
-  if (GNUNET_OK != GNUNET_CONFIGURATION_parse_and_run (config_filename,
-                                                       &prepare_database,
-                                                       NULL))
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_parse_and_run (config_filename,
+                                          &prepare_database,
+                                          NULL))
   {
     TALER_LOG_WARNING ("Could not prepare database for tests.\n");
     return result;
   }
-
   GNUNET_free (config_filename);
   GNUNET_free (testname);
-  dbc.plugin->drop_tables (dbc.plugin->cls);
-  TALER_EXCHANGEDB_plugin_unload (dbc.plugin);
   return GNUNET_OK == result ? 0 : 1;
 }
 

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



reply via email to

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