more work on wire auditor and reporting (#4958)
This commit is contained in:
parent
45c443f348
commit
f8af22b882
4
.gitignore
vendored
4
.gitignore
vendored
@ -88,3 +88,7 @@ contrib/taler-exchange.tag
|
|||||||
doxygen-doc/
|
doxygen-doc/
|
||||||
src/exchange-lib/test_exchange_api_keys_cherry_picking
|
src/exchange-lib/test_exchange_api_keys_cherry_picking
|
||||||
src/auditor/taler-wire-auditor
|
src/auditor/taler-wire-auditor
|
||||||
|
contrib/auditor-report.aux
|
||||||
|
contrib/auditor-report.log
|
||||||
|
contrib/auditor-report.tex
|
||||||
|
contrib/auditor-report.pdf
|
||||||
|
@ -311,11 +311,130 @@ public key for ``payback-master'' operations.
|
|||||||
|
|
||||||
\subsection{Actual incoming wire transfers}
|
\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}
|
\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}
|
\section{Minor irregularities}
|
||||||
|
|
||||||
@ -358,6 +477,39 @@ translate into a financial loss (yet).
|
|||||||
{% endif %}
|
{% 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}
|
\subsection{Other issues}
|
||||||
|
|
||||||
This section describes issues found that do not have a clear financial
|
This section describes issues found that do not have a clear financial
|
||||||
@ -470,6 +622,34 @@ implications.
|
|||||||
{% endif %}
|
{% 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}
|
\end{document}
|
||||||
|
@ -1,14 +1,19 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python
|
||||||
# This file is in the public domain.
|
# 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.
|
First command-line argument must be the JSON input from taler-auditor.
|
||||||
The tool reads the template from stdin and writes
|
Second command-line argument must be the JSON input from the
|
||||||
the expanded output to stdout.
|
taler-wire-auditor.
|
||||||
|
|
||||||
|
The tool then reads the template from stdin and writes the expanded
|
||||||
|
output to stdout.
|
||||||
|
|
||||||
|
TODO: proper installation, man page, error handling, --help option.
|
||||||
|
|
||||||
@author Christian Grothoff
|
@author Christian Grothoff
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
@ -23,10 +28,13 @@ class StdinLoader(BaseLoader):
|
|||||||
def get_source(self, environment, template):
|
def get_source(self, environment, template):
|
||||||
source = sys.stdin.read().decode('utf-8')
|
source = sys.stdin.read().decode('utf-8')
|
||||||
return source, self.path, lambda: false
|
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(),
|
jinjaEnv = jinja2.Environment(loader=StdinLoader(),
|
||||||
lstrip_blocks=True,
|
lstrip_blocks=True,
|
||||||
@ -35,4 +43,4 @@ jinjaEnv = jinja2.Environment(loader=StdinLoader(),
|
|||||||
autoescape=False)
|
autoescape=False)
|
||||||
tmpl = jinjaEnv.get_template('stdin');
|
tmpl = jinjaEnv.get_template('stdin');
|
||||||
|
|
||||||
print(tmpl.render(data = jsonData))
|
print(tmpl.render(data = jsonData1, wire = jsonData2))
|
||||||
|
@ -39,6 +39,7 @@ taler_wire_auditor_LDADD = \
|
|||||||
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
|
$(top_builddir)/src/exchangedb/libtalerexchangedb.la \
|
||||||
$(top_builddir)/src/auditordb/libtalerauditordb.la \
|
$(top_builddir)/src/auditordb/libtalerauditordb.la \
|
||||||
-ljansson \
|
-ljansson \
|
||||||
|
-lgnunetjson \
|
||||||
-lgnunetutil
|
-lgnunetutil
|
||||||
|
|
||||||
taler_auditor_sign_SOURCES = \
|
taler_auditor_sign_SOURCES = \
|
||||||
|
@ -130,7 +130,23 @@ static void *out_wire_off;
|
|||||||
static size_t wire_off_size;
|
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;
|
static json_t *report_row_inconsistencies;
|
||||||
|
|
||||||
@ -139,17 +155,49 @@ static json_t *report_row_inconsistencies;
|
|||||||
*/
|
*/
|
||||||
static json_t *report_row_minor_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 **************************** */
|
/* ***************************** Shutdown **************************** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry in map with wire information we expect to obtain from the
|
* Entry in map with wire information we expect to obtain from the
|
||||||
* bank later.
|
* bank later.
|
||||||
*/
|
*/
|
||||||
struct ReserveInInfo
|
struct ReserveInInfo
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash of expected row offset.
|
* Hash of expected row offset.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_HashCode row_off_hash;
|
struct GNUNET_HashCode row_off_hash;
|
||||||
@ -168,18 +216,18 @@ struct ReserveInInfo
|
|||||||
* RowID in reserves_in table.
|
* RowID in reserves_in table.
|
||||||
*/
|
*/
|
||||||
uint64_t rowid;
|
uint64_t rowid;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entry in map with wire information we expect to obtain from the
|
* Entry in map with wire information we expect to obtain from the
|
||||||
* #edb later.
|
* #edb later.
|
||||||
*/
|
*/
|
||||||
struct ReserveOutInfo
|
struct ReserveOutInfo
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hash of the wire transfer subject.
|
* Hash of the wire transfer subject.
|
||||||
*/
|
*/
|
||||||
struct GNUNET_HashCode subject_hash;
|
struct GNUNET_HashCode subject_hash;
|
||||||
@ -188,7 +236,7 @@ struct ReserveOutInfo
|
|||||||
* Expected details about the wire transfer.
|
* Expected details about the wire transfer.
|
||||||
*/
|
*/
|
||||||
struct TALER_WIRE_TransferDetails details;
|
struct TALER_WIRE_TransferDetails details;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -253,11 +301,32 @@ do_shutdown (void *cls)
|
|||||||
if (NULL != report_row_inconsistencies)
|
if (NULL != report_row_inconsistencies)
|
||||||
{
|
{
|
||||||
json_t *report;
|
json_t *report;
|
||||||
|
|
||||||
GNUNET_assert (NULL != report_row_minor_inconsistencies);
|
GNUNET_assert (NULL != report_row_minor_inconsistencies);
|
||||||
report = json_pack ("{s:o, s:o}",
|
report = json_pack ("{s:o, s:o, s:o, s:o, s:o,"
|
||||||
"row-inconsistencies", report_row_inconsistencies,
|
" s:o, s:o, s:o, s:o, s:o }",
|
||||||
"row-minor-inconsistencies", report_row_minor_inconsistencies);
|
/* 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,
|
json_dumpf (report,
|
||||||
stdout,
|
stdout,
|
||||||
JSON_INDENT (2));
|
JSON_INDENT (2));
|
||||||
@ -313,7 +382,7 @@ do_shutdown (void *cls)
|
|||||||
*
|
*
|
||||||
* @param array report array to append @a object to
|
* @param array report array to append @a object to
|
||||||
* @param object object to append, should be check that it is not NULL
|
* @param object object to append, should be check that it is not NULL
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
report (json_t *array,
|
report (json_t *array,
|
||||||
json_t *object)
|
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 ****************** */
|
/* *************************** General transaction logic ****************** */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -475,15 +503,15 @@ commit (enum GNUNET_DB_QueryStatus qs)
|
|||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
wire_out_cb (void *cls,
|
wire_out_cb (void *cls,
|
||||||
uint64_t rowid,
|
uint64_t rowid,
|
||||||
struct GNUNET_TIME_Absolute date,
|
struct GNUNET_TIME_Absolute date,
|
||||||
const struct TALER_WireTransferIdentifierRawP *wtid,
|
const struct TALER_WireTransferIdentifierRawP *wtid,
|
||||||
const json_t *wire,
|
const json_t *wire,
|
||||||
const struct TALER_Amount *amount)
|
const struct TALER_Amount *amount)
|
||||||
{
|
{
|
||||||
struct GNUNET_HashCode key;
|
struct GNUNET_HashCode key;
|
||||||
struct ReserveOutInfo *roi;
|
struct ReserveOutInfo *roi;
|
||||||
|
|
||||||
GNUNET_CRYPTO_hash (wtid,
|
GNUNET_CRYPTO_hash (wtid,
|
||||||
sizeof (struct TALER_WireTransferIdentifierRawP),
|
sizeof (struct TALER_WireTransferIdentifierRawP),
|
||||||
&key);
|
&key);
|
||||||
@ -491,37 +519,108 @@ wire_out_cb (void *cls,
|
|||||||
&key);
|
&key);
|
||||||
if (NULL == roi)
|
if (NULL == roi)
|
||||||
{
|
{
|
||||||
/* FIXME (#4963): do proper logging! */
|
/* Wire transfer was not made (yet) at all (but would have been
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
justified), so the entire amount is missing / still to be done.
|
||||||
"Failed to find wire transfer `%s' over %s at `%s' in exchange database!\n",
|
This is moderately harmless, it might just be that the aggreator
|
||||||
TALER_B2S (wtid),
|
has not yet fully caught up with the transfers it should do. */
|
||||||
TALER_amount2s (amount),
|
report (report_wire_out_inconsistencies,
|
||||||
GNUNET_STRINGS_absolute_time_to_string (date));
|
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;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
if (0 != TALER_amount_cmp (&roi->details.amount,
|
|
||||||
amount))
|
|
||||||
{
|
|
||||||
report_row_inconsistency ("reserves_out",
|
|
||||||
rowid,
|
|
||||||
"wire amount missmatch");
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
|
||||||
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,
|
if (! json_equal ((json_t *) wire,
|
||||||
roi->details.account_details))
|
roi->details.account_details))
|
||||||
{
|
{
|
||||||
report_row_inconsistency ("reserves_out",
|
/* Destination bank account is wrong in actual wire transfer, so
|
||||||
rowid,
|
we should count the wire transfer as entirely spurious, and
|
||||||
"receiver account missmatch");
|
additionally consider the justified wire transfer as missing. */
|
||||||
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_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 (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 (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_assert (GNUNET_OK ==
|
||||||
GNUNET_CONTAINER_multihashmap_remove (out_map,
|
GNUNET_CONTAINER_multihashmap_remove (out_map,
|
||||||
&key,
|
&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 cls NULL
|
||||||
* @param key unused key
|
* @param key unused key
|
||||||
* @param value the `struct ReserveOutInfo` to free
|
* @param value the `struct ReserveOutInfo` to report
|
||||||
* @return #GNUNET_OK
|
* @return #GNUNET_OK
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -549,12 +649,18 @@ complain_out_not_found (void *cls,
|
|||||||
{
|
{
|
||||||
struct ReserveOutInfo *roi = value;
|
struct ReserveOutInfo *roi = value;
|
||||||
|
|
||||||
(void) roi;
|
report (report_wire_out_inconsistencies,
|
||||||
/* FIXME (#4963): log more precisely which wire transfer (and amount)
|
json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
|
||||||
is bogus. */
|
"row", (json_int_t) 0,
|
||||||
report_row_inconsistency ("reserves_out",
|
"amount_wired", TALER_JSON_from_amount (&roi->details.amount),
|
||||||
UINT64_MAX,
|
"amount_justified", TALER_JSON_from_amount (&zero),
|
||||||
"matching wire transfer not found");
|
"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;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,7 +673,7 @@ static void
|
|||||||
check_exchange_wire_out ()
|
check_exchange_wire_out ()
|
||||||
{
|
{
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
enum GNUNET_DB_QueryStatus qs;
|
||||||
|
|
||||||
qs = edb->select_wire_out_above_serial_id (edb->cls,
|
qs = edb->select_wire_out_above_serial_id (edb->cls,
|
||||||
esession,
|
esession,
|
||||||
pp.last_wire_out_serial_id,
|
pp.last_wire_out_serial_id,
|
||||||
@ -582,14 +688,14 @@ check_exchange_wire_out ()
|
|||||||
}
|
}
|
||||||
GNUNET_CONTAINER_multihashmap_iterate (out_map,
|
GNUNET_CONTAINER_multihashmap_iterate (out_map,
|
||||||
&complain_out_not_found,
|
&complain_out_not_found,
|
||||||
NULL);
|
NULL);
|
||||||
/* clean up (technically redundant, but nicer) */
|
/* clean up */
|
||||||
GNUNET_CONTAINER_multihashmap_iterate (out_map,
|
GNUNET_CONTAINER_multihashmap_iterate (out_map,
|
||||||
&free_roi,
|
&free_roi,
|
||||||
NULL);
|
NULL);
|
||||||
GNUNET_CONTAINER_multihashmap_destroy (out_map);
|
GNUNET_CONTAINER_multihashmap_destroy (out_map);
|
||||||
out_map = NULL;
|
out_map = NULL;
|
||||||
|
|
||||||
/* conclude with: */
|
/* conclude with: */
|
||||||
commit (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT);
|
commit (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT);
|
||||||
GNUNET_SCHEDULER_shutdown ();
|
GNUNET_SCHEDULER_shutdown ();
|
||||||
@ -616,7 +722,7 @@ history_debit_cb (void *cls,
|
|||||||
const struct TALER_WIRE_TransferDetails *details)
|
const struct TALER_WIRE_TransferDetails *details)
|
||||||
{
|
{
|
||||||
struct ReserveOutInfo *roi;
|
struct ReserveOutInfo *roi;
|
||||||
|
|
||||||
if (TALER_BANK_DIRECTION_NONE == dir)
|
if (TALER_BANK_DIRECTION_NONE == dir)
|
||||||
{
|
{
|
||||||
/* end of iteration, now check wire_out to see
|
/* end of iteration, now check wire_out to see
|
||||||
@ -640,9 +746,12 @@ history_debit_cb (void *cls,
|
|||||||
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
|
GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
|
||||||
report_row_inconsistency ("bank wire log",
|
report (report_row_inconsistencies,
|
||||||
UINT64_MAX,
|
json_pack ("{s:s, s:I, s:o, s:s}",
|
||||||
"duplicate wire offset");
|
"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_SYSERR;
|
||||||
}
|
}
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
@ -727,9 +836,12 @@ reserve_in_cb (void *cls,
|
|||||||
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
|
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
|
||||||
{
|
{
|
||||||
GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
|
GNUNET_break_op (0); /* duplicate wire offset is not allowed! */
|
||||||
report_row_inconsistency ("reserves_in",
|
report (report_row_inconsistencies,
|
||||||
rowid,
|
json_pack ("{s:s, s:I, s:o, s:s}",
|
||||||
"duplicate wire offset");
|
"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;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
pp.last_reserve_in_serial_id = rowid + 1;
|
pp.last_reserve_in_serial_id = rowid + 1;
|
||||||
@ -752,9 +864,18 @@ complain_in_not_found (void *cls,
|
|||||||
{
|
{
|
||||||
struct ReserveInInfo *rii = value;
|
struct ReserveInInfo *rii = value;
|
||||||
|
|
||||||
report_row_inconsistency ("reserves_in",
|
report (report_reserve_in_inconsistencies,
|
||||||
rii->rowid,
|
json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
|
||||||
"matching wire transfer not found");
|
"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;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -780,7 +901,7 @@ history_credit_cb (void *cls,
|
|||||||
{
|
{
|
||||||
struct ReserveInInfo *rii;
|
struct ReserveInInfo *rii;
|
||||||
struct GNUNET_HashCode key;
|
struct GNUNET_HashCode key;
|
||||||
|
|
||||||
if (TALER_BANK_DIRECTION_NONE == dir)
|
if (TALER_BANK_DIRECTION_NONE == dir)
|
||||||
{
|
{
|
||||||
/* end of operation */
|
/* end of operation */
|
||||||
@ -831,42 +952,110 @@ history_credit_cb (void *cls,
|
|||||||
if (row_off_size != rii->row_off_size)
|
if (row_off_size != rii->row_off_size)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
report_row_inconsistency ("reserves_in",
|
report (report_row_inconsistencies,
|
||||||
rii->rowid,
|
json_pack ("{s:s, s:o, s:o, s:s}",
|
||||||
"wire reference size missmatch");
|
"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;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
if (0 != TALER_amount_cmp (&rii->details.amount,
|
|
||||||
&details->amount))
|
|
||||||
{
|
|
||||||
report_row_inconsistency ("reserves_in",
|
|
||||||
rii->rowid,
|
|
||||||
"wire amount 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,
|
if (0 != memcmp (&details->reserve_pub,
|
||||||
&rii->details.reserve_pub,
|
&rii->details.reserve_pub,
|
||||||
sizeof (struct TALER_ReservePublicKeyP)))
|
sizeof (struct TALER_ReservePublicKeyP)))
|
||||||
{
|
{
|
||||||
report_row_inconsistency ("reserves_in",
|
report (report_reserve_in_inconsistencies,
|
||||||
rii->rowid,
|
json_pack ("{s:I, s:o, s:o, s:o, s:s, s:s}",
|
||||||
"reserve public key / wire subject missmatch");
|
"row", GNUNET_JSON_from_data (row_off, row_off_size),
|
||||||
return GNUNET_OK;
|
"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,
|
if (! json_equal (details->account_details,
|
||||||
rii->details.account_details))
|
rii->details.account_details))
|
||||||
{
|
{
|
||||||
report_row_minor_inconsistency ("reserves_in",
|
report (report_missattribution_in_inconsistencies,
|
||||||
rii->rowid,
|
json_pack ("{s:s, s:o, s:o}",
|
||||||
"sender account missmatch");
|
"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_assert (GNUNET_OK ==
|
||||||
GNUNET_CONTAINER_multihashmap_remove (in_map,
|
GNUNET_CONTAINER_multihashmap_remove (in_map,
|
||||||
&key,
|
&key,
|
||||||
@ -1002,9 +1191,32 @@ run (void *cls,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GNUNET_assert (NULL !=
|
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 !=
|
GNUNET_assert (NULL !=
|
||||||
(report_row_minor_inconsistencies = json_array ()));
|
(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,
|
qsx = adb->get_wire_auditor_progress (adb->cls,
|
||||||
asession,
|
asession,
|
||||||
&master_pub,
|
&master_pub,
|
||||||
|
Loading…
Reference in New Issue
Block a user