diff --git a/contrib/auditor-report.tex.j2 b/contrib/auditor-report.tex.j2
index 921daabcd..ab5a16102 100644
--- a/contrib/auditor-report.tex.j2
+++ b/contrib/auditor-report.tex.j2
@@ -1,3 +1,24 @@
+% This file is part of TALER
+% Copyright (C) 2016, 2017 Taler Systems SA
+%
+% TALER is free software; you can redistribute it and/or modify it under the
+% terms of the GNU Affero General Public License as published by the Free Software
+% Foundation; either version 3, or (at your option) any later version.
+%
+% TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+% A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
+%
+% You should have received a copy of the GNU Affero General Public License along with
+% TALER; see the file COPYING. If not, see
+%
+%
+% With respect to this file, our interpretation of the license is
+% that publishing an audit report (i.e. in TeX or PDF) requires
+% publishing the corresponding j2 template sources under AGPL, and
+% linking to them from the report. (This file _is_ source code,
+% the generated PDF is the service under definition of the AGPL.)
+%
\documentclass{article} % {acmart}
\usepackage{url}
\usepackage[T1]{fontenc}
@@ -7,7 +28,15 @@
\begin{document}
-\title{Taler Auditor Report}
+% If you update this template, complying with the license requires
+% publishing the J2 source and linking to it from the generated PDF.
+% So if you change this outside of the Taler Git repository, you must
+% update this link (and the link must remain available to the receiver
+% of the result from the generated TeX, PDF or other format).
+\title{Taler Auditor Report\footnote{Template available at \url{https://git.taler.net/}}}
+
+% You must also credit the original author.
+\author{Christian Grothoff}
\maketitle
\section{Operations}
@@ -569,6 +598,80 @@ have a clear financial impact.
\end{longtable}
{% endif %}
+
+\subsection{Outgoing wire transfer subject issues}
+
+This section describes issues found by the wire auditor that
+relate to outgoing wire transfers being malformed.
+This happens if the exchange somehow creates wire transfers
+with duplicate or malformed wire transfer subjects.
+
+{% if wire.wire_format_inconsistencies|length() == 0 %}
+ {\bf No wire format inconsistencies found.}
+{% else %}
+ \begin{longtable}{p{4.5cm}|rl}
+ \multicolumn{3}{c}{ {\bf Row hash} } \\
+ {\bf Diagnostic} & \multicolumn{2}{c|}{ {\bf Amount} } \\
+ \hline \hline
+\endfirsthead
+ \multicolumn{3}{c}{ {\bf Row hash} } \\
+ {\bf Diagnostic} & \multicolumn{2}{c|}{ {\bf Amount} } \\
+ \hline \hline
+\endhead
+ \hline
+ \multicolumn{3}{c}{ {\bf Row hash} } \\
+ {\bf Diagnostic} & \multicolumn{2}{c|}{ {\bf Amount} } \\
+\endfoot
+ \hline
+ \hline
+ {\bf Total} &
+ {{ wire.total_wire_format_amount.value }}.{{ wire.total_wire_format_amount.fraction }} &
+ {{ wire.total_wire_format_amount.currency }} \\
+ \caption{Outgoing wire transfer subject issues found.}
+ \label{table:outgoing:wtid}
+\endlastfoot
+{% for item in wire.wire_format_inconsistencies %}
+ \multicolumn{3}{l}{ \verb! {{ item.wire_offset_hash }} ! } \\
+\nopagebreak
+ {{ item.diagnostic }} &
+ {{ item.amount.value }}.{{ item.amount.fraction }} &
+ {{ item.amount.currency }} \\
+{% endfor %}
+ \end{longtable}
+{% endif %}
+
+
+\subsection{Wire fee structure inconsistencies}
+
+This section lists cases where the exchange's database may be ambiguous
+with respect to what wire fee it charges at what time.
+
+{% if data.wire_fee_time_inconsistencies|length() == 0 %}
+ {\bf No wire fee timing issues detected.}
+{% else %}
+ \begin{longtable}{p{1.5cm}|r|p{5.5}}
+ {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic}
+ \\ \hline \hline
+\endfirsthead
+ {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic}
+ \\ \hline \hline
+\endhead
+ \hline \hline
+ {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic} \\
+\endfoot
+ \hline \hline
+ {\bf Wire format} & {\bf Timestamp} & {\bf Diagnostic} \\
+ \caption{Wire fees with ambiguous timestamps.}
+ \label{table:wire_fee:ambiguity}
+\endlastfoot
+{% for item in data.wire_fee_time_inconsistencies %}
+ {\tt {{ item.type }} } & {{ item.time }} & {{ item.diagnostic }} \\ \hline
+{% endfor %}
+ \end{longtable}
+{% endif %}
+
+
+
\subsection{Other issues}
This section describes issues found that do not have a clear financial
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 7016dc701..cd1ee0d27 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -3,14 +3,14 @@
Copyright (C) 2016, 2017 Inria
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
+ terms of the GNU Affero Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.
- You should have received a copy of the GNU General Public License along with
+ You should have received a copy of the GNU Affero Public License along with
TALER; see the file COPYING. If not, see
*/
/**
@@ -210,6 +210,11 @@ static json_t *report_aggregation_fee_balances;
*/
static json_t *report_amount_arithmetic_inconsistencies;
+/**
+ * Array of reports about wire fees being ambiguous in terms of validity periods.
+ */
+static json_t *report_fee_time_inconsistencies;
+
/**
* Profits the exchange made by bad amount calculations.
*/
@@ -2303,11 +2308,24 @@ get_wire_fee (struct AggregationContext *ac,
pos->prev,
wfi);
/* Check non-overlaping fee invariant */
- /* TODO (#5177): report problems more nicely? */
- if (NULL != wfi->prev)
- GNUNET_break (wfi->prev->end_date.abs_value_us <= wfi->start_date.abs_value_us);
- if (NULL != wfi->next)
- GNUNET_break (wfi->next->start_date.abs_value_us >= wfi->end_date.abs_value_us);
+ if ( (NULL != wfi->prev) &&
+ (wfi->prev->end_date.abs_value_us > wfi->start_date.abs_value_us) )
+ {
+ report (report_fee_time_inconsistencies,
+ json_pack ("{s:s, s:s, s:s}",
+ "type", type,
+ "diagnostic", "start date before previous end date",
+ "time", GNUNET_STRINGS_absolute_time_to_string (wfi->start_date)));
+ }
+ if ( (NULL != wfi->next) &&
+ (wfi->next->start_date.abs_value_us >= wfi->end_date.abs_value_us) )
+ {
+ report (report_fee_time_inconsistencies,
+ json_pack ("{s:s, s:s, s:s}",
+ "type", type,
+ "diagnostic", "end date date after next start date",
+ "time", GNUNET_STRINGS_absolute_time_to_string (wfi->end_date)));
+ }
return &wfi->wire_fee;
}
@@ -4085,6 +4103,8 @@ run (void *cls,
(report_amount_arithmetic_inconsistencies = json_array ()));
GNUNET_assert (NULL !=
(report_bad_sig_losses = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_fee_time_inconsistencies = json_array ()));
setup_sessions_and_run ();
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Audit complete\n");
@@ -4108,7 +4128,8 @@ run (void *cls,
" s:o, s:o, s:o, s:o, s:o,"
" s:o, s:o, s:o, s:o, s:o,"
" s:o, s:o, s:o, s:o, s:o,"
- " s:o, s:o, s:o, s:o, s:o}",
+ " s:o, s:o, s:o, s:o, s:o,"
+ " s:o }",
/* blocks of 5 for easier counting/matching to format string */
/* block */
"reserve_balance_insufficient_inconsistencies",
@@ -4175,9 +4196,10 @@ run (void *cls,
"total_arithmetic_delta_minus",
TALER_JSON_from_amount (&total_arithmetic_delta_minus),
"total_aggregation_fee_income",
- TALER_JSON_from_amount (&total_aggregation_fee_income)
+ TALER_JSON_from_amount (&total_aggregation_fee_income),
/* block */
- );
+ "wire_fee_time_inconsistencies",
+ report_fee_time_inconsistencies);
GNUNET_break (NULL != report);
json_dumpf (report,
stdout,
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
index a9a4e8c81..9f16794d2 100644
--- a/src/auditor/taler-wire-auditor.c
+++ b/src/auditor/taler-wire-auditor.c
@@ -159,6 +159,12 @@ static json_t *report_missattribution_in_inconsistencies;
*/
static json_t *report_row_inconsistencies;
+/**
+ * Array of reports about inconcistencies in the database about
+ * the incoming wire transfers (exchange is not exactly to blame).
+ */
+static json_t *report_wire_format_inconsistencies;
+
/**
* Array of reports about minor row inconcistencies.
*/
@@ -201,6 +207,11 @@ static struct TALER_Amount total_missattribution_in;
*/
static struct TALER_Amount total_amount_lag;
+/**
+ * Total amount affected by wire format trouble.s
+ */
+static struct TALER_Amount total_wire_format_amount;
+
/**
* Amount of zero in our currency.
*/
@@ -324,7 +335,7 @@ do_shutdown (void *cls)
GNUNET_assert (NULL != 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,"
- " s:o, s:o }",
+ " s:o, s:o, s:o, s:o }",
/* blocks of 5 */
"wire_out_amount_inconsistencies",
report_wire_out_inconsistencies,
@@ -348,6 +359,10 @@ do_shutdown (void *cls)
"row_minor_inconsistencies",
report_row_minor_inconsistencies,
/* block */
+ "total_wire_format_amount",
+ TALER_JSON_from_amount (&total_wire_format_amount),
+ "wire_format_inconsistencies",
+ report_wire_format_inconsistencies,
"total_amount_lag",
TALER_JSON_from_amount (&total_bad_amount_in_minus),
"lag_details",
@@ -363,6 +378,7 @@ do_shutdown (void *cls)
report_row_minor_inconsistencies = NULL;
report_missattribution_in_inconsistencies = NULL;
report_lags = NULL;
+ report_wire_format_inconsistencies = NULL;
}
if (NULL != hh)
{
@@ -846,18 +862,17 @@ history_debit_cb (void *cls,
row_off_size,
&rowh);
GNUNET_asprintf (&diagnostic,
- "malformed wire transfer subject `%s'",
+ "malformed subject `%8s...'",
details->wtid_s);
- report (report_row_inconsistencies,
- json_pack ("{s:s, s:I, s:o, s:o, s:s}",
- "table", "bank wire log",
- "row", (json_int_t) 0,
+ GNUNET_break (GNUNET_OK ==
+ TALER_amount_add (&total_wire_format_amount,
+ &total_wire_format_amount,
+ &details->amount));
+ report (report_wire_format_inconsistencies,
+ json_pack ("{s:o, s:o, s:s}",
"amount", TALER_JSON_from_amount (&details->amount),
"wire_offset_hash", GNUNET_JSON_from_data_auto (&rowh),
"diagnostic", diagnostic));
- /* TODO (#5177): report generator currently ignores 'amount' for this
- table, maybe use a different table to report this issue! */
- /* TODO: add 'amount' to some total amount that was badly wired! */
GNUNET_free (diagnostic);
return GNUNET_SYSERR;
}
@@ -881,18 +896,17 @@ history_debit_cb (void *cls,
row_off_size,
&rowh);
GNUNET_asprintf (&diagnostic,
- "duplicate wire transfer subject `%s'",
+ "duplicate subject hash `%8s...'",
TALER_B2S (&roi->subject_hash));
- report (report_row_inconsistencies,
- json_pack ("{s:s, s:I, s:o, s:o, s:s}",
- "table", "bank wire log",
- "row", (json_int_t) 0,
+ GNUNET_break (GNUNET_OK ==
+ TALER_amount_add (&total_wire_format_amount,
+ &total_wire_format_amount,
+ &details->amount));
+ report (report_wire_format_inconsistencies,
+ json_pack ("{s:o, s:o, s:s}",
"amount", TALER_JSON_from_amount (&details->amount),
"wire_offset_hash", GNUNET_JSON_from_data_auto (&rowh),
"diagnostic", diagnostic));
- /* TODO (#5177): report generator currently ignores 'amount' for this
- table, maybe use a different table to report this issue! */
- /* TODO: add 'amount' to some total amount that was badly wired! */
GNUNET_free (diagnostic);
return GNUNET_SYSERR;
}
@@ -1381,6 +1395,8 @@ run (void *cls,
(report_reserve_in_inconsistencies = json_array ()));
GNUNET_assert (NULL !=
(report_row_minor_inconsistencies = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_wire_format_inconsistencies = json_array ()));
GNUNET_assert (NULL !=
(report_row_inconsistencies = json_array ()));
GNUNET_assert (NULL !=
@@ -1405,6 +1421,9 @@ run (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (currency,
&total_amount_lag));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_get_zero (currency,
+ &total_wire_format_amount));
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (currency,
&zero));