gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: fix #6170 and rest of #6164


From: gnunet
Subject: [taler-exchange] branch master updated: fix #6170 and rest of #6164
Date: Wed, 08 Apr 2020 23:52:04 +0200

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 84a40be0 fix #6170 and rest of #6164
84a40be0 is described below

commit 84a40be0bce66cda800de7891f758a0c69afc7fa
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Apr 8 23:52:01 2020 +0200

    fix #6170 and rest of #6164
---
 src/auditor/report-lib.c                           | 188 ++++++++++
 src/auditor/report-lib.h                           | 137 ++++++++
 src/auditor/taler-helper-auditor-aggregation.c     | 239 ++++---------
 src/auditor/taler-helper-auditor-coins.c           | 391 +++++++++------------
 src/auditor/taler-helper-auditor-deposits.c        |   7 +-
 src/auditor/taler-helper-auditor-reserves.c        | 191 +++++-----
 src/auditor/taler-helper-auditor-wire.c            | 141 ++++----
 src/benchmark/taler-exchange-benchmark.c           |   2 +-
 src/exchange/taler-exchange-aggregator.c           |  10 +-
 src/exchange/taler-exchange-httpd_deposit.c        |   4 +-
 src/exchange/taler-exchange-httpd_deposits_get.c   |   2 +-
 src/exchange/taler-exchange-httpd_melt.c           |   2 +-
 src/exchange/taler-exchange-httpd_recoup.c         |   2 +-
 .../taler-exchange-httpd_refreshes_reveal.c        |   4 +-
 src/exchange/taler-exchange-httpd_responses.c      |  12 +-
 src/exchange/taler-exchange-httpd_transfers_get.c  |   8 +-
 src/exchange/taler-exchange-httpd_withdraw.c       |   2 +-
 src/exchangedb/exchangedb_transactions.c           |  18 +-
 src/exchangedb/plugin_exchangedb_postgres.c        |  12 +-
 src/exchangedb/test_exchangedb.c                   |   6 +-
 src/include/taler_amount_lib.h                     |  54 ++-
 src/lib/exchange_api_common.c                      |  16 +-
 src/lib/exchange_api_deposit.c                     |   4 +-
 src/lib/exchange_api_melt.c                        |   2 +-
 src/lib/exchange_api_refresh_common.c              |   4 +-
 src/lib/exchange_api_transfers_get.c               |   6 +-
 src/lib/exchange_api_withdraw.c                    |   4 +-
 src/testing/testing_api_cmd_exec_closer.c          |   2 +-
 src/testing/testing_api_cmd_refresh.c              |   4 +-
 src/testing/testing_api_cmd_withdraw.c             |   2 +-
 src/util/amount.c                                  |  39 +-
 src/util/test_amount.c                             |  14 +-
 32 files changed, 853 insertions(+), 676 deletions(-)

diff --git a/src/auditor/report-lib.c b/src/auditor/report-lib.c
index 6baf6e8b..3074b579 100644
--- a/src/auditor/report-lib.c
+++ b/src/auditor/report-lib.c
@@ -417,6 +417,194 @@ test_master_present (void *cls,
 }
 
 
+/**
+ * Perform addition of amounts.  If the addition fails, logs
+ * a detailed error and calls exit() to terminate the process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_add().
+ *
+ * @param[out] sum where to store @a a1 + @a a2, set to "invalid" on overflow
+ * @param a1 first amount to add
+ * @param a2 second amount to add
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ */
+void
+TALER_ARL_amount_add_ (struct TALER_Amount *sum,
+                       const struct TALER_Amount *a1,
+                       const struct TALER_Amount *a2,
+                       const char *filename,
+                       const char *functionname,
+                       unsigned int line)
+{
+  enum TALER_AmountArithmeticResult aar;
+  const char *msg;
+  char *a2s;
+
+  aar = TALER_amount_add (sum,
+                          a1,
+                          a2);
+  if (aar >= 0)
+    return;
+  switch (aar)
+  {
+  case TALER_AAR_INVALID_RESULT_OVERFLOW:
+    msg =
+      "arithmetic overflow in amount addition (likely the database is corrupt, 
see manual)";
+    break;
+  case TALER_AAR_INVALID_NORMALIZATION_FAILED:
+    msg =
+      "normalization failed in amount addition (likely the database is 
corrupt, see manual)";
+    break;
+  case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
+    msg =
+      "incompatible currencies in amount addition (likely bad configuration 
and auditor code missing a sanity check, see manual)";
+    break;
+  default:
+    GNUNET_assert (0); /* should be impossible */
+  }
+  a2s = TALER_amount_to_string (a2);
+  fprintf (stderr,
+           "Aborting audit due to fatal error in function %s at %s:%d trying 
to add %s to %s: %s\n",
+           functionname,
+           filename,
+           line,
+           TALER_amount2s (a1),
+           a2s,
+           msg);
+  GNUNET_free (a2s);
+  exit (42);
+}
+
+
+/**
+ * Perform subtraction of amounts. If the subtraction fails, logs
+ * a detailed error and calls exit() to terminate the process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_subtract().
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ */
+void
+TALER_ARL_amount_subtract_ (struct TALER_Amount *diff,
+                            const struct TALER_Amount *a1,
+                            const struct TALER_Amount *a2,
+                            const char *filename,
+                            const char *functionname,
+                            unsigned int line)
+{
+  enum TALER_AmountArithmeticResult aar;
+  const char *msg;
+  char *a2s;
+
+  aar = TALER_amount_subtract (diff,
+                               a1,
+                               a2);
+  if (aar >= 0)
+    return;
+  switch (aar)
+  {
+  case TALER_AAR_INVALID_NEGATIVE_RESULT:
+    msg =
+      "negative result in amount subtraction (likely the database is corrupt, 
see manual)";
+    break;
+  case TALER_AAR_INVALID_NORMALIZATION_FAILED:
+    msg =
+      "normalization failed in amount subtraction (likely the database is 
corrupt, see manual)";
+    break;
+  case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
+    msg =
+      "currencies incompatible in amount subtraction (likely bad configuration 
and auditor code missing a sanity check, see manual)";
+    break;
+  default:
+    GNUNET_assert (0); /* should be impossible */
+  }
+  a2s = TALER_amount_to_string (a2);
+  fprintf (stderr,
+           "Aborting audit due to fatal error in function %s at %s:%d trying 
to subtract %s from %s: %s\n",
+           functionname,
+           filename,
+           line,
+           a2s,
+           TALER_amount2s (a1),
+           msg);
+  GNUNET_free (a2s);
+  exit (42);
+}
+
+
+/**
+ * Perform subtraction of amounts. Negative results should be signalled by the
+ * return value (leaving @a diff set to 'invalid'). If the subtraction fails
+ * for other reasons (currency missmatch, normalization failure), logs a
+ * detailed error and calls exit() to terminate the process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_subtract_neg().
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ * @return #TALER_ARL_SR_NEGATIVE if the result was negative (and @a diff is 
now invalid),
+ *         #TALER_ARL_SR_ZERO if the result was zero,
+ *         #TALER_ARL_SR_POSITIVE if the result is positive
+ */
+enum TALER_ARL_SubtractionResult
+TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff,
+                                const struct TALER_Amount *a1,
+                                const struct TALER_Amount *a2,
+                                const char *filename,
+                                const char *functionname,
+                                unsigned int line)
+{
+  enum TALER_AmountArithmeticResult aar;
+  const char *msg;
+  char *a2s;
+
+  aar = TALER_amount_subtract (diff,
+                               a1,
+                               a2);
+  switch (aar)
+  {
+  case TALER_AAR_RESULT_POSITIVE:
+    return TALER_ARL_SR_POSITIVE;
+  case TALER_AAR_RESULT_ZERO:
+    return TALER_ARL_SR_ZERO;
+  case TALER_AAR_INVALID_NEGATIVE_RESULT:
+    return TALER_ARL_SR_INVALID_NEGATIVE;
+  case TALER_AAR_INVALID_NORMALIZATION_FAILED:
+    msg =
+      "normalization failed in amount subtraction (likely the database is 
corrupt, see manual)";
+    break;
+  case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE:
+    msg =
+      "currencies incompatible in amount subtraction (likely bad configuration 
and auditor code missing a sanity check, see manual)";
+    break;
+  default:
+    GNUNET_assert (0); /* should be impossible */
+  }
+  a2s = TALER_amount_to_string (a2);
+  fprintf (stderr,
+           "Aborting audit due to fatal error in function %s at %s:%d trying 
to subtract %s from %s: %s\n",
+           functionname,
+           filename,
+           line,
+           a2s,
+           TALER_amount2s (a1),
+           msg);
+  GNUNET_free (a2s);
+  exit (42);
+}
+
+
 /**
  * Setup global variables based on configuration.
  *
diff --git a/src/auditor/report-lib.h b/src/auditor/report-lib.h
index 8176e740..eeb36f0a 100644
--- a/src/auditor/report-lib.h
+++ b/src/auditor/report-lib.h
@@ -152,6 +152,143 @@ typedef enum GNUNET_DB_QueryStatus
 (*TALER_ARL_Analysis)(void *cls);
 
 
+/**
+ * Perform addition of amounts.  If the addition fails, logs
+ * a detailed error and calls exit() to terminate the process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_add().
+ *
+ * @param[out] sum where to store @a a1 + @a a2, set to "invalid" on overflow
+ * @param a1 first amount to add
+ * @param a2 second amount to add
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ */
+void
+TALER_ARL_amount_add_ (struct TALER_Amount *sum,
+                       const struct TALER_Amount *a1,
+                       const struct TALER_Amount *a2,
+                       const char *filename,
+                       const char *functionname,
+                       unsigned int line);
+
+
+/**
+ * Perform addition of amounts.  If the addition fails, logs
+ * a detailed error and calls exit() to terminate the process (!).
+ *
+ * @param[out] sum where to store @a a1 + @a a2, set to "invalid" on overflow
+ * @param a1 first amount to add
+ * @param a2 second amount to add
+ */
+#define TALER_ARL_amount_add(sum,a1,a2) \
+  TALER_ARL_amount_add_ (sum, a1, a2, __FILE__, __FUNCTION__, __LINE__)
+
+
+/**
+ * Perform subtraction of amounts where the result "cannot" be negative. If the
+ * subtraction fails, logs a detailed error and calls exit() to terminate the
+ * process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_subtract().
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ */
+void
+TALER_ARL_amount_subtract_ (struct TALER_Amount *diff,
+                            const struct TALER_Amount *a1,
+                            const struct TALER_Amount *a2,
+                            const char *filename,
+                            const char *functionname,
+                            unsigned int line);
+
+
+/**
+ * Perform subtraction of amounts where the result "cannot" be negative. If
+ * the subtraction fails, logs a detailed error and calls exit() to terminate
+ * the process (!).
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ */
+#define TALER_ARL_amount_subtract(diff,a1,a2) \
+  TALER_ARL_amount_subtract_ (diff, a1, a2, __FILE__, __FUNCTION__, __LINE__)
+
+
+/**
+ * Possible outcomes of #TALER_ARL_amount_subtract_neg().
+ */
+enum TALER_ARL_SubtractionResult
+{
+  /**
+   * Note that in this case no actual result was computed.
+   */
+  TALER_ARL_SR_INVALID_NEGATIVE = -1,
+
+  /**
+   * The result of the subtraction is exactly zero.
+   */
+  TALER_ARL_SR_ZERO = 0,
+
+  /**
+   * The result of the subtraction is a positive value.
+   */
+  TALER_ARL_SR_POSITIVE = 1
+};
+
+
+/**
+ * Perform subtraction of amounts. Negative results should be signalled by the
+ * return value (leaving @a diff set to 'invalid'). If the subtraction fails
+ * for other reasons (currency missmatch, normalization failure), logs a
+ * detailed error and calls exit() to terminate the process (!).
+ *
+ * Do not call this function directly, use #TALER_ARL_amount_subtract_neg().
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ * @param filename where is the addition called
+ * @param functionname name of the function where the addition is called
+ * @param line line number of the addition
+ * @return #TALER_ARL_SR_NEGATIVE if the result was negative (and @a diff is 
now invalid),
+ *         #TALER_ARL_SR_ZERO if the result was zero,
+ *         #TALER_ARL_SR_POSITIVE if the result is positive
+ */
+enum TALER_ARL_SubtractionResult
+TALER_ARL_amount_subtract_neg_ (struct TALER_Amount *diff,
+                                const struct TALER_Amount *a1,
+                                const struct TALER_Amount *a2,
+                                const char *filename,
+                                const char *functionname,
+                                unsigned int line);
+
+
+/**
+ * Perform subtraction of amounts.  Negative results should be signalled by
+ * the return value (leaving @a diff set to 'invalid'). If the subtraction
+ * fails for other reasons (currency missmatch, normalization failure), logs a
+ * detailed error and calls exit() to terminate the process (!).
+ *
+ * @param[out] diff where to store (@a a1 - @a a2)
+ * @param a1 amount to subtract from
+ * @param a2 amount to subtract
+ * @return #TALER_ARL_SR_NEGATIVE if the result was negative (and @a diff is 
now invalid),
+ *         #TALER_ARL_SR_ZERO if the result was zero,
+ *         #TALER_ARL_SR_POSITIVE if the result is positive
+ */
+#define TALER_ARL_amount_subtract_neg(diff,a1,a2) \
+  TALER_ARL_amount_subtract_neg_ (diff, a1, a2, __FILE__, __FUNCTION__, \
+                                  __LINE__)
+
+
 /**
  * Initialize DB sessions and run the analysis.
  *
diff --git a/src/auditor/taler-helper-auditor-aggregation.c 
b/src/auditor/taler-helper-auditor-aggregation.c
index 09376a79..2a56971d 100644
--- a/src/auditor/taler-helper-auditor-aggregation.c
+++ b/src/auditor/taler-helper-auditor-aggregation.c
@@ -145,19 +145,17 @@ report_amount_arithmetic_inconsistency (
                             auditor))
   {
     /* exchange > auditor */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          exchange,
-                                          auditor));
+    TALER_ARL_amount_subtract (&delta,
+                               exchange,
+                               auditor);
   }
   else
   {
     /* auditor < exchange */
     profitable = -profitable;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          auditor,
-                                          exchange));
+    TALER_ARL_amount_subtract (&delta,
+                               auditor,
+                               exchange);
   }
   TALER_ARL_report (report_amount_arithmetic_inconsistencies,
                     json_pack ("{s:s, s:I, s:o, s:o, s:I}",
@@ -171,10 +169,9 @@ report_amount_arithmetic_inconsistency (
     target = (1 == profitable)
              ? &total_arithmetic_delta_plus
              : &total_arithmetic_delta_minus;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (target,
-                                     target,
-                                     &delta));
+    TALER_ARL_amount_add (target,
+                          target,
+                          &delta);
   }
 }
 
@@ -207,19 +204,17 @@ report_coin_arithmetic_inconsistency (
                             auditor))
   {
     /* exchange > auditor */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          exchange,
-                                          auditor));
+    TALER_ARL_amount_subtract (&delta,
+                               exchange,
+                               auditor);
   }
   else
   {
     /* auditor < exchange */
     profitable = -profitable;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          auditor,
-                                          exchange));
+    TALER_ARL_amount_subtract (&delta,
+                               auditor,
+                               exchange);
   }
   TALER_ARL_report (report_coin_inconsistencies,
                     json_pack ("{s:s, s:o, s:o, s:o, s:I}",
@@ -234,10 +229,9 @@ report_coin_arithmetic_inconsistency (
     target = (1 == profitable)
              ? &total_coin_delta_plus
              : &total_coin_delta_minus;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (target,
-                                     target,
-                                     &delta));
+    TALER_ARL_amount_add (target,
+                          target,
+                          &delta);
   }
 }
 
@@ -452,14 +446,9 @@ check_transaction_history_for_deposit (
       }
       amount_with_fee = &tl->details.deposit->amount_with_fee; /* according to 
exchange*/
       fee_claimed = &tl->details.deposit->deposit_fee; /* Fee according to 
exchange DB */
-      if (GNUNET_OK !=
-          TALER_amount_add (&expenditures,
+      TALER_ARL_amount_add (&expenditures,
                             &expenditures,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            amount_with_fee);
       /* Check if this deposit is within the remit of the aggregation
          we are investigating, if so, include it in the totals. */
       if ( (0 == GNUNET_memcmp (merchant_pub,
@@ -469,22 +458,12 @@ check_transaction_history_for_deposit (
       {
         struct TALER_Amount amount_without_fee;
 
-        if (GNUNET_OK !=
-            TALER_amount_subtract (&amount_without_fee,
+        TALER_ARL_amount_subtract (&amount_without_fee,
                                    amount_with_fee,
-                                   fee_claimed))
-        {
-          GNUNET_break (0);
-          return GNUNET_SYSERR;
-        }
-        if (GNUNET_OK !=
-            TALER_amount_add (merchant_gain,
+                                   fee_claimed);
+        TALER_ARL_amount_add (merchant_gain,
                               merchant_gain,
-                              &amount_without_fee))
-        {
-          GNUNET_break (0);
-          return GNUNET_SYSERR;
-        }
+                              &amount_without_fee);
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "Detected applicable deposit of %s\n",
                     TALER_amount2s (&amount_without_fee));
@@ -513,14 +492,9 @@ check_transaction_history_for_deposit (
     case TALER_EXCHANGEDB_TT_MELT:
       amount_with_fee = &tl->details.melt->amount_with_fee;
       fee_claimed = &tl->details.melt->melt_fee;
-      if (GNUNET_OK !=
-          TALER_amount_add (&expenditures,
+      TALER_ARL_amount_add (&expenditures,
                             &expenditures,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            amount_with_fee);
       /* Check that the fees given in the transaction list and in dki match */
       {
         struct TALER_Amount fee_expected;
@@ -543,22 +517,12 @@ check_transaction_history_for_deposit (
     case TALER_EXCHANGEDB_TT_REFUND:
       amount_with_fee = &tl->details.refund->refund_amount;
       fee_claimed = &tl->details.refund->refund_fee;
-      if (GNUNET_OK !=
-          TALER_amount_add (&refunds,
+      TALER_ARL_amount_add (&refunds,
                             &refunds,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
-      if (GNUNET_OK !=
-          TALER_amount_add (&expenditures,
+                            amount_with_fee);
+      TALER_ARL_amount_add (&expenditures,
                             &expenditures,
-                            fee_claimed))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            fee_claimed);
       /* Check if this refund is within the remit of the aggregation
          we are investigating, if so, include it in the totals. */
       if ( (0 == GNUNET_memcmp (merchant_pub,
@@ -569,14 +533,9 @@ check_transaction_history_for_deposit (
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                     "Detected applicable refund of %s\n",
                     TALER_amount2s (amount_with_fee));
-        if (GNUNET_OK !=
-            TALER_amount_add (&merchant_loss,
+        TALER_ARL_amount_add (&merchant_loss,
                               &merchant_loss,
-                              amount_with_fee))
-        {
-          GNUNET_break (0);
-          return GNUNET_SYSERR;
-        }
+                              amount_with_fee);
         /* If there is a refund, we give back the deposit fee */
         refund_deposit_fee = GNUNET_YES;
       }
@@ -604,40 +563,25 @@ check_transaction_history_for_deposit (
       /* We count recoups of refreshed coins like refunds for the dirty old
          coin, as they equivalently _increase_ the remaining value on the
          _old_ coin */
-      if (GNUNET_OK !=
-          TALER_amount_add (&refunds,
+      TALER_ARL_amount_add (&refunds,
                             &refunds,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            amount_with_fee);
       break;
     case TALER_EXCHANGEDB_TT_RECOUP:
       /* We count recoups of the coin as expenditures, as it
          equivalently decreases the remaining value of the recouped coin. */
       amount_with_fee = &tl->details.recoup->value;
-      if (GNUNET_OK !=
-          TALER_amount_add (&expenditures,
+      TALER_ARL_amount_add (&expenditures,
                             &expenditures,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            amount_with_fee);
       break;
     case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
       /* We count recoups of the coin as expenditures, as it
          equivalently decreases the remaining value of the recouped coin. */
       amount_with_fee = &tl->details.recoup_refresh->value;
-      if (GNUNET_OK !=
-          TALER_amount_add (&expenditures,
+      TALER_ARL_amount_add (&expenditures,
                             &expenditures,
-                            amount_with_fee))
-      {
-        GNUNET_break (0);
-        return GNUNET_SYSERR;
-      }
+                            amount_with_fee);
       break;
     }
   } /* for 'tl' */
@@ -654,22 +598,17 @@ check_transaction_history_for_deposit (
   {
     /* We had a /deposit operation AND a /refund operation,
        and should thus not charge the merchant the /deposit fee */
-    if (GNUNET_OK !=
-        TALER_amount_add (merchant_gain,
+    TALER_ARL_amount_add (merchant_gain,
                           merchant_gain,
-                          deposit_fee))
-    {
-      GNUNET_break (0);
-      return GNUNET_SYSERR;
-    }
+                          deposit_fee);
   }
   {
     struct TALER_Amount final_gain;
 
-    if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&final_gain,
-                               merchant_gain,
-                               &merchant_loss))
+    if (TALER_ARL_SR_INVALID_NEGATIVE ==
+        TALER_ARL_amount_subtract_neg (&final_gain,
+                                       merchant_gain,
+                                       &merchant_loss))
     {
       /* refunds above deposits? Bad! */
       report_coin_arithmetic_inconsistency ("refund (merchant)",
@@ -696,10 +635,10 @@ check_transaction_history_for_deposit (
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Subtracting refunds of %s from coin value loss\n",
               TALER_amount2s (&refunds));
-  if (GNUNET_SYSERR ==
-      TALER_amount_subtract (&spent,
-                             &expenditures,
-                             &refunds))
+  if (TALER_ARL_SR_INVALID_NEGATIVE ==
+      TALER_ARL_amount_subtract_neg (&spent,
+                                     &expenditures,
+                                     &refunds))
   {
     /* refunds above expenditures? Bad! */
     report_coin_arithmetic_inconsistency ("refund (balance)",
@@ -859,10 +798,9 @@ wire_transfer_information_cb (
                                  "loss", TALER_JSON_from_amount (coin_value),
                                  "coin_pub", GNUNET_JSON_from_data_auto (
                                    &coin.coin_pub)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_sig_loss,
-                                     &total_bad_sig_loss,
-                                     coin_value));
+    TALER_ARL_amount_add (&total_bad_sig_loss,
+                          &total_bad_sig_loss,
+                          coin_value);
     GNUNET_CRYPTO_rsa_signature_free (coin.denom_sig.rsa_signature);
     TALER_ARL_edb->free_coin_transaction_list (TALER_ARL_edb->cls,
                                                tl);
@@ -898,10 +836,10 @@ wire_transfer_information_cb (
   {
     struct TALER_Amount coin_value_without_fee;
 
-    if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&coin_value_without_fee,
-                               coin_value,
-                               deposit_fee))
+    if (TALER_ARL_SR_INVALID_NEGATIVE ==
+        TALER_ARL_amount_subtract_neg (&coin_value_without_fee,
+                                       coin_value,
+                                       deposit_fee))
     {
       wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
       report_amount_arithmetic_inconsistency (
@@ -949,15 +887,9 @@ wire_transfer_information_cb (
   {
     struct TALER_Amount res;
 
-    if (GNUNET_OK !=
-        TALER_amount_add (&res,
+    TALER_ARL_amount_add (&res,
                           &wcc->total_deposits,
-                          &computed_value))
-    {
-      GNUNET_break (0);
-      wcc->qs = GNUNET_DB_STATUS_HARD_ERROR;
-      return;
-    }
+                          &computed_value);
     wcc->total_deposits = res;
   }
 }
@@ -1177,10 +1109,10 @@ check_wire_out_cb (void *cls,
       /* If fee is unknown, we just assume the fee is zero */
       final_amount = wcc.total_deposits;
     }
-    else if (GNUNET_SYSERR ==
-             TALER_amount_subtract (&final_amount,
-                                    &wcc.total_deposits,
-                                    wire_fee))
+    else if (TALER_ARL_SR_INVALID_NEGATIVE ==
+             TALER_ARL_amount_subtract_neg (&final_amount,
+                                            &wcc.total_deposits,
+                                            wire_fee))
     {
       report_amount_arithmetic_inconsistency (
         "wire out (fee structure)",
@@ -1200,26 +1132,13 @@ check_wire_out_cb (void *cls,
                                          &TALER_ARL_currency_round_unit));
 
   /* Calculate the exchange's gain as the fees plus rounding differences! */
-  if (GNUNET_SYSERR ==
-      TALER_amount_subtract (&exchange_gain,
+  TALER_ARL_amount_subtract (&exchange_gain,
                              &wcc.total_deposits,
-                             &final_amount))
-  {
-    GNUNET_break (0);
-    ac->qs = GNUNET_DB_STATUS_HARD_ERROR;
-    return GNUNET_SYSERR;
-  }
-
+                             &final_amount);
   /* Sum up aggregation fees (we simply include the rounding gains) */
-  if (GNUNET_OK !=
-      TALER_amount_add (&total_aggregation_fee_income,
+  TALER_ARL_amount_add (&total_aggregation_fee_income,
                         &total_aggregation_fee_income,
-                        &exchange_gain))
-  {
-    GNUNET_break (0);
-    ac->qs = GNUNET_DB_STATUS_HARD_ERROR;
-    return GNUNET_SYSERR;
-  }
+                        &exchange_gain);
 
   /* Check that calculated amount matches actual amount */
   if (0 != TALER_amount_cmp (amount,
@@ -1231,26 +1150,22 @@ check_wire_out_cb (void *cls,
                               &final_amount))
     {
       /* amount > final_amount */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            amount,
-                                            &final_amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_wire_out_delta_plus,
-                                       &total_wire_out_delta_plus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 amount,
+                                 &final_amount);
+      TALER_ARL_amount_add (&total_wire_out_delta_plus,
+                            &total_wire_out_delta_plus,
+                            &delta);
     }
     else
     {
       /* amount < final_amount */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            &final_amount,
-                                            amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_wire_out_delta_minus,
-                                       &total_wire_out_delta_minus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 &final_amount,
+                                 amount);
+      TALER_ARL_amount_add (&total_wire_out_delta_minus,
+                            &total_wire_out_delta_minus,
+                            &delta);
     }
 
     TALER_ARL_report (report_wire_out_inconsistencies,
diff --git a/src/auditor/taler-helper-auditor-coins.c 
b/src/auditor/taler-helper-auditor-coins.c
index 8acc874c..9d5e6670 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -290,14 +290,12 @@ report_emergency_by_amount (
                                  issue->expire_deposit),
                                "value",
                                TALER_JSON_from_amount_nbo (&issue->value)));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&reported_emergency_risk_by_amount,
-                                   &reported_emergency_risk_by_amount,
-                                   risk));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&reported_emergency_loss,
-                                   &reported_emergency_loss,
-                                   loss));
+  TALER_ARL_amount_add (&reported_emergency_risk_by_amount,
+                        &reported_emergency_risk_by_amount,
+                        risk);
+  TALER_ARL_amount_add (&reported_emergency_loss,
+                        &reported_emergency_loss,
+                        loss);
 }
 
 
@@ -342,18 +340,15 @@ report_emergency_by_count (
                                  issue->expire_deposit),
                                "value",
                                TALER_JSON_from_amount_nbo (&issue->value)));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&reported_emergency_risk_by_count,
-                                   &reported_emergency_risk_by_count,
-                                   risk));
+  TALER_ARL_amount_add (&reported_emergency_risk_by_count,
+                        &reported_emergency_risk_by_count,
+                        risk);
   TALER_amount_ntoh (&denom_value,
                      &issue->value);
   for (uint64_t i = num_issued; i<num_known; i++)
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (
-                     &reported_emergency_loss_by_count,
-                     &reported_emergency_loss_by_count,
-                     &denom_value));
+    TALER_ARL_amount_add (&reported_emergency_loss_by_count,
+                          &reported_emergency_loss_by_count,
+                          &denom_value);
 
 }
 
@@ -388,19 +383,17 @@ report_amount_arithmetic_inconsistency (
                             auditor))
   {
     /* exchange > auditor */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          exchange,
-                                          auditor));
+    TALER_ARL_amount_subtract (&delta,
+                               exchange,
+                               auditor);
   }
   else
   {
     /* auditor < exchange */
     profitable = -profitable;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          auditor,
-                                          exchange));
+    TALER_ARL_amount_subtract (&delta,
+                               auditor,
+                               exchange);
   }
   TALER_ARL_report (report_amount_arithmetic_inconsistencies,
                     json_pack ("{s:s, s:I, s:o, s:o, s:I}",
@@ -414,10 +407,9 @@ report_amount_arithmetic_inconsistency (
     target = (1 == profitable)
              ? &total_arithmetic_delta_plus
              : &total_arithmetic_delta_minus;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (target,
-                                     target,
-                                     &delta));
+    TALER_ARL_amount_add (target,
+                          target,
+                          &delta);
   }
 }
 
@@ -495,51 +487,44 @@ check_coin_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
     {
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       /* spent += pos->amount_with_fee */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&spent,
-                                       &spent,
-                                       
&pos->details.deposit->amount_with_fee));
+      TALER_ARL_amount_add (&spent,
+                            &spent,
+                            &pos->details.deposit->amount_with_fee);
       deposit_fee = pos->details.deposit->deposit_fee;
       break;
     case TALER_EXCHANGEDB_TT_MELT:
       /* spent += pos->amount_with_fee */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&spent,
-                                       &spent,
-                                       &pos->details.melt->amount_with_fee));
+      TALER_ARL_amount_add (&spent,
+                            &spent,
+                            &pos->details.melt->amount_with_fee);
       break;
     case TALER_EXCHANGEDB_TT_REFUND:
       /* refunded += pos->refund_amount - pos->refund_fee */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&refunded,
-                                       &refunded,
-                                       &pos->details.refund->refund_amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&spent,
-                                       &spent,
-                                       &pos->details.refund->refund_fee));
+      TALER_ARL_amount_add (&refunded,
+                            &refunded,
+                            &pos->details.refund->refund_amount);
+      TALER_ARL_amount_add (&spent,
+                            &spent,
+                            &pos->details.refund->refund_fee);
       have_refund = GNUNET_YES;
       break;
     case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
       /* refunded += pos->value */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&refunded,
-                                       &refunded,
-                                       &pos->details.old_coin_recoup->value));
+      TALER_ARL_amount_add (&refunded,
+                            &refunded,
+                            &pos->details.old_coin_recoup->value);
       break;
     case TALER_EXCHANGEDB_TT_RECOUP:
       /* spent += pos->value */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&spent,
-                                       &spent,
-                                       &pos->details.recoup->value));
+      TALER_ARL_amount_add (&spent,
+                            &spent,
+                            &pos->details.recoup->value);
       break;
     case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
       /* spent += pos->value */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&spent,
-                                       &spent,
-                                       &pos->details.recoup_refresh->value));
+      TALER_ARL_amount_add (&spent,
+                            &spent,
+                            &pos->details.recoup_refresh->value);
       break;
     }
   }
@@ -547,16 +532,14 @@ check_coin_history (const struct 
TALER_CoinSpendPublicKeyP *coin_pub,
   if (have_refund)
   {
     /* If we gave any refund, also discount ONE deposit fee */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&refunded,
-                                     &refunded,
-                                     &deposit_fee));
+    TALER_ARL_amount_add (&refunded,
+                          &refunded,
+                          &deposit_fee);
   }
   /* total coin value = original value plus refunds */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total,
-                                   &refunded,
-                                   value));
+  TALER_ARL_amount_add (&total,
+                        &refunded,
+                        value);
   if (1 ==
       TALER_amount_cmp (&spent,
                         &total))
@@ -564,10 +547,9 @@ check_coin_history (const struct TALER_CoinSpendPublicKeyP 
*coin_pub,
     /* spent > total: bad */
     struct TALER_Amount loss;
 
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&loss,
-                                          &spent,
-                                          &total));
+    TALER_ARL_amount_subtract (&loss,
+                               &spent,
+                               &total);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Loss detected for coin %s - %s\n",
                 TALER_B2S (coin_pub),
@@ -844,10 +826,9 @@ sync_denomination (void *cls,
       /* The denomination expired and carried a balance; we can now
          book the remaining balance as profit, and reduce our risk
          exposure by the accumulated risk of the denomination. */
-      GNUNET_assert (GNUNET_SYSERR !=
-                     TALER_amount_subtract (&total_risk,
-                                            &total_risk,
-                                            &ds->denom_risk));
+      TALER_ARL_amount_subtract (&total_risk,
+                                 &total_risk,
+                                 &ds->denom_risk);
       /* If the above fails, our risk assessment is inconsistent!
          This is really, really bad (auditor-internal invariant
          would be violated). Hence we can "safely" assert.  If
@@ -1035,26 +1016,22 @@ withdraw_cb (void *cls,
               GNUNET_h2s (&dh),
               TALER_amount2s (&value));
   ds->num_issued++;
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&ds->denom_balance,
-                                   &ds->denom_balance,
-                                   &value));
+  TALER_ARL_amount_add (&ds->denom_balance,
+                        &ds->denom_balance,
+                        &value);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "New balance of denomination `%s' is %s\n",
               GNUNET_h2s (&dh),
               TALER_amount2s (&ds->denom_balance));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_escrow_balance,
-                                   &total_escrow_balance,
-                                   &value));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_risk,
-                                   &total_risk,
-                                   &value));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&ds->denom_risk,
-                                   &ds->denom_risk,
-                                   &value));
+  TALER_ARL_amount_add (&total_escrow_balance,
+                        &total_escrow_balance,
+                        &value);
+  TALER_ARL_amount_add (&total_risk,
+                        &total_risk,
+                        &value);
+  TALER_ARL_amount_add (&ds->denom_risk,
+                        &ds->denom_risk,
+                        &value);
   return GNUNET_OK;
 }
 
@@ -1220,11 +1197,9 @@ check_known_coin (const char *operation,
                                    loss_potential),
                                  "coin_pub", GNUNET_JSON_from_data_auto (
                                    coin_pub)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_sig_loss,
-                                     &total_bad_sig_loss,
-                                     loss_potential));
-
+    TALER_ARL_amount_add (&total_bad_sig_loss,
+                          &total_bad_sig_loss,
+                          loss_potential);
   }
   GNUNET_CRYPTO_rsa_signature_free (ci.denom_sig.rsa_signature);
   return qs;
@@ -1324,10 +1299,9 @@ refresh_session_cb (void *cls,
                                      amount_with_fee),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount_with_fee);
     }
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1367,10 +1341,9 @@ refresh_session_cb (void *cls,
                                      amount_with_fee),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_refresh_hanging,
-                                       &total_refresh_hanging,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&total_refresh_hanging,
+                            &total_refresh_hanging,
+                            amount_with_fee);
       return GNUNET_OK;
     }
     if (GNUNET_SYSERR == reveal_ctx.err)
@@ -1397,14 +1370,12 @@ refresh_session_cb (void *cls,
                          &reveal_ctx.new_issues[i]->fee_withdraw);
       TALER_amount_ntoh (&value,
                          &reveal_ctx.new_issues[i]->value);
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&refresh_cost,
-                                       &refresh_cost,
-                                       &fee));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&refresh_cost,
-                                       &refresh_cost,
-                                       &value));
+      TALER_ARL_amount_add (&refresh_cost,
+                            &refresh_cost,
+                            &fee);
+      TALER_ARL_amount_add (&refresh_cost,
+                            &refresh_cost,
+                            &value);
     }
 
     /* compute contribution of old coin */
@@ -1413,10 +1384,10 @@ refresh_session_cb (void *cls,
 
       TALER_amount_ntoh (&melt_fee,
                          &issue->fee_refresh);
-      if (GNUNET_OK !=
-          TALER_amount_subtract (&amount_without_fee,
-                                 amount_with_fee,
-                                 &melt_fee))
+      if (TALER_ARL_SR_POSITIVE !=
+          TALER_ARL_amount_subtract_neg (&amount_without_fee,
+                                         amount_with_fee,
+                                         &melt_fee))
       {
         /* Melt fee higher than contribution of melted coin; this makes
            no sense (exchange should never have accepted the operation) */
@@ -1469,26 +1440,22 @@ refresh_session_cb (void *cls,
                     GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
                     TALER_amount2s (&value));
         dsi->num_issued++;
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&dsi->denom_balance,
-                                         &dsi->denom_balance,
-                                         &value));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&dsi->denom_risk,
-                                         &dsi->denom_risk,
-                                         &value));
+        TALER_ARL_amount_add (&dsi->denom_balance,
+                              &dsi->denom_balance,
+                              &value);
+        TALER_ARL_amount_add (&dsi->denom_risk,
+                              &dsi->denom_risk,
+                              &value);
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                     "New balance of denomination `%s' is %s\n",
                     GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
                     TALER_amount2s (&dsi->denom_balance));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&total_escrow_balance,
-                                         &total_escrow_balance,
-                                         &value));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&total_risk,
-                                         &total_risk,
-                                         &value));
+        TALER_ARL_amount_add (&total_escrow_balance,
+                              &total_escrow_balance,
+                              &value);
+        TALER_ARL_amount_add (&total_risk,
+                              &total_risk,
+                              &value);
       }
     }
     GNUNET_free_non_null (reveal_ctx.new_issues);
@@ -1506,15 +1473,14 @@ refresh_session_cb (void *cls,
   }
   else
   {
-    if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&tmp,
-                               &dso->denom_balance,
-                               amount_with_fee))
+    if (TALER_ARL_SR_INVALID_NEGATIVE ==
+        TALER_ARL_amount_subtract_neg (&tmp,
+                                       &dso->denom_balance,
+                                       amount_with_fee))
     {
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&dso->denom_loss,
-                                       &dso->denom_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&dso->denom_loss,
+                            &dso->denom_loss,
+                            amount_with_fee);
       dso->report_emergency = GNUNET_YES;
     }
     else
@@ -1539,10 +1505,9 @@ refresh_session_cb (void *cls,
     }
     else
     {
-      GNUNET_assert (GNUNET_SYSERR !=
-                     TALER_amount_subtract (&total_escrow_balance,
-                                            &total_escrow_balance,
-                                            amount_with_fee));
+      TALER_ARL_amount_subtract (&total_escrow_balance,
+                                 &total_escrow_balance,
+                                 amount_with_fee);
     }
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "New balance of denomination `%s' after melt is %s\n",
@@ -1556,10 +1521,9 @@ refresh_session_cb (void *cls,
 
     TALER_amount_ntoh (&rfee,
                        &issue->fee_refresh);
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_melt_fee_income,
-                                     &total_melt_fee_income,
-                                     &rfee));
+    TALER_ARL_amount_add (&total_melt_fee_income,
+                          &total_melt_fee_income,
+                          &rfee);
   }
   return GNUNET_OK;
 }
@@ -1666,10 +1630,9 @@ deposit_cb (void *cls,
                                      amount_with_fee),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount_with_fee);
       return GNUNET_OK;
     }
     TALER_amount_hton (&dr.amount_with_fee,
@@ -1691,10 +1654,9 @@ deposit_cb (void *cls,
                                      amount_with_fee),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount_with_fee);
       return GNUNET_OK;
     }
   }
@@ -1718,15 +1680,14 @@ deposit_cb (void *cls,
   {
     struct TALER_Amount tmp;
 
-    if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&tmp,
-                               &ds->denom_balance,
-                               amount_with_fee))
+    if (TALER_ARL_SR_INVALID_NEGATIVE ==
+        TALER_ARL_amount_subtract_neg (&tmp,
+                                       &ds->denom_balance,
+                                       amount_with_fee))
     {
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&ds->denom_loss,
-                                       &ds->denom_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&ds->denom_loss,
+                            &ds->denom_loss,
+                            amount_with_fee);
       ds->report_emergency = GNUNET_YES;
     }
     else
@@ -1752,10 +1713,9 @@ deposit_cb (void *cls,
     }
     else
     {
-      GNUNET_assert (GNUNET_SYSERR !=
-                     TALER_amount_subtract (&total_escrow_balance,
-                                            &total_escrow_balance,
-                                            amount_with_fee));
+      TALER_ARL_amount_subtract (&total_escrow_balance,
+                                 &total_escrow_balance,
+                                 amount_with_fee);
     }
 
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1770,10 +1730,9 @@ deposit_cb (void *cls,
 
     TALER_amount_ntoh (&dfee,
                        &issue->fee_deposit);
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_deposit_fee_income,
-                                     &total_deposit_fee_income,
-                                     &dfee));
+    TALER_ARL_amount_add (&total_deposit_fee_income,
+                          &total_deposit_fee_income,
+                          &dfee);
   }
 
   return GNUNET_OK;
@@ -1862,20 +1821,19 @@ refund_cb (void *cls,
                                      amount_with_fee),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount_with_fee));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount_with_fee);
       return GNUNET_OK;
     }
   }
 
   TALER_amount_ntoh (&refund_fee,
                      &issue->fee_refund);
-  if (GNUNET_OK !=
-      TALER_amount_subtract (&amount_without_fee,
-                             amount_with_fee,
-                             &refund_fee))
+  if (TALER_ARL_SR_INVALID_NEGATIVE ==
+      TALER_ARL_amount_subtract_neg (&amount_without_fee,
+                                     amount_with_fee,
+                                     &refund_fee))
   {
     report_amount_arithmetic_inconsistency ("refund (fee)",
                                             rowid,
@@ -1903,32 +1861,27 @@ refund_cb (void *cls,
   }
   else
   {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&ds->denom_balance,
-                                     &ds->denom_balance,
-                                     &amount_without_fee));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&ds->denom_risk,
-                                     &ds->denom_risk,
-                                     &amount_without_fee));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_escrow_balance,
-                                     &total_escrow_balance,
-                                     &amount_without_fee));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_risk,
-                                     &total_risk,
-                                     &amount_without_fee));
+    TALER_ARL_amount_add (&ds->denom_balance,
+                          &ds->denom_balance,
+                          &amount_without_fee);
+    TALER_ARL_amount_add (&ds->denom_risk,
+                          &ds->denom_risk,
+                          &amount_without_fee);
+    TALER_ARL_amount_add (&total_escrow_balance,
+                          &total_escrow_balance,
+                          &amount_without_fee);
+    TALER_ARL_amount_add (&total_risk,
+                          &total_risk,
+                          &amount_without_fee);
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "New balance of denomination `%s' after refund is %s\n",
                 GNUNET_h2s (&issue->denom_hash),
                 TALER_amount2s (&ds->denom_balance));
   }
   /* update total refund fee balance */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_refund_fee_income,
-                                   &total_refund_fee_income,
-                                   &refund_fee));
+  TALER_ARL_amount_add (&total_refund_fee_income,
+                        &total_refund_fee_income,
+                        &refund_fee);
   return GNUNET_OK;
 }
 
@@ -1972,10 +1925,9 @@ check_recoup (struct CoinContext *cc,
                                  "loss", TALER_JSON_from_amount (amount),
                                  "coin_pub", GNUNET_JSON_from_data_auto (
                                    &coin->denom_pub_hash)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_sig_loss,
-                                     &total_bad_sig_loss,
-                                     amount));
+    TALER_ARL_amount_add (&total_bad_sig_loss,
+                          &total_bad_sig_loss,
+                          amount);
   }
   qs = TALER_ARL_get_denomination_info_by_hash (&coin->denom_pub_hash,
                                                 &issue);
@@ -2028,10 +1980,9 @@ check_recoup (struct CoinContext *cc,
                                    "loss", TALER_JSON_from_amount (amount),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      &coin->coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount);
       return GNUNET_OK;
     }
   }
@@ -2059,19 +2010,16 @@ check_recoup (struct CoinContext *cc,
                                    "loss", TALER_JSON_from_amount (amount),
                                    "coin_pub", GNUNET_JSON_from_data_auto (
                                      &coin->coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount);
     }
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&ds->denom_recoup,
-                                     &ds->denom_recoup,
-                                     amount));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_recoup_loss,
-                                     &total_recoup_loss,
-                                     amount));
+    TALER_ARL_amount_add (&ds->denom_recoup,
+                          &ds->denom_recoup,
+                          amount);
+    TALER_ARL_amount_add (&total_recoup_loss,
+                          &total_recoup_loss,
+                          amount);
   }
   return GNUNET_OK;
 }
@@ -2189,10 +2137,9 @@ recoup_refresh_cb (void *cls,
     }
     else
     {
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&dso->denom_balance,
-                                       &dso->denom_balance,
-                                       amount));
+      TALER_ARL_amount_add (&dso->denom_balance,
+                            &dso->denom_balance,
+                            amount);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "New balance of denomination `%s' after refresh-recoup is 
%s\n",
                   GNUNET_h2s (&issue->denom_hash),
diff --git a/src/auditor/taler-helper-auditor-deposits.c 
b/src/auditor/taler-helper-auditor-deposits.c
index 1b6a46f1..29155859 100644
--- a/src/auditor/taler-helper-auditor-deposits.c
+++ b/src/auditor/taler-helper-auditor-deposits.c
@@ -147,10 +147,9 @@ test_dc (void *cls,
   dcc->first_missed_coin_serial = GNUNET_MIN (dcc->first_missed_coin_serial,
                                               serial_id);
   dcc->missed_count++;
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&dcc->missed_amount,
-                                   &dcc->missed_amount,
-                                   &dc->amount_without_fee));
+  TALER_ARL_amount_add (&dcc->missed_amount,
+                        &dcc->missed_amount,
+                        &dc->amount_without_fee);
 }
 
 
diff --git a/src/auditor/taler-helper-auditor-reserves.c 
b/src/auditor/taler-helper-auditor-reserves.c
index 766a8fda..8879d495 100644
--- a/src/auditor/taler-helper-auditor-reserves.c
+++ b/src/auditor/taler-helper-auditor-reserves.c
@@ -174,19 +174,17 @@ report_amount_arithmetic_inconsistency (
                             auditor))
   {
     /* exchange > auditor */
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          exchange,
-                                          auditor));
+    TALER_ARL_amount_subtract (&delta,
+                               exchange,
+                               auditor);
   }
   else
   {
     /* auditor < exchange */
     profitable = -profitable;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_subtract (&delta,
-                                          auditor,
-                                          exchange));
+    TALER_ARL_amount_subtract (&delta,
+                               auditor,
+                               exchange);
   }
   TALER_ARL_report (report_amount_arithmetic_inconsistencies,
                     json_pack ("{s:s, s:I, s:o, s:o, s:I}",
@@ -200,10 +198,9 @@ report_amount_arithmetic_inconsistency (
     target = (1 == profitable)
              ? &total_arithmetic_delta_plus
              : &total_arithmetic_delta_minus;
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (target,
-                                     target,
-                                     &delta));
+    TALER_ARL_amount_add (target,
+                          target,
+                          &delta);
   }
 }
 
@@ -445,10 +442,9 @@ handle_reserve_in (void *cls,
   }
   else
   {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&rs->total_in,
-                                     &rs->total_in,
-                                     credit));
+    TALER_ARL_amount_add (&rs->total_in,
+                          &rs->total_in,
+                          credit);
     if (NULL == rs->sender_account)
       rs->sender_account = GNUNET_strdup (sender_account_details);
   }
@@ -571,10 +567,9 @@ handle_reserve_out (void *cls,
                                    amount_with_fee),
                                  "key_pub", GNUNET_JSON_from_data_auto (
                                    reserve_pub)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_sig_loss,
-                                     &total_bad_sig_loss,
-                                     amount_with_fee));
+    TALER_ARL_amount_add (&total_bad_sig_loss,
+                          &total_bad_sig_loss,
+                          amount_with_fee);
     return GNUNET_OK;   /* exit here, we cannot add this to the legitimate 
withdrawals */
   }
 
@@ -610,10 +605,9 @@ handle_reserve_out (void *cls,
   }
   else
   {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&rs->total_out,
-                                     &rs->total_out,
-                                     amount_with_fee));
+    TALER_ARL_amount_add (&rs->total_out,
+                          &rs->total_out,
+                          amount_with_fee);
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Reserve `%s' reduced by %s from withdraw\n",
@@ -624,10 +618,9 @@ handle_reserve_out (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Increasing withdraw profits by fee %s\n",
               TALER_amount2s (&withdraw_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&rs->total_fee,
-                                   &rs->total_fee,
-                                   &withdraw_fee));
+  TALER_ARL_amount_add (&rs->total_fee,
+                        &rs->total_fee,
+                        &withdraw_fee);
   return GNUNET_OK;
 }
 
@@ -697,10 +690,9 @@ handle_recoup_by_reserve (
                                    "loss", TALER_JSON_from_amount (amount),
                                    "key_pub", GNUNET_JSON_from_data_auto (
                                      &coin->coin_pub)));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_sig_loss,
-                                       &total_bad_sig_loss,
-                                       amount));
+      TALER_ARL_amount_add (&total_bad_sig_loss,
+                            &total_bad_sig_loss,
+                            amount);
     }
   }
 
@@ -725,10 +717,9 @@ handle_recoup_by_reserve (
       report_row_inconsistency ("recoup",
                                 rowid,
                                 "denomination key not in revocation set");
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_irregular_recoups,
-                                       &total_irregular_recoups,
-                                       amount));
+      TALER_ARL_amount_add (&total_irregular_recoups,
+                            &total_irregular_recoups,
+                            amount);
     }
     else
     {
@@ -774,10 +765,9 @@ handle_recoup_by_reserve (
                                  "loss", TALER_JSON_from_amount (amount),
                                  "key_pub", GNUNET_JSON_from_data_auto (
                                    &TALER_ARL_master_pub)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_sig_loss,
-                                     &total_bad_sig_loss,
-                                     amount));
+    TALER_ARL_amount_add (&total_bad_sig_loss,
+                          &total_bad_sig_loss,
+                          amount);
   }
 
   GNUNET_CRYPTO_hash (reserve_pub,
@@ -812,10 +802,9 @@ handle_recoup_by_reserve (
   }
   else
   {
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&rs->total_in,
-                                     &rs->total_in,
-                                     amount));
+    TALER_ARL_amount_add (&rs->total_in,
+                          &rs->total_in,
+                          amount);
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Additional /recoup value to for reserve `%s' of %s\n",
@@ -949,14 +938,12 @@ handle_reserve_closed (
   {
     struct TALER_Amount expected_fee;
 
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&rs->total_out,
-                                     &rs->total_out,
-                                     amount_with_fee));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&rs->total_fee,
-                                     &rs->total_fee,
-                                     closing_fee));
+    TALER_ARL_amount_add (&rs->total_out,
+                          &rs->total_out,
+                          amount_with_fee);
+    TALER_ARL_amount_add (&rs->total_fee,
+                          &rs->total_fee,
+                          closing_fee);
     /* verify closing_fee is correct! */
     if (GNUNET_OK !=
         get_closing_fee (receiver_account,
@@ -1025,25 +1012,22 @@ verify_reserve_balance (void *cls,
   ret = GNUNET_OK;
   /* Check our reserve summary balance calculation shows that
      the reserve balance is acceptable (i.e. non-negative) */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&balance,
-                                   &rs->total_in,
-                                   &rs->balance_at_previous_audit));
-  if (GNUNET_SYSERR ==
-      TALER_amount_subtract (&nbalance,
-                             &balance,
-                             &rs->total_out))
+  TALER_ARL_amount_add (&balance,
+                        &rs->total_in,
+                        &rs->balance_at_previous_audit);
+  if (TALER_ARL_SR_INVALID_NEGATIVE ==
+      TALER_ARL_amount_subtract_neg (&nbalance,
+                                     &balance,
+                                     &rs->total_out))
   {
     struct TALER_Amount loss;
 
-    GNUNET_assert (GNUNET_SYSERR !=
-                   TALER_amount_subtract (&loss,
-                                          &rs->total_out,
-                                          &balance));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_balance_insufficient_loss,
-                                     &total_balance_insufficient_loss,
-                                     &loss));
+    TALER_ARL_amount_subtract (&loss,
+                               &rs->total_out,
+                               &balance);
+    TALER_ARL_amount_add (&total_balance_insufficient_loss,
+                          &total_balance_insufficient_loss,
+                          &loss);
     TALER_ARL_report (report_reserve_balance_insufficient_inconsistencies,
                       json_pack ("{s:o, s:o}",
                                  "reserve_pub",
@@ -1095,26 +1079,22 @@ verify_reserve_balance (void *cls,
                                 &reserve.balance))
       {
         /* balance > reserve.balance */
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_subtract (&delta,
-                                              &nbalance,
-                                              &reserve.balance));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&total_balance_summary_delta_plus,
-                                         &total_balance_summary_delta_plus,
-                                         &delta));
+        TALER_ARL_amount_subtract (&delta,
+                                   &nbalance,
+                                   &reserve.balance);
+        TALER_ARL_amount_add (&total_balance_summary_delta_plus,
+                              &total_balance_summary_delta_plus,
+                              &delta);
       }
       else
       {
         /* balance < reserve.balance */
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_subtract (&delta,
-                                              &reserve.balance,
-                                              &nbalance));
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&total_balance_summary_delta_minus,
-                                         &total_balance_summary_delta_minus,
-                                         &delta));
+        TALER_ARL_amount_subtract (&delta,
+                                   &reserve.balance,
+                                   &nbalance);
+        TALER_ARL_amount_add (&total_balance_summary_delta_minus,
+                              &total_balance_summary_delta_minus,
+                              &delta);
       }
       TALER_ARL_report (report_reserve_balance_summary_wrong_inconsistencies,
                         json_pack ("{s:o, s:o, s:o}",
@@ -1147,10 +1127,9 @@ verify_reserve_balance (void *cls,
                                  &cfee))
       {
         /* remaining balance (according to us) exceeds closing fee */
-        GNUNET_assert (GNUNET_OK ==
-                       TALER_amount_add (&total_balance_reserve_not_closed,
-                                         &total_balance_reserve_not_closed,
-                                         &nbalance));
+        TALER_ARL_amount_add (&total_balance_reserve_not_closed,
+                              &total_balance_reserve_not_closed,
+                              &nbalance);
         TALER_ARL_report (report_reserve_not_closed_inconsistencies,
                           json_pack ("{s:o, s:o, s:o}",
                                      "reserve_pub",
@@ -1166,10 +1145,9 @@ verify_reserve_balance (void *cls,
     else
     {
       /* We failed to determine the closing fee, complain! */
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_balance_reserve_not_closed,
-                                       &total_balance_reserve_not_closed,
-                                       &nbalance));
+      TALER_ARL_amount_add (&total_balance_reserve_not_closed,
+                            &total_balance_reserve_not_closed,
+                            &nbalance);
       TALER_ARL_report (report_reserve_not_closed_inconsistencies,
                         json_pack ("{s:o, s:o, s:o, s:s}",
                                    "reserve_pub",
@@ -1190,25 +1168,22 @@ verify_reserve_balance (void *cls,
               "Reserve reserve `%s' made %s in withdraw fees\n",
               TALER_B2S (&rs->reserve_pub),
               TALER_amount2s (&rs->total_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&rs->a_withdraw_fee_balance,
-                                   &rs->a_withdraw_fee_balance,
-                                   &rs->total_fee));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_escrow_balance,
-                                   &total_escrow_balance,
-                                   &rs->total_in));
-  GNUNET_assert (GNUNET_YES ==
-                 TALER_amount_add (&total_withdraw_fee_income,
-                                   &total_withdraw_fee_income,
-                                   &rs->total_fee));
+  TALER_ARL_amount_add (&rs->a_withdraw_fee_balance,
+                        &rs->a_withdraw_fee_balance,
+                        &rs->total_fee);
+  TALER_ARL_amount_add (&total_escrow_balance,
+                        &total_escrow_balance,
+                        &rs->total_in);
+  TALER_ARL_amount_add (&total_withdraw_fee_income,
+                        &total_withdraw_fee_income,
+                        &rs->total_fee);
   {
     struct TALER_Amount r;
 
-    if (GNUNET_SYSERR ==
-        TALER_amount_subtract (&r,
-                               &total_escrow_balance,
-                               &rs->total_out))
+    if (TALER_ARL_SR_INVALID_NEGATIVE ==
+        TALER_ARL_amount_subtract_neg (&r,
+                                       &total_escrow_balance,
+                                       &rs->total_out))
     {
       /* We could not reduce our total balance, i.e. exchange allowed IN TOTAL 
(!)
          to be withdrawn more than it was IN TOTAL ever given (exchange balance
diff --git a/src/auditor/taler-helper-auditor-wire.c 
b/src/auditor/taler-helper-auditor-wire.c
index 59cb544a..9dfed13b 100644
--- a/src/auditor/taler-helper-auditor-wire.c
+++ b/src/auditor/taler-helper-auditor-wire.c
@@ -629,10 +629,9 @@ check_pending_rc (void *cls,
 
   (void) cls;
   (void) key;
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_closure_amount_lag,
-                                   &total_closure_amount_lag,
-                                   &rc->amount));
+  TALER_ARL_amount_add (&total_closure_amount_lag,
+                        &total_closure_amount_lag,
+                        &rc->amount);
   if ( (0 != rc->amount.value) ||
        (0 != rc->amount.fraction) )
     TALER_ARL_report (report_closure_lags,
@@ -835,10 +834,9 @@ wire_missing_cb (void *cls,
                  /* bool? */ int done)
 {
   (void) cls;
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_amount_lag,
-                                   &total_amount_lag,
-                                   amount));
+  TALER_ARL_amount_add (&total_amount_lag,
+                        &total_amount_lag,
+                        amount);
   if ( (GNUNET_YES == tiny) &&
        (0 > TALER_amount_cmp (amount,
                               &tiny_amount)) )
@@ -1001,10 +999,9 @@ wire_out_cb (void *cls,
                                    date),
                                  "diagnostic", "wire transfer not made (yet?)",
                                  "account_section", wa->section_name));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_amount_out_minus,
-                                     &total_bad_amount_out_minus,
-                                     amount));
+    TALER_ARL_amount_add (&total_bad_amount_out_minus,
+                          &total_bad_amount_out_minus,
+                          amount);
     return GNUNET_OK;
   }
   {
@@ -1029,10 +1026,9 @@ wire_out_cb (void *cls,
                                      date),
                                    "diagnostic", "recevier account mismatch",
                                    "account_section", wa->section_name));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_out_plus,
-                                       &total_bad_amount_out_plus,
-                                       &roi->details.amount));
+      TALER_ARL_amount_add (&total_bad_amount_out_plus,
+                            &total_bad_amount_out_plus,
+                            &roi->details.amount);
       TALER_ARL_report (report_wire_out_inconsistencies,
                         json_pack ("{s:I, s:o, s:o, s:o, s:o, s:s, s:s}",
                                    "row", (json_int_t) rowid,
@@ -1045,10 +1041,9 @@ wire_out_cb (void *cls,
                                      date),
                                    "diagnostic", "receiver account mismatch",
                                    "account_section", wa->section_name));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_out_minus,
-                                       &total_bad_amount_out_minus,
-                                       amount));
+      TALER_ARL_amount_add (&total_bad_amount_out_minus,
+                            &total_bad_amount_out_minus,
+                            amount);
       GNUNET_free (payto_uri);
       goto cleanup;
     }
@@ -1075,28 +1070,24 @@ wire_out_cb (void *cls,
       /* amount > roi->details.amount: wire transfer was smaller than it 
should have been */
       struct TALER_Amount delta;
 
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            amount,
-                                            &roi->details.amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_out_minus,
-                                       &total_bad_amount_out_minus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 amount,
+                                 &roi->details.amount);
+      TALER_ARL_amount_add (&total_bad_amount_out_minus,
+                            &total_bad_amount_out_minus,
+                            &delta);
     }
     else
     {
       /* roi->details.amount < amount: wire transfer was larger than it should 
have been */
       struct TALER_Amount delta;
 
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            &roi->details.amount,
-                                            amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_out_plus,
-                                       &total_bad_amount_out_plus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 &roi->details.amount,
+                                 amount);
+      TALER_ARL_amount_add (&total_bad_amount_out_plus,
+                            &total_bad_amount_out_plus,
+                            &delta);
     }
     goto cleanup;
   }
@@ -1217,10 +1208,9 @@ complain_out_not_found (void *cls,
                                wa->section_name,
                                "diagnostic",
                                "justification for wire transfer not found"));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_bad_amount_out_plus,
-                                   &total_bad_amount_out_plus,
-                                   &roi->details.amount));
+  TALER_ARL_amount_add (&total_bad_amount_out_plus,
+                        &total_bad_amount_out_plus,
+                        &roi->details.amount);
   return GNUNET_OK;
 }
 
@@ -1350,10 +1340,9 @@ history_debit_cb (void *cls,
     GNUNET_asprintf (&diagnostic,
                      "duplicate subject hash `%s'",
                      TALER_B2S (&roi->subject_hash));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_wire_format_amount,
-                                     &total_wire_format_amount,
-                                     &details->amount));
+    TALER_ARL_amount_add (&total_wire_format_amount,
+                          &total_wire_format_amount,
+                          &details->amount);
     TALER_ARL_report (report_wire_format_inconsistencies,
                       json_pack ("{s:o, s:I, s:s}",
                                  "amount", TALER_JSON_from_amount (
@@ -1540,10 +1529,9 @@ complain_in_not_found (void *cls,
                                "account", wa->section_name,
                                "diagnostic",
                                "incoming wire transfer claimed by exchange not 
found"));
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_add (&total_bad_amount_in_minus,
-                                   &total_bad_amount_in_minus,
-                                   &rii->details.amount));
+  TALER_ARL_amount_add (&total_bad_amount_in_minus,
+                        &total_bad_amount_in_minus,
+                        &rii->details.amount);
   return GNUNET_OK;
 }
 
@@ -1653,10 +1641,9 @@ history_credit_cb (void *cls,
                                  "timestamp", TALER_ARL_json_from_time_abs (
                                    rii->details.execution_date),
                                  "diagnostic", "wire subject does not match"));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_amount_in_minus,
-                                     &total_bad_amount_in_minus,
-                                     &rii->details.amount));
+    TALER_ARL_amount_add (&total_bad_amount_in_minus,
+                          &total_bad_amount_in_minus,
+                          &rii->details.amount);
     TALER_ARL_report (report_reserve_in_inconsistencies,
                       json_pack ("{s:I, s:I, s:o, s:o, s:o, s:o, s:s}",
                                  "row", (json_int_t) rii->rowid,
@@ -1672,10 +1659,9 @@ history_credit_cb (void *cls,
                                    details->execution_date),
                                  "diagnostic", "wire subject does not match"));
 
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_bad_amount_in_plus,
-                                     &total_bad_amount_in_plus,
-                                     &details->amount));
+    TALER_ARL_amount_add (&total_bad_amount_in_plus,
+                          &total_bad_amount_in_plus,
+                          &details->amount);
     goto cleanup;
   }
   if (0 != TALER_amount_cmp (&rii->details.amount,
@@ -1701,28 +1687,24 @@ history_credit_cb (void *cls,
       /* details->amount > rii->details.amount: wire transfer was larger than 
it should have been */
       struct TALER_Amount delta;
 
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            &details->amount,
-                                            &rii->details.amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_in_plus,
-                                       &total_bad_amount_in_plus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 &details->amount,
+                                 &rii->details.amount);
+      TALER_ARL_amount_add (&total_bad_amount_in_plus,
+                            &total_bad_amount_in_plus,
+                            &delta);
     }
     else
     {
       /* rii->details.amount < details->amount: wire transfer was smaller than 
it should have been */
       struct TALER_Amount delta;
 
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_subtract (&delta,
-                                            &rii->details.amount,
-                                            &details->amount));
-      GNUNET_assert (GNUNET_OK ==
-                     TALER_amount_add (&total_bad_amount_in_minus,
-                                       &total_bad_amount_in_minus,
-                                       &delta));
+      TALER_ARL_amount_subtract (&delta,
+                                 &rii->details.amount,
+                                 &details->amount);
+      TALER_ARL_amount_add (&total_bad_amount_in_minus,
+                            &total_bad_amount_in_minus,
+                            &delta);
     }
     goto cleanup;
   }
@@ -1737,10 +1719,9 @@ history_credit_cb (void *cls,
                                  "bank_row", (json_int_t) row_off,
                                  "reserve_pub", GNUNET_JSON_from_data_auto (
                                    &rii->details.reserve_pub)));
-    GNUNET_assert (GNUNET_OK ==
-                   TALER_amount_add (&total_missattribution_in,
-                                     &total_missattribution_in,
-                                     &rii->details.amount));
+    TALER_ARL_amount_add (&total_missattribution_in,
+                          &total_missattribution_in,
+                          &rii->details.amount);
   }
   if (details->execution_date.abs_value_us !=
       rii->details.execution_date.abs_value_us)
@@ -1867,10 +1848,10 @@ reserve_closed_cb (void *cls,
 
   (void) cls;
   rc = GNUNET_new (struct ReserveClosure);
-  if (GNUNET_SYSERR ==
-      TALER_amount_subtract (&rc->amount,
-                             amount_with_fee,
-                             closing_fee))
+  if (TALER_ARL_SR_INVALID_NEGATIVE ==
+      TALER_ARL_amount_subtract_neg (&rc->amount,
+                                     amount_with_fee,
+                                     closing_fee))
   {
     TALER_ARL_report (report_row_inconsistencies,
                       json_pack ("{s:s, s:I, s:o, s:o, s:o, s:s}",
diff --git a/src/benchmark/taler-exchange-benchmark.c 
b/src/benchmark/taler-exchange-benchmark.c
index 307b0f37..57fde430 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -338,7 +338,7 @@ run (void *cls,
                  TALER_string_to_amount (withdraw_fee_str,
                                          &withdraw_fee));
   for (unsigned int i = 0; i < howmany_coins; i++)
-    GNUNET_assert (GNUNET_OK ==
+    GNUNET_assert (0 <=
                    TALER_amount_add (&total_reserve_amount,
                                      &total_reserve_amount,
                                      &withdraw_fee));
diff --git a/src/exchange/taler-exchange-aggregator.c 
b/src/exchange/taler-exchange-aggregator.c
index da24a125..0b98a342 100644
--- a/src/exchange/taler-exchange-aggregator.c
+++ b/src/exchange/taler-exchange-aggregator.c
@@ -312,7 +312,7 @@ refund_by_coin_cb (void *cls,
               "Aggregator subtracts applicable refund of amount %s\n",
               TALER_amount2s (amount_with_fee));
   aux->have_refund = GNUNET_YES;
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&aux->total_amount,
                              &aux->total_amount,
                              amount_with_fee))
@@ -385,7 +385,7 @@ deposit_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Non-refunded transaction, subtracting deposit fee %s\n",
                 TALER_amount2s (deposit_fee));
-    if (GNUNET_SYSERR ==
+    if (0 >
         TALER_amount_subtract (&ntotal,
                                amount_with_fee,
                                deposit_fee))
@@ -571,7 +571,7 @@ aggregate_cb (void *cls,
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Subtracting deposit fee %s for non-refunded coin\n",
                 TALER_amount2s (deposit_fee));
-    if (GNUNET_SYSERR ==
+    if (0 >
         TALER_amount_subtract (&tmp,
                                &au->total_amount,
                                deposit_fee))
@@ -595,7 +595,7 @@ aggregate_cb (void *cls,
   {
     struct TALER_Amount tmp;
 
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_add (&tmp,
                           &au->total_amount,
                           &old))
@@ -782,7 +782,7 @@ run_aggregation (void *cls)
   /* Subtract wire transfer fee and round to the unit supported by the
      wire transfer method; Check if after rounding down, we still have
      an amount to transfer, and if not mark as 'tiny'. */
-  if ( (GNUNET_OK !=
+  if ( (0 >=
         TALER_amount_subtract (&au_active.final_amount,
                                &au_active.total_amount,
                                &au_active.wire_fee)) ||
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index ac854de6..d3439165 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -162,7 +162,7 @@ deposit_transaction (void *cls,
 
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "/deposit replay, accepting again!\n");
-    GNUNET_assert (GNUNET_OK ==
+    GNUNET_assert (0 <=
                    TALER_amount_subtract (&amount_without_fee,
                                           &deposit->amount_with_fee,
                                           &deposit->deposit_fee));
@@ -543,7 +543,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
     struct TALER_Amount amount_without_fee;
     int res;
 
-    GNUNET_assert (GNUNET_SYSERR !=
+    GNUNET_assert (0 <=
                    TALER_amount_subtract (&amount_without_fee,
                                           &deposit.amount_with_fee,
                                           &deposit.deposit_fee));
diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c 
b/src/exchange/taler-exchange-httpd_deposits_get.c
index f2b364ca..04d24f49 100644
--- a/src/exchange/taler-exchange-httpd_deposits_get.c
+++ b/src/exchange/taler-exchange-httpd_deposits_get.c
@@ -176,7 +176,7 @@ handle_wtid_data (void *cls,
     ctx->execution_time = execution_time;
     return;
   }
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&ctx->coin_delta,
                              coin_contribution,
                              coin_fee))
diff --git a/src/exchange/taler-exchange-httpd_melt.c 
b/src/exchange/taler-exchange-httpd_melt.c
index fab0f106..c08c9773 100644
--- a/src/exchange/taler-exchange-httpd_melt.c
+++ b/src/exchange/taler-exchange-httpd_melt.c
@@ -249,7 +249,7 @@ refresh_check_melt (struct MHD_Connection *connection,
   {
     struct TALER_Amount coin_residual;
 
-    GNUNET_assert (GNUNET_SYSERR !=
+    GNUNET_assert (0 <=
                    TALER_amount_subtract (&coin_residual,
                                           &spent,
                                           
&rmc->refresh_session.amount_with_fee));
diff --git a/src/exchange/taler-exchange-httpd_recoup.c 
b/src/exchange/taler-exchange-httpd_recoup.c
index ccb75622..a3014e78 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -242,7 +242,7 @@ recoup_transaction (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Recoup: coin value %s\n",
               TALER_amount2s (&pc->value));
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&pc->amount,
                              &pc->value,
                              &spent))
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 5b6ca2d3..da1b3eb9 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -436,11 +436,11 @@ refreshes_reveal_transaction (void *cls,
                          &rctx->dkis[i]->issue.properties.fee_withdraw);
       TALER_amount_ntoh (&value,
                          &rctx->dkis[i]->issue.properties.value);
-      if ( (GNUNET_OK !=
+      if ( (0 >
             TALER_amount_add (&total,
                               &fee_withdraw,
                               &value)) ||
-           (GNUNET_OK !=
+           (0 >
             TALER_amount_add (&refresh_cost,
                               &refresh_cost,
                               &total)) )
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 4ddd9cd8..3870db14 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -200,7 +200,7 @@ TEH_RESPONSE_compile_transaction_history (
           return NULL;
         }
 #endif
-        if (GNUNET_OK !=
+        if (0 >
             TALER_amount_subtract (&value,
                                    &refund->refund_amount,
                                    &refund->refund_fee))
@@ -481,7 +481,7 @@ TEH_RESPONSE_compile_reserve_history (
           credit_total = bank->amount;
           init |= IA_CREDIT;
         }
-        else if (GNUNET_OK !=
+        else if (0 >
                  TALER_amount_add (&credit_total,
                                    &credit_total,
                                    &bank->amount))
@@ -526,7 +526,7 @@ TEH_RESPONSE_compile_reserve_history (
         }
         else
         {
-          if (GNUNET_OK !=
+          if (0 >
               TALER_amount_add (&withdraw_total,
                                 &withdraw_total,
                                 &value))
@@ -572,7 +572,7 @@ TEH_RESPONSE_compile_reserve_history (
           credit_total = recoup->value;
           init |= IA_CREDIT;
         }
-        else if (GNUNET_OK !=
+        else if (0 >
                  TALER_amount_add (&credit_total,
                                    &credit_total,
                                    &recoup->value))
@@ -642,7 +642,7 @@ TEH_RESPONSE_compile_reserve_history (
         }
         else
         {
-          if (GNUNET_OK !=
+          if (0 >
               TALER_amount_add (&withdraw_total,
                                 &withdraw_total,
                                 &value))
@@ -724,7 +724,7 @@ TEH_RESPONSE_compile_reserve_history (
                    TALER_amount_get_zero (credit_total.currency,
                                           &withdraw_total));
   }
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (balance,
                              &credit_total,
                              &withdraw_total))
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c 
b/src/exchange/taler-exchange-httpd_transfers_get.c
index 4cc855d7..2aa9a5c9 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -314,7 +314,7 @@ handle_deposit_data (void *cls,
     ctx->exec_time = exec_time;
     ctx->wire_method = wire_method; /* captures the reference */
     ctx->is_valid = GNUNET_YES;
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_subtract (&ctx->total,
                                deposit_value,
                                deposit_fee))
@@ -343,7 +343,7 @@ handle_deposit_data (void *cls,
       return;
     }
     GNUNET_free (wire_method);
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_subtract (&delta,
                                deposit_value,
                                deposit_fee))
@@ -352,7 +352,7 @@ handle_deposit_data (void *cls,
       ctx->is_valid = GNUNET_SYSERR;
       return;
     }
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_add (&ctx->total,
                           &ctx->total,
                           &delta))
@@ -489,7 +489,7 @@ get_transfer_deposits (void *cls,
     }
     return qs;
   }
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_subtract (&ctx->total,
                              &ctx->total,
                              &ctx->wire_fee))
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c 
b/src/exchange/taler-exchange-httpd_withdraw.c
index 58ef97ba..152ebfbb 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -422,7 +422,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
                        &wc.dki->issue.properties.value);
     TALER_amount_ntoh (&fee_withdraw,
                        &wc.dki->issue.properties.fee_withdraw);
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_add (&wc.amount_required,
                           &amount,
                           &fee_withdraw))
diff --git a/src/exchangedb/exchangedb_transactions.c 
b/src/exchangedb/exchangedb_transactions.c
index ade7f9cf..7fe65d52 100644
--- a/src/exchangedb/exchangedb_transactions.c
+++ b/src/exchangedb/exchangedb_transactions.c
@@ -55,7 +55,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
     {
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       /* spent += pos->amount_with_fee */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&spent,
                             &spent,
                             &pos->details.deposit->amount_with_fee))
@@ -67,7 +67,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
       break;
     case TALER_EXCHANGEDB_TT_MELT:
       /* spent += pos->amount_with_fee */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&spent,
                             &spent,
                             &pos->details.melt->amount_with_fee))
@@ -78,7 +78,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
       break;
     case TALER_EXCHANGEDB_TT_REFUND:
       /* refunded += pos->refund_amount - pos->refund_fee */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&refunded,
                             &refunded,
                             &pos->details.refund->refund_amount))
@@ -86,7 +86,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
         GNUNET_break (0);
         return GNUNET_SYSERR;
       }
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&spent,
                             &spent,
                             &pos->details.refund->refund_fee))
@@ -98,7 +98,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
       break;
     case TALER_EXCHANGEDB_TT_OLD_COIN_RECOUP:
       /* refunded += pos->value */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&refunded,
                             &refunded,
                             &pos->details.old_coin_recoup->value))
@@ -109,7 +109,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
       break;
     case TALER_EXCHANGEDB_TT_RECOUP:
       /* spent += pos->value */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&spent,
                             &spent,
                             &pos->details.recoup->value))
@@ -120,7 +120,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
       break;
     case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
       /* spent += pos->value */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&spent,
                             &spent,
                             &pos->details.recoup_refresh->value))
@@ -134,7 +134,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
   if (have_refund)
   {
     /* If we gave any refund, also discount ONE deposit fee */
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_add (&refunded,
                           &refunded,
                           &deposit_fee))
@@ -144,7 +144,7 @@ TALER_EXCHANGEDB_calculate_transaction_list_totals (
     }
   }
   /* spent = spent - refunded */
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&spent,
                              &spent,
                              &refunded))
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index a639b133..5ecefe5e 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -1987,7 +1987,7 @@ postgres_reserves_in_insert (void *cls,
        never actually have to rollback anything. */struct 
TALER_EXCHANGEDB_Reserve updated_reserve;
 
     updated_reserve.pub = reserve.pub;
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_add (&updated_reserve.balance,
                           &reserve.balance,
                           balance))
@@ -2160,7 +2160,7 @@ postgres_insert_withdraw_info (
       qs = GNUNET_DB_STATUS_HARD_ERROR;
     return qs;
   }
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&reserve.balance,
                              &reserve.balance,
                              &collectable->amount_with_fee))
@@ -5083,7 +5083,7 @@ postgres_insert_reserve_closed (
     TALER_PQ_query_param_amount (closing_fee),
     GNUNET_PQ_query_param_end
   };
-  int ret;
+  enum TALER_AmountArithmeticResult ret;
   enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
@@ -5108,7 +5108,7 @@ postgres_insert_reserve_closed (
   ret = TALER_amount_subtract (&reserve.balance,
                                &reserve.balance,
                                amount_with_fee);
-  if (GNUNET_SYSERR == ret)
+  if (ret < 0)
   {
     /* The reserve history was checked to make sure there is enough of a 
balance
        left before we tried this; however, concurrent operations may have 
changed
@@ -5118,7 +5118,7 @@ postgres_insert_reserve_closed (
                 TALER_B2S (reserve_pub));
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  GNUNET_break (GNUNET_NO == ret);
+  GNUNET_break (TALER_AAR_RESULT_ZERO == ret);
   return reserves_update (cls,
                           session,
                           &reserve);
@@ -6839,7 +6839,7 @@ postgres_insert_recoup_request (
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
     return qs;
   }
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_add (&reserve.balance,
                         &reserve.balance,
                         amount))
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index a9272164..eea484e9 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -1264,7 +1264,7 @@ test_wire_out (struct TALER_EXCHANGEDB_Session *session,
 
   coin_value_wt = deposit->amount_with_fee;
   coin_fee_wt = fee_deposit;
-  GNUNET_assert (GNUNET_OK ==
+  GNUNET_assert (0 <
                  TALER_amount_subtract (&transfer_value_wt,
                                         &coin_value_wt,
                                         &coin_fee_wt));
@@ -1728,7 +1728,7 @@ run (void *cls)
             plugin->reserves_get (plugin->cls,
                                   session,
                                   &post_reserve));
-    FAILIF (GNUNET_OK !=
+    FAILIF (0 >=
             TALER_amount_subtract (&delta,
                                    &post_reserve.balance,
                                    &pre_reserve.balance));
@@ -1743,7 +1743,7 @@ run (void *cls)
                                                  &recoup_cb,
                                                  &coin_blind));
 
-  GNUNET_assert (GNUNET_OK ==
+  GNUNET_assert (0 <=
                  TALER_amount_add (&amount_with_fee,
                                    &value,
                                    &value));
diff --git a/src/include/taler_amount_lib.h b/src/include/taler_amount_lib.h
index 3da2b851..4f77c322 100644
--- a/src/include/taler_amount_lib.h
+++ b/src/include/taler_amount_lib.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014, 2015 Taler Systems SA
+  Copyright (C) 2014, 2015, 2020 Taler Systems SA
 
   TALER is free software; you can redistribute it and/or modify it under the
   terms of the GNU General Public License as published by the Free Software
@@ -230,18 +230,55 @@ TALER_amount_cmp_currency_nbo (const struct 
TALER_AmountNBO *a1,
                                const struct TALER_AmountNBO *a2);
 
 
+/**
+ * Possible results from calling #TALER_amount_subtract() and
+ * possibly other arithmetic operations. Negative values
+ * indicate that the operation did not generate a result.
+ */
+enum TALER_AmountArithmeticResult
+{
+
+  /**
+   * Operation succeeded, result is positive.
+   */
+  TALER_AAR_RESULT_POSITIVE = 1,
+
+  /**
+   * Operation succeeded, result is exactly zero.
+   */
+  TALER_AAR_RESULT_ZERO = 0,
+
+  /**
+   * Operation failed, the result would have been negative.
+   */
+  TALER_AAR_INVALID_NEGATIVE_RESULT = -1,
+
+  /**
+   * Operation failed, result outside of the representable range.
+   */
+  TALER_AAR_INVALID_RESULT_OVERFLOW = -2,
+
+  /**
+   * Operation failed, inputs could not be normalized.
+   */
+  TALER_AAR_INVALID_NORMALIZATION_FAILED = -3,
+
+  /**
+   * Operation failed, input currencies were not identical.
+   */
+  TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE = -4
+
+};
+
 /**
  * Perform saturating subtraction of amounts.
  *
  * @param[out] diff where to store (@a a1 - @a a2), or invalid if @a a2 > @a a1
  * @param a1 amount to subtract from
  * @param a2 amount to subtract
- * @return #GNUNET_OK if the subtraction worked,
- *         #GNUNET_NO if @a a1 = @a a2
- *         #GNUNET_SYSERR if @a a2 > @a a1 or currencies are incompatible;
- *                        @a diff is set to invalid
+ * @return operation status, negative on failures
  */
-int
+enum TALER_AmountArithmeticResult
 TALER_amount_subtract (struct TALER_Amount *diff,
                        const struct TALER_Amount *a1,
                        const struct TALER_Amount *a2);
@@ -253,10 +290,9 @@ TALER_amount_subtract (struct TALER_Amount *diff,
  * @param[out] sum where to store @a a1 + @a a2, set to "invalid" on overflow
  * @param a1 first amount to add
  * @param a2 second amount to add
- * @return #GNUNET_OK if the addition worked,
- *         #GNUNET_SYSERR on overflow
+ * @return operation status, negative on failures
  */
-int
+enum TALER_AmountArithmeticResult
 TALER_amount_add (struct TALER_Amount *sum,
                   const struct TALER_Amount *a1,
                   const struct TALER_Amount *a2);
diff --git a/src/lib/exchange_api_common.c b/src/lib/exchange_api_common.c
index d441807a..07f5e187 100644
--- a/src/lib/exchange_api_common.c
+++ b/src/lib/exchange_api_common.c
@@ -117,7 +117,7 @@ TALER_EXCHANGE_parse_reserve_history (
       };
 
       rh->type = TALER_EXCHANGE_RTT_CREDIT;
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&total_in,
                             &total_in,
                             &amount))
@@ -233,7 +233,7 @@ TALER_EXCHANGE_parse_reserve_history (
       }
       uuid_off++;
 
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&total_out,
                             &total_out,
                             &amount))
@@ -301,7 +301,7 @@ TALER_EXCHANGE_parse_reserve_history (
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&total_in,
                             &total_in,
                             &rh->amount))
@@ -378,7 +378,7 @@ TALER_EXCHANGE_parse_reserve_history (
         GNUNET_break_op (0);
         return GNUNET_SYSERR;
       }
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&total_out,
                             &total_out,
                             &rh->amount))
@@ -398,7 +398,7 @@ TALER_EXCHANGE_parse_reserve_history (
   }
 
   /* check balance = total_in - total_out < withdraw-amount */
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (balance,
                              &total_in,
                              &total_out))
@@ -750,7 +750,7 @@ TALER_EXCHANGE_verify_coin_history (
     if (GNUNET_YES == add)
     {
       /* This amount should be added to the total */
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (total,
                             total,
                             &amount))
@@ -768,7 +768,7 @@ TALER_EXCHANGE_verify_coin_history (
          these negative amounts, as we might get refunds before
          deposits from a semi-evil exchange.  Then, at the end, we do
          the subtraction by calculating "total = total - rtotal" 
*/GNUNET_assert (GNUNET_NO == add);
-      if (GNUNET_OK !=
+      if (0 >
           TALER_amount_add (&rtotal,
                             &rtotal,
                             &amount))
@@ -781,7 +781,7 @@ TALER_EXCHANGE_verify_coin_history (
   }
 
   /* Finally, subtract 'rtotal' from total to handle the subtractions */
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_subtract (total,
                              total,
                              &rtotal))
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index 38f15246..3c06bbe3 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -263,7 +263,7 @@ verify_deposit_signature_forbidden (
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_add (&total,
                         &total,
                         &dh->amount_with_fee))
@@ -586,7 +586,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
     GNUNET_break (0);
     return NULL;
   }
-  if (GNUNET_SYSERR ==
+  if (0 >
       TALER_amount_subtract (&amount_without_fee,
                              amount,
                              &dki->fee_deposit))
diff --git a/src/lib/exchange_api_melt.c b/src/lib/exchange_api_melt.c
index 0217757b..f89036e4 100644
--- a/src/lib/exchange_api_melt.c
+++ b/src/lib/exchange_api_melt.c
@@ -227,7 +227,7 @@ verify_melt_signature_conflict (struct 
TALER_EXCHANGE_MeltHandle *mh,
   json_decref (history);
 
   /* check if melt operation was really too expensive given history */
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_add (&total,
                         &total,
                         &melt_value_with_fee))
diff --git a/src/lib/exchange_api_refresh_common.c 
b/src/lib/exchange_api_refresh_common.c
index f0468dc8..92217c5e 100644
--- a/src/lib/exchange_api_refresh_common.c
+++ b/src/lib/exchange_api_refresh_common.c
@@ -536,11 +536,11 @@ TALER_EXCHANGE_refresh_prepare (
   {
     md.fresh_pks[i].rsa_public_key
       = GNUNET_CRYPTO_rsa_public_key_dup (fresh_pks[i].key.rsa_public_key);
-    if ( (GNUNET_OK !=
+    if ( (0 >
           TALER_amount_add (&total,
                             &total,
                             &fresh_pks[i].value)) ||
-         (GNUNET_OK !=
+         (0 >
           TALER_amount_add (&total,
                             &total,
                             &fresh_pks[i].fee_withdraw)) )
diff --git a/src/lib/exchange_api_transfers_get.c 
b/src/lib/exchange_api_transfers_get.c
index aa4abfa5..55253695 100644
--- a/src/lib/exchange_api_transfers_get.c
+++ b/src/lib/exchange_api_transfers_get.c
@@ -165,11 +165,11 @@ check_transfers_get_response_ok (
                          &detail->coin_value);
       TALER_amount_hton (&dd.deposit_fee,
                          &detail->coin_fee);
-      if ( (GNUNET_OK !=
+      if ( (0 >
             TALER_amount_add (&total_expected,
                               &total_expected,
                               &detail->coin_value)) ||
-           (GNUNET_OK !=
+           (0 >
             TALER_amount_subtract (&total_expected,
                                    &total_expected,
                                    &detail->coin_fee)) )
@@ -216,7 +216,7 @@ check_transfers_get_response_ok (
       return GNUNET_SYSERR;
     }
 
-    if (GNUNET_OK !=
+    if (0 >
         TALER_amount_subtract (&total_expected,
                                &total_expected,
                                &wire_fee))
diff --git a/src/lib/exchange_api_withdraw.c b/src/lib/exchange_api_withdraw.c
index c72454e2..6258053b 100644
--- a/src/lib/exchange_api_withdraw.c
+++ b/src/lib/exchange_api_withdraw.c
@@ -242,7 +242,7 @@ reserve_withdraw_payment_required (
     return GNUNET_SYSERR;
   }
   /* Compute how much we expected to charge to the reserve */
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_add (&requested_amount,
                         &wh->pk.value,
                         &wh->pk.fee_withdraw))
@@ -515,7 +515,7 @@ TALER_EXCHANGE_withdraw (
                                       &req.reserve_pub.eddsa_pub);
   req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
   req.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
-  if (GNUNET_OK !=
+  if (0 >
       TALER_amount_add (&amount_with_fee,
                         &pk->fee_withdraw,
                         &pk->value))
diff --git a/src/testing/testing_api_cmd_exec_closer.c 
b/src/testing/testing_api_cmd_exec_closer.c
index 78369699..d604ecec 100644
--- a/src/testing/testing_api_cmd_exec_closer.c
+++ b/src/testing/testing_api_cmd_exec_closer.c
@@ -239,7 +239,7 @@ TALER_TESTING_cmd_exec_closer (const char *label,
     }
     /* expected amount includes fee, while our argument
        gives the amount _without_ the fee. So add the fee. */
-    GNUNET_assert (GNUNET_OK ==
+    GNUNET_assert (0 <=
                    TALER_amount_add (&as->reserve_history.amount,
                                      &as->reserve_history.amount,
                                      
&as->reserve_history.details.close_details.
diff --git a/src/testing/testing_api_cmd_refresh.c 
b/src/testing/testing_api_cmd_refresh.c
index 09228af8..92229cc7 100644
--- a/src/testing/testing_api_cmd_refresh.c
+++ b/src/testing/testing_api_cmd_refresh.c
@@ -1053,11 +1053,11 @@ melt_run (void *cls,
         TALER_TESTING_interpreter_fail (rms->is);
         return;
       }
-      GNUNET_assert (GNUNET_OK ==
+      GNUNET_assert (0 <=
                      TALER_amount_add (&melt_amount,
                                        &melt_amount,
                                        &fresh_amount));
-      GNUNET_assert (GNUNET_OK ==
+      GNUNET_assert (0 <=
                      TALER_amount_add (&melt_amount,
                                        &melt_amount,
                                        &fresh_pk->fee_withdraw));
diff --git a/src/testing/testing_api_cmd_withdraw.c 
b/src/testing/testing_api_cmd_withdraw.c
index e277da14..d863e406 100644
--- a/src/testing/testing_api_cmd_withdraw.c
+++ b/src/testing/testing_api_cmd_withdraw.c
@@ -331,7 +331,7 @@ withdraw_run (void *cls,
     ws->amount = ws->pk->value;
   }
   ws->reserve_history.type = TALER_EXCHANGE_RTT_WITHDRAWAL;
-  GNUNET_assert (GNUNET_OK ==
+  GNUNET_assert (0 <=
                  TALER_amount_add (&ws->reserve_history.amount,
                                    &ws->amount,
                                    &ws->pk->fee_withdraw));
diff --git a/src/util/amount.c b/src/util/amount.c
index f96ab9c4..2de93762 100644
--- a/src/util/amount.c
+++ b/src/util/amount.c
@@ -394,12 +394,9 @@ TALER_amount_cmp (const struct TALER_Amount *a1,
  * @param[out] diff where to store (@a a1 - @a a2), or invalid if @a a2 > @a a1
  * @param a1 amount to subtract from
  * @param a2 amount to subtract
- * @return #GNUNET_OK if the subtraction worked,
- *         #GNUNET_NO if @a a1 = @a a2
- *         #GNUNET_SYSERR if @a a2 > @a a1 or currencies are incompatible;
- *                        @a diff is set to invalid
+ * @return operation status, negative on failures
  */
-int
+enum TALER_AmountArithmeticResult
 TALER_amount_subtract (struct TALER_Amount *diff,
                        const struct TALER_Amount *a1,
                        const struct TALER_Amount *a2)
@@ -412,7 +409,7 @@ TALER_amount_subtract (struct TALER_Amount *diff,
                                  a2))
   {
     invalidate (diff);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE;
   }
   /* make local copies to avoid aliasing problems between
      diff and a1/a2 */
@@ -422,7 +419,7 @@ TALER_amount_subtract (struct TALER_Amount *diff,
        (GNUNET_SYSERR == TALER_amount_normalize (&n2)) )
   {
     invalidate (diff);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_NORMALIZATION_FAILED;
   }
 
   if (n1.fraction < n2.fraction)
@@ -430,7 +427,7 @@ TALER_amount_subtract (struct TALER_Amount *diff,
     if (0 == n1.value)
     {
       invalidate (diff);
-      return GNUNET_SYSERR;
+      return TALER_AAR_INVALID_NEGATIVE_RESULT;
     }
     n1.fraction += TALER_AMOUNT_FRAC_BASE;
     n1.value--;
@@ -438,7 +435,7 @@ TALER_amount_subtract (struct TALER_Amount *diff,
   if (n1.value < n2.value)
   {
     invalidate (diff);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_NEGATIVE_RESULT;
   }
   GNUNET_assert (GNUNET_OK ==
                  TALER_amount_get_zero (n1.currency,
@@ -449,8 +446,8 @@ TALER_amount_subtract (struct TALER_Amount *diff,
   diff->value = n1.value - n2.value;
   if ( (0 == diff->fraction) &&
        (0 == diff->value) )
-    return GNUNET_NO;
-  return GNUNET_OK;
+    return TALER_AAR_RESULT_ZERO;
+  return TALER_AAR_RESULT_POSITIVE;
 }
 
 
@@ -460,10 +457,9 @@ TALER_amount_subtract (struct TALER_Amount *diff,
  * @param[out] sum where to store @a a1 + @a a2, set to "invalid" on overflow
  * @param a1 first amount to add
  * @param a2 second amount to add
- * @return #GNUNET_OK if the addition worked,
- *         #GNUNET_SYSERR on overflow
+ * @return operation status, negative on failures
  */
-int
+enum TALER_AmountArithmeticResult
 TALER_amount_add (struct TALER_Amount *sum,
                   const struct TALER_Amount *a1,
                   const struct TALER_Amount *a2)
@@ -476,7 +472,7 @@ TALER_amount_add (struct TALER_Amount *sum,
       TALER_amount_cmp_currency (a1, a2))
   {
     invalidate (sum);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE;
   }
   /* make local copies to avoid aliasing problems between
      diff and a1/a2 */
@@ -486,7 +482,7 @@ TALER_amount_add (struct TALER_Amount *sum,
        (GNUNET_SYSERR == TALER_amount_normalize (&n2)) )
   {
     invalidate (sum);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_NORMALIZATION_FAILED;
   }
 
   GNUNET_assert (GNUNET_OK ==
@@ -497,13 +493,13 @@ TALER_amount_add (struct TALER_Amount *sum,
   {
     /* integer overflow */
     invalidate (sum);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_RESULT_OVERFLOW;
   }
   if (res.value > MAX_AMOUNT_VALUE)
   {
     /* too large to be legal */
     invalidate (sum);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_RESULT_OVERFLOW;
   }
   res.fraction = n1.fraction + n2.fraction;
   if (GNUNET_SYSERR ==
@@ -511,10 +507,13 @@ TALER_amount_add (struct TALER_Amount *sum,
   {
     /* integer overflow via carry from fraction */
     invalidate (sum);
-    return GNUNET_SYSERR;
+    return TALER_AAR_INVALID_RESULT_OVERFLOW;
   }
   *sum = res;
-  return GNUNET_OK;
+  if ( (0 == sum->fraction) &&
+       (0 == sum->value) )
+    return TALER_AAR_RESULT_ZERO;
+  return TALER_AAR_RESULT_POSITIVE;
 }
 
 
diff --git a/src/util/test_amount.c b/src/util/test_amount.c
index 03f15cb8..8a83e4cf 100644
--- a/src/util/test_amount.c
+++ b/src/util/test_amount.c
@@ -117,7 +117,7 @@ main (int argc,
                                             &a2));
 
   /* test subtraction failure (currency mismatch) */
-  GNUNET_assert (GNUNET_SYSERR ==
+  GNUNET_assert (TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE ==
                  TALER_amount_subtract (&a3,
                                         &a3,
                                         &a2));
@@ -125,7 +125,7 @@ main (int argc,
                  TALER_amount_normalize (&a3));
 
   /* test subtraction failure (negative result) */
-  GNUNET_assert (GNUNET_SYSERR ==
+  GNUNET_assert (TALER_AAR_INVALID_NEGATIVE_RESULT ==
                  TALER_amount_subtract (&a3,
                                         &a1,
                                         &a2));
@@ -133,11 +133,11 @@ main (int argc,
                  TALER_amount_normalize (&a3));
 
   /* test subtraction success cases */
-  GNUNET_assert (GNUNET_YES ==
+  GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
                  TALER_amount_subtract (&a3,
                                         &a2,
                                         &a1));
-  GNUNET_assert (GNUNET_NO ==
+  GNUNET_assert (TALER_AAR_RESULT_ZERO ==
                  TALER_amount_subtract (&a3,
                                         &a1,
                                         &a1));
@@ -147,7 +147,7 @@ main (int argc,
                  TALER_amount_normalize (&a3));
 
   /* test addition success */
-  GNUNET_assert (GNUNET_OK ==
+  GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
                  TALER_amount_add (&a3,
                                    &a3,
                                    &a2));
@@ -189,7 +189,7 @@ main (int argc,
   a1.value = UINT64_MAX - 5;
   a2.fraction = 2;
   a2.value = 5;
-  GNUNET_assert (GNUNET_SYSERR ==
+  GNUNET_assert (TALER_AAR_INVALID_RESULT_OVERFLOW ==
                  TALER_amount_add (&a3, &a1, &a2));
 
   /* test addition with underflow on fraction */
@@ -197,7 +197,7 @@ main (int argc,
   a1.value = UINT64_MAX;
   a2.fraction = 2;
   a2.value = 0;
-  GNUNET_assert (GNUNET_OK ==
+  GNUNET_assert (TALER_AAR_RESULT_POSITIVE ==
                  TALER_amount_subtract (&a3, &a1, &a2));
   GNUNET_assert (UINT64_MAX - 1 == a3.value);
   GNUNET_assert (TALER_AMOUNT_FRAC_BASE - 1 == a3.fraction);

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



reply via email to

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