gnunet-svn
[Top][All Lists]
Advanced

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

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


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: more work on wire auditor and reporting (#4958)
Date: Tue, 07 Nov 2017 14:38:48 +0100

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new f8af22b  more work on wire auditor and reporting (#4958)
f8af22b is described below

commit f8af22b882f734c3d7dd0bcaf4673552d0a616c4
Author: Christian Grothoff <address@hidden>
AuthorDate: Tue Nov 7 14:38:45 2017 +0100

    more work on wire auditor and reporting (#4958)
---
 .gitignore                       |   4 +
 contrib/auditor-report.tex.j2    | 184 ++++++++++++++-
 contrib/render.py                |  26 ++-
 src/auditor/Makefile.am          |   1 +
 src/auditor/taler-wire-auditor.c | 470 ++++++++++++++++++++++++++++-----------
 5 files changed, 545 insertions(+), 140 deletions(-)

diff --git a/.gitignore b/.gitignore
index 16c6234..5f227d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,3 +88,7 @@ contrib/taler-exchange.tag
 doxygen-doc/
 src/exchange-lib/test_exchange_api_keys_cherry_picking
 src/auditor/taler-wire-auditor
+contrib/auditor-report.aux
+contrib/auditor-report.log
+contrib/auditor-report.tex
+contrib/auditor-report.pdf
diff --git a/contrib/auditor-report.tex.j2 b/contrib/auditor-report.tex.j2
index 11b7841..d852f90 100644
--- a/contrib/auditor-report.tex.j2
+++ b/contrib/auditor-report.tex.j2
@@ -311,11 +311,130 @@ public key for ``payback-master'' operations.
 
 \subsection{Actual incoming wire transfers}
 
-TBD.  See bug 4958.
+This section highlights cases where the exchange's record about
+incoming wire transfers does not match with that of the bank.
+
+{% if wire.reserve_in_amount_inconsistencies() == 0 %}
+  {\bf All incoming wire transfer amounts and subjects matched up.}
+{% else %}
+  \begin{longtable}{p{6.5cm}|rl|rl}
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Expected}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+  \hline \hline
+\endfirsthead
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Expected}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+  \hline \hline
+\endhead
+  \hline \hline
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Expected}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+\endfoot
+  \hline
+  {\bf Total deltas}  & &
+  {{ wire.total_bad_amount_in_plus.value}}.{{ 
wire.total_bad_amount_in_plus.fraction}} & {{ 
wire.total_bad_amount_in_plus.currency}} &
+  - {{ wire.total_bad_amount_in_minus.value}}.{{ 
wire.total_bad_amount_in_minus.fraction}} & {{ 
wire.total_bad_amount_in_minus.currency}} \\
+  \caption{Incoming wire transfer amounts not matching up.}
+  \label{table:wire_in:transfer_amount_inconsistencies}
+\endlastfoot
+{% for item in wire.reserve_in_amount_inconsistencies %}
+  {\tt {{ item.wtid }} } &
+  {{ item.amount_wired.value }}.{{ item.amount_wired.fraction }} &
+  {{ item.amount_wired.currency }} &
+  {{ item.amount_expected.value }}.{{ item.amount_expected.fraction }} &
+  {{ item.amount_expected.currency }} \\ \hline
+\nopagebreak
+  &
+  {{ item.diagnostic }} &
+  {{ item.row }} &
+  {{ item.timestmap }} \\ \hline
+{% endfor %}
+  \end{longtable}
+{% endif %}
+
+
+\subsection{Missattributed incoming wire transfers}
+
+This section lists cases where the sender account record of an
+incoming wire transfer differs between the exchange and the bank.
+This will cause funds to be sent to the wrong account when the reserve
+is closed and the remaining balance is refunded to the original
+account.
+
+
+{% if wire.missattribution_in_inconsistencies() == 0 %}
+  {\bf All incoming wire transfer sender accounts matched up.}
+{% else %}
+  \begin{longtable}{p{6.5cm}|rl}
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
+  \hline \hline
+\endfirsthead
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
+  \hline \hline
+\endhead
+  \hline \hline
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Amount}} \\
+\endfoot
+  \hline
+  {\bf Total amount}  &
+  {{ wire.total_missattribution_in_plus.value}}.{{ 
wire.total_missattribution_in_plus.fraction}} & {{ 
wire.total_missattribution_in_plus.currency}} \\
+  \caption{Incoming wire transfer sender accounts not matching up.}
+  \label{table:wire_in:sender_account_inconsistencies}
+\endlastfoot
+{% for item in wire.missattribution_in_inconsistencies %}
+  {\tt {{ item.wtid }} } &
+  {{ item.amount.value }}.{{ item.amount.fraction }} &
+  {{ item.amount.currency }} \\ hline
+{% endfor %}
+  \end{longtable}
+{% endif %}
+
+
+
 
 \subsection{Actual outgoing wire transfers} \label{sec:wire_check_out}
 
-TBD.  See bug 4958.
+This section highlights cases where the exchange missbehaved
+with respect to outgoing wire transfers.
+
+{% if wire.wire_out_amount_inconsistencies() == 0 %}
+  {\bf All outgoing wire transfers matched up.}
+{% else %}
+  \begin{longtable}{p{6.5cm}|rl|rl}
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Justified}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+  \hline \hline
+\endfirsthead
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Justified}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+  \hline \hline
+\endhead
+  \hline \hline
+  {\bf Wire transfer identifier} & \multicolumn{2}{|c|}{ {\bf Wired}} & 
\multicolumn{2}{|c|}{ {\bf Justified}}  \\
+  {\bf Diagnostic}               & \multicolumn{2}{|c|}{ {\bf Row}} & 
\multicolumn{2}{|c|}{ {\bf Timestamp}}  \\
+\endfoot
+  \hline
+  {\bf Total deltas}  & &
+  {{ wire.total_bad_amount_out_plus.value}}.{{ 
wire.total_bad_amount_out_plus.fraction}} & {{ 
wire.total_bad_amount_out_plus.currency}} &
+  - {{ wire.total_bad_amount_out_minus.value}}.{{ 
wire.total_bad_amount_out_minus.fraction}} & {{ 
wire.total_bad_amount_out_minus.currency}} \\
+  \caption{Outgoing wire transfer amounts not matching up.}
+  \label{table:wire_out:transfer_amount_inconsistencies}
+\endlastfoot
+{% for item in wire.wire_out_amount_inconsistencies %}
+  {\tt {{ item.wtid }} } &
+  {{ item.amount_wired.value }}.{{ item.amount_wired.fraction }} &
+  {{ item.amount_wired.currency }} &
+  {{ item.amount_justified.value }}.{{ item.amount_justified.fraction }} &
+  {{ item.amount_justified.currency }} \\ \hline
+\nopagebreak
+  &
+  {{ item.diagnostic }} &
+  {{ item.row }} &
+  {{ item.timestmap }} \\ \hline
+{% endfor %}
+  \end{longtable}
+{% endif %}
+
 
 \section{Minor irregularities}
 
@@ -358,6 +477,39 @@ translate into a financial loss (yet).
 {% endif %}
 
 
+\subsection{Wire table issues}
+
+This section describes issues found by the wire auditor that do not
+have a clear financial impact.
+
+{% if wire.row_inconsistencies|length() == 0 %}
+  {\bf No wire row inconsistencies found.}
+{% else %}
+  \begin{longtable}{p{1.5cm}|l|p{5.5}}
+  {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
+  \hline \hline
+\endfirsthead
+  {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
+  \hline \hline
+\endhead
+  \hline \hline
+  {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
+\endfoot
+  \hline
+  {\bf Table} & {\bf Row} & {\bf Diagnostic} \\
+  \caption{Other wire table issues found (by table and row).}
+  \label{table:misc}
+\endlastfoot
+{% for item in data.row_inconsistencies %}
+  {{ item.table }} &
+  {{ item.row }} &
+  {{ item.diagnostic }} \\
+\nopagebreak
+  {{ item.wire_offset_hash }}  \\ \hline
+{% endfor %}
+  \end{longtable}
+{% endif %}
+
 \subsection{Other issues}
 
 This section describes issues found that do not have a clear financial
@@ -470,6 +622,34 @@ implications.
 {% endif %}
 
 
+\subsection{Wire transfer timestamp issues}
+
+This section lists issues with wire transfers related to timestamps.
+
+
+{% if wire.row_minor_inconsistencies|length() == 0 %}
+  {\bf No timestamp issues detected.}
+{% else %}
+  \begin{longtable}{p{1.5cm}|r|p{5.5}}
+  {\bf Table} & {\bf Table row} & {\bf Diagnostic}
+  \\ \hline \hline
+\endfirsthead
+  {\bf Table} & {\bf Table row} & {\bf Diagnostic}
+  \\ \hline \hline
+\endhead
+  \hline \hline
+  {\bf Table} & {\bf Table row} & {\bf Diagnostic} \\
+\endfoot
+  \hline \hline
+  {\bf Table} & {\bf Table row} & {\bf Diagnostic} \\
+  \caption{Execution times not matching in wire transfers.}
+  \label{table:wire:bad_time}
+\endlastfoot
+{% for item in wire.row_minor_inconsistencies %}
+  {\tt {{ item.table }} } & {{ item.row }} & {{ item.diagnostic }} \\ \hline
+{% endfor %}
+  \end{longtable}
+{% endif %}
 
 
 \end{document}
diff --git a/contrib/render.py b/contrib/render.py
index d31c7f9..093db35 100755
--- a/contrib/render.py
+++ b/contrib/render.py
@@ -1,14 +1,19 @@
 #!/usr/bin/python
 # This file is in the public domain.
 
-"""
-Expand Jinja2 templates based on JSON input.
+"""Expand Jinja2 templates based on JSON input.
+
+First command-line argument must be the JSON input from taler-auditor.
+Second command-line argument must be the JSON input from the
+taler-wire-auditor.
+
+The tool then reads the template from stdin and writes the expanded
+output to stdout.
 
-First command-line argument must be the JSON input.
-The tool reads the template from stdin and writes
-the expanded output to stdout.
+TODO: proper installation, man page, error handling, --help option.
 
 @author Christian Grothoff
+
 """
 
 import sys
@@ -23,10 +28,13 @@ class StdinLoader(BaseLoader):
      def get_source(self, environment, template):
               source = sys.stdin.read().decode('utf-8')
               return source, self.path, lambda: false
-  
 
-jsonFile = open (sys.argv[1], 'r')
-jsonData = json.load(jsonFile)
+
+jsonFile1 = open (sys.argv[1], 'r')
+jsonData1 = json.load(jsonFile)
+
+jsonFile2 = open (sys.argv[2], 'r')
+jsonData2 = json.load(jsonFile)
 
 jinjaEnv = jinja2.Environment(loader=StdinLoader(),
                               lstrip_blocks=True,
@@ -35,4 +43,4 @@ jinjaEnv = jinja2.Environment(loader=StdinLoader(),
                               autoescape=False)
 tmpl = jinjaEnv.get_template('stdin');
 
-print(tmpl.render(data = jsonData))
+print(tmpl.render(data = jsonData1, wire = jsonData2))
diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index 439db7f..0770338 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -39,6 +39,7 @@ taler_wire_auditor_LDADD = \
   $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
   $(top_builddir)/src/auditordb/libtalerauditordb.la \
   -ljansson \
+  -lgnunetjson \
   -lgnunetutil
 
 taler_auditor_sign_SOURCES = \
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index 7cc741b..c61d2a3 100644
--- a/src/auditor/taler-wire-auditor.c
+++ b/src/auditor/taler-wire-auditor.c
@@ -130,7 +130,23 @@ static void *out_wire_off;
 static size_t wire_off_size;
 
 /**
- * Array of reports about row inconsitencies.
+ * Array of reports about row inconsitencies in wire_out table.
+ */
+static json_t *report_wire_out_inconsistencies;
+
+/**
+ * Array of reports about row inconsitencies in reserves_in table.
+ */
+static json_t *report_reserve_in_inconsistencies;
+
+/**
+ * Array of reports about wrong bank account being recorded for
+ * incoming wire transfers.
+ */
+static json_t *report_missattribution_in_inconsistencies;
+
+/**
+ * Array of reports about row inconcistencies.
  */
 static json_t *report_row_inconsistencies;
 
@@ -139,17 +155,49 @@ static json_t *report_row_inconsistencies;
  */
 static json_t *report_row_minor_inconsistencies;
 
+/**
+ * Total amount that was transferred too much from the exchange.
+ */
+static struct TALER_Amount total_bad_amount_out_plus;
+
+/**
+ * Total amount that was transferred too little from the exchange.
+ */
+static struct TALER_Amount total_bad_amount_out_minus;
+
+/**
+ * Total amount that was transferred too much to the exchange.
+ */
+static struct TALER_Amount total_bad_amount_in_plus;
+
+/**
+ * Total amount that was transferred too little to the exchange.
+ */
+static struct TALER_Amount total_bad_amount_in_minus;
+
+/**
+ * Total amount where the exchange has the wrong sender account
+ * for incoming funds and may thus wire funds to the wrong
+ * destination when closing the reserve.
+ */
+static struct TALER_Amount total_missattribution_in;
+
+/**
+ * Amount of zero in our currency.
+ */
+static struct TALER_Amount zero;
+
 
 /* *****************************   Shutdown   **************************** */
 
-/** 
+/**
  * Entry in map with wire information we expect to obtain from the
  * bank later.
  */
 struct ReserveInInfo
 {
 
-  /** 
+  /**
    * Hash of expected row offset.
    */
   struct GNUNET_HashCode row_off_hash;
@@ -168,18 +216,18 @@ struct ReserveInInfo
    * RowID in reserves_in table.
    */
   uint64_t rowid;
-  
+
 };
 
 
-/** 
+/**
  * Entry in map with wire information we expect to obtain from the
  * #edb later.
  */
 struct ReserveOutInfo
 {
 
-  /** 
+  /**
    * Hash of the wire transfer subject.
    */
   struct GNUNET_HashCode subject_hash;
@@ -188,7 +236,7 @@ struct ReserveOutInfo
    * Expected details about the wire transfer.
    */
   struct TALER_WIRE_TransferDetails details;
-  
+
 };
 
 
@@ -253,11 +301,32 @@ do_shutdown (void *cls)
   if (NULL != report_row_inconsistencies)
   {
     json_t *report;
-    
+
     GNUNET_assert (NULL != report_row_minor_inconsistencies);
-    report = json_pack ("{s:o, s:o}",
-                       "row-inconsistencies", report_row_inconsistencies,
-                       "row-minor-inconsistencies", 
report_row_minor_inconsistencies);
+    report = json_pack ("{s:o, s:o, s:o, s:o, s:o,"
+                        " s:o, s:o, s:o, s:o, s:o }",
+                        /* blocks of 5 */
+                       "wire_out_amount_inconsistencies",
+                        report_wire_out_inconsistencies,
+                        "total_wire_out_delta_plus",
+                        TALER_JSON_from_amount (&total_bad_amount_out_plus),
+                        "total_wire_out_delta_minus",
+                        TALER_JSON_from_amount (&total_bad_amount_out_minus),
+                       "reserve_in_amount_inconsistencies",
+                        report_reserve_in_inconsistencies,
+                        "total_wire_in_delta_minus",
+                        TALER_JSON_from_amount (&total_bad_amount_in_plus),
+                        /* block */
+                        "total_wire_in_delta_minus",
+                        TALER_JSON_from_amount (&total_bad_amount_in_minus),
+                        "missattribution_in_inconsistencies",
+                        report_missattribution_in_inconsistencies,
+                        "total_missattribution_in",
+                        TALER_JSON_from_amount (&total_missattribution_in),
+                       "row_inconsistencies",
+                        report_row_inconsistencies,
+                       "row_minor_inconsistencies",
+                        report_row_minor_inconsistencies);
     json_dumpf (report,
                stdout,
                JSON_INDENT (2));
@@ -313,7 +382,7 @@ do_shutdown (void *cls)
  *
  * @param array report array to append @a object to
  * @param object object to append, should be check that it is not NULL
- */ 
+ */
 static void
 report (json_t *array,
        json_t *object)
@@ -325,47 +394,6 @@ report (json_t *array,
 }
 
 
-/**
- * Report a (serious) inconsistency in the exchange's database.
- *
- * @param table affected table
- * @param rowid affected row, UINT64_MAX if row is missing
- * @param diagnostic message explaining the problem
- */
-static void
-report_row_inconsistency (const char *table,
-                          uint64_t rowid,
-                          const char *diagnostic)
-{
-  report (report_row_inconsistencies,
-         json_pack ("{s:s, s:I, s:s}",
-                    "table", table,
-                    "row", (json_int_t) rowid,
-                    "diagnostic", diagnostic));
-}
-
-
-/**
- * Report a minor inconsistency in the exchange's database (i.e. something
- * relating to timestamps that should have no financial implications).
- *
- * @param table affected table
- * @param rowid affected row, UINT64_MAX if row is missing
- * @param diagnostic message explaining the problem
- */
-static void
-report_row_minor_inconsistency (const char *table,
-                                uint64_t rowid,
-                                const char *diagnostic)
-{
-  report (report_row_minor_inconsistencies,
-         json_pack ("{s:s, s:I, s:s}",
-                    "table", table,
-                    "row", (json_int_t) rowid,
-                    "diagnostic", diagnostic));
-}
-
-
 /* *************************** General transaction logic ****************** */
 
 /**
@@ -475,15 +503,15 @@ commit (enum GNUNET_DB_QueryStatus qs)
  */
 static int
 wire_out_cb (void *cls,
-               uint64_t rowid,
-               struct GNUNET_TIME_Absolute date,
-               const struct TALER_WireTransferIdentifierRawP *wtid,
-               const json_t *wire,
-               const struct TALER_Amount *amount)
+             uint64_t rowid,
+             struct GNUNET_TIME_Absolute date,
+             const struct TALER_WireTransferIdentifierRawP *wtid,
+             const json_t *wire,
+             const struct TALER_Amount *amount)
 {
   struct GNUNET_HashCode key;
   struct ReserveOutInfo *roi;
-  
+
   GNUNET_CRYPTO_hash (wtid,
                      sizeof (struct TALER_WireTransferIdentifierRawP),
                      &key);
@@ -491,37 +519,108 @@ wire_out_cb (void *cls,
                                           &key);
   if (NULL == roi)
   {
-    /* FIXME (#4963): do proper logging! */
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               "Failed to find wire transfer `%s' over %s at `%s' in exchange 
database!\n",
-               TALER_B2S (wtid),
-               TALER_amount2s (amount),
-               GNUNET_STRINGS_absolute_time_to_string (date));
+    /* Wire transfer was not made (yet) at all (but would have been
+       justified), so the entire amount is missing / still to be done.
+       This is moderately harmless, it might just be that the aggreator
+       has not yet fully caught up with the transfers it should do. */
+    report (report_wire_out_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", (json_int_t) rowid,
+                       "amount_wired", TALER_JSON_from_amount (&zero),
+                       "amount_justified", TALER_JSON_from_amount (amount),
+                       "wtid", GNUNET_JSON_from_data_auto (wtid),
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                       "diagnostic", "wire transfer not made (yet?)"));
+    GNUNET_break (GNUNET_OK ==
+                  TALER_amount_add (&total_bad_amount_out_minus,
+                                    &total_bad_amount_out_minus,
+                                    amount));
     return GNUNET_OK;
   }
+  if (! json_equal ((json_t *) wire,
+                   roi->details.account_details))
+  {
+    /* Destination bank account is wrong in actual wire transfer, so
+       we should count the wire transfer as entirely spurious, and
+       additionally consider the justified wire transfer as missing. */
+    report (report_wire_out_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", (json_int_t) rowid,
+                       "amount_wired", TALER_JSON_from_amount 
(&roi->details.amount),
+                       "amount_justified", TALER_JSON_from_amount (&zero),
+                       "wtid", GNUNET_JSON_from_data_auto (wtid),
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                       "diagnostic", "recevier account missmatch"));
+    GNUNET_break (GNUNET_OK ==
+                  TALER_amount_add (&total_bad_amount_out_plus,
+                                    &total_bad_amount_out_plus,
+                                    &roi->details.amount));
+    report (report_wire_out_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", (json_int_t) rowid,
+                       "amount_wired", TALER_JSON_from_amount (&zero),
+                       "amount_justified", TALER_JSON_from_amount (amount),
+                       "wtid", GNUNET_JSON_from_data_auto (wtid),
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                       "diagnostic", "receiver account missmatch"));
+    GNUNET_break (GNUNET_OK ==
+                  TALER_amount_add (&total_bad_amount_out_minus,
+                                    &total_bad_amount_out_minus,
+                                    amount));
+    goto cleanup;
+  }
   if (0 != TALER_amount_cmp (&roi->details.amount,
                             amount))
   {
-    report_row_inconsistency ("reserves_out",
-                             rowid,
-                             "wire amount missmatch");
-    return GNUNET_OK;
+    report (report_wire_out_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", (json_int_t) rowid,
+                       "amount_justified", TALER_JSON_from_amount (amount),
+                       "amount_wired", TALER_JSON_from_amount 
(&roi->details.amount),
+                       "wtid", GNUNET_JSON_from_data_auto (wtid),
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(date),
+                       "diagnostic", "wire amount does not match"));
+    if (0 < TALER_amount_cmp (amount,
+                              &roi->details.amount))
+    {
+      /* amount > roi->details.amount: wire transfer was smaller than it 
should have been */
+      struct TALER_Amount delta;
+
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_subtract (&delta,
+                                           amount,
+                                           &roi->details.amount));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_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_break (GNUNET_OK ==
+                    TALER_amount_subtract (&delta,
+                                           &roi->details.amount,
+                                           amount));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_add (&total_bad_amount_out_plus,
+                                      &total_bad_amount_out_plus,
+                                      &delta));
+    }
+    goto cleanup;
   }
   if (roi->details.execution_date.abs_value_us !=
       date.abs_value_us)
   {
-    report_row_minor_inconsistency ("reserves_out",
-                                   rowid,
-                                   "execution date missmatch");
-  }
-  if (! json_equal ((json_t *) wire,
-                   roi->details.account_details))
-  {
-    report_row_inconsistency ("reserves_out",
-                             rowid,
-                             "receiver account missmatch");
-    return GNUNET_OK;
+    report (report_row_minor_inconsistencies,
+            json_pack ("{s:s, s:I, s:s}",
+                       "table", "wire_out",
+                       "row", (json_int_t) rowid,
+                       "diagnostic", "execution date missmatch"));
   }
+cleanup:
   GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multihashmap_remove (out_map,
                                                       &key,
@@ -535,11 +634,12 @@ wire_out_cb (void *cls,
 
 
 /**
- * Complain that we failed to match an entry from #out_map.
+ * Complain that we failed to match an entry from #out_map.  This
+ * means a wire transfer was made without proper justification.
  *
  * @param cls NULL
  * @param key unused key
- * @param value the `struct ReserveOutInfo` to free
+ * @param value the `struct ReserveOutInfo` to report
  * @return #GNUNET_OK
  */
 static int
@@ -549,12 +649,18 @@ complain_out_not_found (void *cls,
 {
   struct ReserveOutInfo *roi = value;
 
-  (void) roi;
-  /* FIXME (#4963): log more precisely which wire transfer (and amount)
-     is bogus. */
-  report_row_inconsistency ("reserves_out",
-                           UINT64_MAX,
-                           "matching wire transfer not found");
+  report (report_wire_out_inconsistencies,
+          json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                     "row", (json_int_t) 0,
+                     "amount_wired", TALER_JSON_from_amount 
(&roi->details.amount),
+                     "amount_justified", TALER_JSON_from_amount (&zero),
+                     "wtid", GNUNET_JSON_from_data_auto 
(&roi->details.reserve_pub), /* #5077 missnomer */
+                     "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(roi->details.execution_date),
+                     "diagnostic", "justification for wire transfer not 
found"));
+  GNUNET_break (GNUNET_OK ==
+                TALER_amount_add (&total_bad_amount_out_plus,
+                                  &total_bad_amount_out_plus,
+                                  &roi->details.amount));
   return GNUNET_OK;
 }
 
@@ -567,7 +673,7 @@ static void
 check_exchange_wire_out ()
 {
   enum GNUNET_DB_QueryStatus qs;
-    
+
   qs = edb->select_wire_out_above_serial_id (edb->cls,
                                             esession,
                                             pp.last_wire_out_serial_id,
@@ -582,14 +688,14 @@ check_exchange_wire_out ()
   }
   GNUNET_CONTAINER_multihashmap_iterate (out_map,
                                         &complain_out_not_found,
-                                        NULL); 
-  /* clean up (technically redundant, but nicer) */
+                                        NULL);
+  /* clean up */
   GNUNET_CONTAINER_multihashmap_iterate (out_map,
                                         &free_roi,
                                         NULL);
   GNUNET_CONTAINER_multihashmap_destroy (out_map);
   out_map = NULL;
- 
+
   /* conclude with: */
   commit (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT);
   GNUNET_SCHEDULER_shutdown ();
@@ -616,7 +722,7 @@ history_debit_cb (void *cls,
                  const struct TALER_WIRE_TransferDetails *details)
 {
   struct ReserveOutInfo *roi;
-  
+
   if (TALER_BANK_DIRECTION_NONE == dir)
   {
     /* end of iteration, now check wire_out to see
@@ -640,9 +746,12 @@ history_debit_cb (void *cls,
                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
   {
     GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
-    report_row_inconsistency ("bank wire log",
-                             UINT64_MAX,
-                             "duplicate wire offset");
+    report (report_row_inconsistencies,
+            json_pack ("{s:s, s:I, s:o, s:s}",
+                       "table", "bank wire log",
+                       "row", (json_int_t) 0,
+                       "wire_offset_hash", GNUNET_JSON_from_data_auto 
(&roi->subject_hash),
+                       "diagnostic", "duplicate wire offset"));
     return GNUNET_SYSERR;
   }
   return GNUNET_OK;
@@ -727,9 +836,12 @@ reserve_in_cb (void *cls,
                                         
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
   {
     GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
-    report_row_inconsistency ("reserves_in",
-                             rowid,
-                             "duplicate wire offset");
+    report (report_row_inconsistencies,
+            json_pack ("{s:s, s:I, s:o, s:s}",
+                       "table", "reserves_in",
+                       "row", (json_int_t) rowid,
+                       "wire_offset_hash", GNUNET_JSON_from_data_auto 
(&rii->row_off_hash),
+                       "diagnostic", "duplicate wire offset"));
     return GNUNET_SYSERR;
   }
   pp.last_reserve_in_serial_id = rowid + 1;
@@ -752,9 +864,18 @@ complain_in_not_found (void *cls,
 {
   struct ReserveInInfo *rii = value;
 
-  report_row_inconsistency ("reserves_in",
-                           rii->rowid,
-                           "matching wire transfer not found");
+  report (report_reserve_in_inconsistencies,
+          json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                     "row", (json_int_t) rii->rowid,
+                     "amount_expected", TALER_JSON_from_amount 
(&rii->details.amount),
+                     "amount_wired", TALER_JSON_from_amount (&zero),
+                     "wtid", GNUNET_JSON_from_data_auto 
(&rii->details.reserve_pub), /* also reserve_pub, but see #5077 missnomer */
+                     "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(rii->details.execution_date),
+                     "diagnostic", "incoming wire transfer claimed by exchange 
not found"));
+  GNUNET_break (GNUNET_OK ==
+                TALER_amount_add (&total_bad_amount_in_minus,
+                                  &total_bad_amount_in_minus,
+                                  &rii->details.amount));
   return GNUNET_OK;
 }
 
@@ -780,7 +901,7 @@ history_credit_cb (void *cls,
 {
   struct ReserveInInfo *rii;
   struct GNUNET_HashCode key;
-  
+
   if (TALER_BANK_DIRECTION_NONE == dir)
   {
     /* end of operation */
@@ -831,42 +952,110 @@ history_credit_cb (void *cls,
   if (row_off_size != rii->row_off_size)
   {
     GNUNET_break (0);
-    report_row_inconsistency ("reserves_in",
-                             rii->rowid,
-                             "wire reference size missmatch");
-    return GNUNET_OK;
-  }
-  if (0 != TALER_amount_cmp (&rii->details.amount,
-                            &details->amount))
-  {
-    report_row_inconsistency ("reserves_in",
-                             rii->rowid,
-                             "wire amount missmatch");
+    report (report_row_inconsistencies,
+            json_pack ("{s:s, s:o, s:o, s:s}",
+                       "table", "reserves_in",
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "wire_offset_hash", GNUNET_JSON_from_data_auto (&key),
+                       "diagnostic", "wire reference size missmatch"));
     return GNUNET_OK;
   }
-  if (details->execution_date.abs_value_us !=
-      rii->details.execution_date.abs_value_us)
-  {
-    report_row_minor_inconsistency ("reserves_in",
-                                   rii->rowid,
-                                   "execution date missmatch");
-  }
   if (0 != memcmp (&details->reserve_pub,
                   &rii->details.reserve_pub,
                   sizeof (struct TALER_ReservePublicKeyP)))
   {
-    report_row_inconsistency ("reserves_in",
-                             rii->rowid,
-                             "reserve public key / wire subject missmatch");
-    return GNUNET_OK;
+    report (report_reserve_in_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "amount_exchange_expected", TALER_JSON_from_amount 
(&rii->details.amount),
+                       "amount_wired", TALER_JSON_from_amount (&zero),
+                       "wtid", GNUNET_JSON_from_data_auto 
(&rii->details.reserve_pub), /* #5077 missnomer */
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(rii->details.execution_date),
+                       "diagnostic", "wire subject does not match"));
+    GNUNET_break (GNUNET_OK ==
+                  TALER_amount_add (&total_bad_amount_in_minus,
+                                    &total_bad_amount_in_minus,
+                                    &rii->details.amount));
+    report (report_reserve_in_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "amount_exchange_expected", TALER_JSON_from_amount 
(&zero),
+                       "amount_wired", TALER_JSON_from_amount 
(&details->amount),
+                       "wtid", GNUNET_JSON_from_data_auto 
(&details->reserve_pub), /* #5077 missnomer */
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(details->execution_date),
+                       "diagnostic", "wire subject does not match"));
+
+    GNUNET_break (GNUNET_OK ==
+                  TALER_amount_add (&total_bad_amount_in_plus,
+                                    &total_bad_amount_in_plus,
+                                    &details->amount));
+    goto cleanup;
+  }
+  if (0 != TALER_amount_cmp (&rii->details.amount,
+                            &details->amount))
+  {
+    report (report_reserve_in_inconsistencies,
+            json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "amount_exchange_expected", TALER_JSON_from_amount 
(&rii->details.amount),
+                       "amount_wired", TALER_JSON_from_amount 
(&details->amount),
+                       "wtid", GNUNET_JSON_from_data_auto 
(&details->reserve_pub), /* #5077 missnomer */
+                       "timestamp", GNUNET_STRINGS_absolute_time_to_string 
(details->execution_date),
+                       "diagnostic", "wire amount does not match"));
+    if (0 < TALER_amount_cmp (&details->amount,
+                              &rii->details.amount))
+    {
+      /* details->amount > rii->details.amount: wire transfer was larger than 
it should have been */
+      struct TALER_Amount delta;
+
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_subtract (&delta,
+                                           &details->amount,
+                                           &rii->details.amount));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_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_break (GNUNET_OK ==
+                    TALER_amount_subtract (&delta,
+                                           &rii->details.amount,
+                                           &details->amount));
+      GNUNET_break (GNUNET_OK ==
+                    TALER_amount_add (&total_bad_amount_in_minus,
+                                      &total_bad_amount_in_minus,
+                                      &delta));
+    }
+    goto cleanup;
   }
   if (! json_equal (details->account_details,
                    rii->details.account_details))
   {
-    report_row_minor_inconsistency ("reserves_in",
-                                   rii->rowid,
-                                   "sender account missmatch");
+    report (report_missattribution_in_inconsistencies,
+            json_pack ("{s:s, s:o, s:o}",
+                       "amount", TALER_JSON_from_amount (&rii->details.amount),
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "wtid", GNUNET_JSON_from_data_auto 
(&rii->details.reserve_pub))); /* FIXME #5077 missnomer */
+    GNUNET_break (GNUNET_OK ==
+                  TALER_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)
+  {
+    report (report_row_minor_inconsistencies,
+            json_pack ("{s:s, s:o, s:s}",
+                       "table", "reserves_in",
+                       "row", GNUNET_JSON_from_data (row_off, row_off_size),
+                       "diagnostic", "execution date missmatch"));
   }
+ cleanup:
   GNUNET_assert (GNUNET_OK ==
                 GNUNET_CONTAINER_multihashmap_remove (in_map,
                                                       &key,
@@ -1002,9 +1191,32 @@ run (void *cls,
     return;
   }
   GNUNET_assert (NULL !=
-                (report_row_inconsistencies = json_array ()));
+                (report_wire_out_inconsistencies = json_array ()));
+  GNUNET_assert (NULL !=
+                (report_reserve_in_inconsistencies = json_array ()));
   GNUNET_assert (NULL !=
                 (report_row_minor_inconsistencies = json_array ()));
+  GNUNET_assert (NULL !=
+                (report_row_inconsistencies = json_array ()));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &total_bad_amount_out_plus));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &total_bad_amount_out_minus));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &total_bad_amount_in_plus));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &total_bad_amount_in_minus));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &total_missattribution_in));
+  GNUNET_assert (GNUNET_OK ==
+                 TALER_amount_get_zero (currency,
+                                        &zero));
+
   qsx = adb->get_wire_auditor_progress (adb->cls,
                                         asession,
                                         &master_pub,

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



reply via email to

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