working on #4962
This commit is contained in:
parent
c5f9c0ca88
commit
cc09fbbb29
@ -58,11 +58,11 @@ This section analyzes the income of the exchange operator from fees.
|
|||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
|
|
||||||
\section{Irregularities}
|
\section{Major irregularities}
|
||||||
|
|
||||||
This section describes the possible irregularities that the auditor
|
This section describes the possible major irregularities that the
|
||||||
has checked, and lists all of the actual irregularities encountered
|
auditor has checked, and lists all of the actual irregularities
|
||||||
in detail.
|
encountered in detail.
|
||||||
|
|
||||||
\subsection{Emergencies}
|
\subsection{Emergencies}
|
||||||
|
|
||||||
@ -108,11 +108,8 @@ compromise.
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
\subsection{Reserve inconsistencies}
|
|
||||||
|
|
||||||
{% if data.reserve_inconsistencies|length() == 0 %}
|
|
||||||
{\bf No reserve inconsistencies detected.}
|
|
||||||
{% else %}
|
|
||||||
\begin{longtable}{p{1.5cm}|rl|rl|p{4cm}}
|
\begin{longtable}{p{1.5cm}|rl|rl|p{4cm}}
|
||||||
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Observed}} & {\bf Diagnostic} \\ \hline \hline
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Observed}} & {\bf Diagnostic} \\ \hline \hline
|
||||||
\endfirsthead
|
\endfirsthead
|
||||||
@ -138,6 +135,220 @@ compromise.
|
|||||||
{{ item.diagnostic }} \\ \hline
|
{{ item.diagnostic }} \\ \hline
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
\end{longtable}
|
\end{longtable}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Reserve withdrawals exceeding balance}
|
||||||
|
|
||||||
|
This section highlights cases where more coins were withdrawn from a
|
||||||
|
reserve than the reserve contained funding for. This is a serious
|
||||||
|
compromise resulting in proportional financial losses to the exchange.
|
||||||
|
|
||||||
|
|
||||||
|
{% if data.reserve_balance_insufficient_inconsistencies|length() == 0 %}
|
||||||
|
{\bf All withdrawals were covered by sufficient reserve funding.}
|
||||||
|
{% else %}
|
||||||
|
\begin{longtable}{p{4.5cm}|rl}
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Loss}} \\ \hline \hline
|
||||||
|
\endfirsthead
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Loss}} \\ \hline \hline
|
||||||
|
\endhead
|
||||||
|
\hline \hline
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Loss}}
|
||||||
|
\endfoot
|
||||||
|
\hline
|
||||||
|
{\bf Total loss} & &
|
||||||
|
{{ data.total_loss_balance_insufficient.value}}.{{ data.total_loss_balance_insufficient.fraction}} & {{ data.total_loss_balance_insufficient.currency}} \\
|
||||||
|
\caption{Reserves with withdrawals higher than reserve funding.}
|
||||||
|
\label{table:reserve:balance_insufficient}
|
||||||
|
\endlastfoot
|
||||||
|
{% for item in data.reserve_balance_insufficient_inconsistencies %}
|
||||||
|
\multicolumn{3}{l}{ {\tt {{ item.reserve_pub }} } } \\
|
||||||
|
\nopagebreak
|
||||||
|
&
|
||||||
|
{{ item.loss.value }}.{{ item.loss.fraction }} &
|
||||||
|
{{ item.loss.currency }} \\ \hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtable}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Claimed outgoing wire transfers}
|
||||||
|
|
||||||
|
This section is about the exchange's database containing a
|
||||||
|
justification to make an outgoing wire transfer for an aggregated
|
||||||
|
amount for various deposits. It is reported as an inconsistency if the
|
||||||
|
amount claimed for the wire transfer does not match up the deposits
|
||||||
|
aggregated. This is about a {\em claimed} outgoing wire transfer as
|
||||||
|
violations do not imply that the wire transfer was actually made (as
|
||||||
|
that is a separate check). Note that not making the wire transfer
|
||||||
|
would be reported separately in Section~\ref{sec:wire_check_out}.
|
||||||
|
|
||||||
|
|
||||||
|
{% if data.reserve_wire_out_inconsistencies|length() == 0 %}
|
||||||
|
{\bf All aggregations matched up.}
|
||||||
|
{% else %}
|
||||||
|
\begin{longtable}{p{1.5cm}|l|rl|rl}
|
||||||
|
{\bf Destination account} & {\bf Database row} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Claimed}} \\ \hline \hline
|
||||||
|
\endfirsthead
|
||||||
|
{\bf Destination account} & {\bf Database row} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Claimed}} \\ \hline \hline
|
||||||
|
\endhead
|
||||||
|
\hline \hline
|
||||||
|
{\bf Destination account} & {\bf Database row} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Claimed}} \\
|
||||||
|
\endfoot
|
||||||
|
\hline
|
||||||
|
{\bf Total deltas} & &
|
||||||
|
{{ data.total_wire_out_delta_plus.value}}.{{ data.total_wire_out_delta_plus.fraction}} & {{ data.total_wire_out_delta_plus.currency}} &
|
||||||
|
- {{ data.total_wire_out_delta_minus.value}}.{{ data.total_wire_out_delta_minus.fraction}} & {{ data.total_wire_out_delta_minus.currency}} \\
|
||||||
|
\caption{Claimed wire out aggregate totals not matching up.}
|
||||||
|
\label{table:reserve:wire_out_balance_inconsistencies}
|
||||||
|
\endlastfoot
|
||||||
|
{% for item in data.wire_out_inconsistencies %}
|
||||||
|
\multicolumn{6}{l}{ {\tt {{ item.destination_account }} } } \\
|
||||||
|
\nopagebreak
|
||||||
|
& {{ item.rowid }} &
|
||||||
|
{{ item.expected.value }}.{{ item.expected.fraction }} &
|
||||||
|
{{ item.expected.currency }} &
|
||||||
|
{{ item.claimed.value }}.{{ item.claimed.fraction }} &
|
||||||
|
{{ item.claimed.currency }} \\ \hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtable}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Coin history inconsistencies}
|
||||||
|
|
||||||
|
TODO.
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Actual incoming wire transfers}
|
||||||
|
|
||||||
|
TBD. See bug 4958.
|
||||||
|
|
||||||
|
\subsection{Actual outgoing wire transfers} \label{sec:wire_check_out}
|
||||||
|
|
||||||
|
TBD. See bug 4958.
|
||||||
|
|
||||||
|
\section{Minor irregularities}
|
||||||
|
|
||||||
|
\subsection{Incorrect reserve balance summary in database}
|
||||||
|
|
||||||
|
This section highlights cases where the reserve balance summary
|
||||||
|
in the database does not match the calculations made by the auditor.
|
||||||
|
Deltas may indicate a corrupt database, but do not necessarily
|
||||||
|
translate into a financial loss (yet).
|
||||||
|
|
||||||
|
|
||||||
|
{% if data.reserve_balance_summary_wrong_inconsistencies|length() == 0 %}
|
||||||
|
{\bf All balances matched up.}
|
||||||
|
{% else %}
|
||||||
|
\begin{longtable}{p{1.5cm}|rl|rl}
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Auditor}} & \multicolumn{2}{|c|}{ {\bf Exchange}} \\ \hline \hline
|
||||||
|
\endfirsthead
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Auditor}} & \multicolumn{2}{|c|}{ {\bf Exchange}} \\ \hline \hline
|
||||||
|
\endhead
|
||||||
|
\hline \hline
|
||||||
|
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Auditor}} & \multicolumn{2}{|c|}{ {\bf Exchange}}
|
||||||
|
\endfoot
|
||||||
|
\hline
|
||||||
|
{\bf Total deltas} & &
|
||||||
|
{{ data.total_balance_summary_delta_plus.value}}.{{ data.total_balance_summary_delta_plus.fraction}} & {{ data.total_balance_summary_delta_plus.currency}} &
|
||||||
|
- {{ data.total_balance_summary_delta_minus.value}}.{{ data.total_balance_summary_delta_minus.fraction}} & {{ data.total_balance_summary_delta_minus.currency}} \\
|
||||||
|
\caption{Reserves balances not matching up.}
|
||||||
|
\label{table:reserve:balance_inconsistencies}
|
||||||
|
\endlastfoot
|
||||||
|
{% for item in data.reserve_balance_summary_wrong_inconsistencies %}
|
||||||
|
\multicolumn{5}{l}{ {\tt {{ item.reserve_pub }} } } \\
|
||||||
|
\nopagebreak
|
||||||
|
&
|
||||||
|
{{ item.auditor.value }}.{{ item.auditor.fraction }} &
|
||||||
|
{{ item.auditor.currency }} &
|
||||||
|
{{ item.exchange.value }}.{{ item.exchange.fraction }} &
|
||||||
|
{{ item.exchange.currency }} \\ \hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtable}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Delays and timing}
|
||||||
|
|
||||||
|
This section describes issues that are likely caused simply by
|
||||||
|
some job process of the exchange not running properly or not having
|
||||||
|
caught up with the work load yet.
|
||||||
|
|
||||||
|
\subsection{Delayed closure of reserves}
|
||||||
|
|
||||||
|
This section describes cases where the exchange did not
|
||||||
|
close a reserve and wire back the remaining funds when the
|
||||||
|
reserve expired.
|
||||||
|
|
||||||
|
|
||||||
|
{% if data.reserve_not_closed_inconsistencies|length() == 0 %}
|
||||||
|
{\bf All expired reserves were closed.}
|
||||||
|
{% else %}
|
||||||
|
\begin{longtable}{p{1.5cm}|c|rl}
|
||||||
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}} \\ \hline \hline
|
||||||
|
\endfirsthead
|
||||||
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}} \\ \hline \hline
|
||||||
|
\endhead
|
||||||
|
\hline \hline
|
||||||
|
{\bf Reserve} & {\bf Expired} & \multicolumn{2}{|c|}{ {\bf Balance}}
|
||||||
|
\endfoot
|
||||||
|
\hline
|
||||||
|
{\bf Sum} & &
|
||||||
|
{{ data.total_balance_reserve_not_closed.value}}.{{ data.total_balance_reserve_not_closed.fraction}} & {{ data.total_balance_reserve_not_closed.currency}} \\
|
||||||
|
\caption{Reserves not closed on time.}
|
||||||
|
\label{table:reserve:not_closed}
|
||||||
|
\endlastfoot
|
||||||
|
{% for item in data.reserve_not_closed_inconsistencies %}
|
||||||
|
\multicolumn{4}{l}{ {\tt {{ item.reserve_pub }} } } \\
|
||||||
|
\nopagebreak
|
||||||
|
&
|
||||||
|
{{ item.expiration_time }} &
|
||||||
|
{{ item.balance.value }}.{{ item.balance.fraction }} &
|
||||||
|
{{ item.balance.currency }} \\ \hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtable}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Denomination key invalid at time of withdrawal}
|
||||||
|
|
||||||
|
This section lists cases where a denomination key was not valid for
|
||||||
|
withdrawal at the time when the exchange claims to have signed a coin
|
||||||
|
with it. This would be irregular, but has no obvious financial
|
||||||
|
implications.
|
||||||
|
|
||||||
|
|
||||||
|
{% if data.denomination_key_validity_withdraw_inconsistencies|length() == 0 %}
|
||||||
|
{\bf All denomination keys were valid at the time of withdrawals.}
|
||||||
|
{% else %}
|
||||||
|
\begin{longtable}{p{7.5cm}|c}
|
||||||
|
{\bf Reserve} & {\bf Table row} \\
|
||||||
|
{\bf Denomination key hash} & {\bf Execution time} \\ \hline \hline
|
||||||
|
\endfirsthead
|
||||||
|
{\bf Reserve} & {\bf Table row} \\
|
||||||
|
{\bf Denomination key hash} & {\bf Execution time} \\ \hline \hline
|
||||||
|
\endhead
|
||||||
|
\hline \hline
|
||||||
|
{\bf Reserve} & {\bf Table row} \\
|
||||||
|
{\bf Denomination key hash} & {\bf Execution time} \\
|
||||||
|
\endfoot
|
||||||
|
\hline
|
||||||
|
{\bf Reserve} & {\bf Table row} \\
|
||||||
|
{\bf Denomination key hash} & {\bf Execution time} \\
|
||||||
|
\caption{Execution times not matching denomination key validity period.}
|
||||||
|
\label{table:withdraw:bad_time}
|
||||||
|
\endlastfoot
|
||||||
|
{% for item in data.denomination_key_validity_withdraw_inconsistencies %}
|
||||||
|
{\tt {{ item.reserve_pub }} } & {{ item.row }} \\
|
||||||
|
\nopagebreak
|
||||||
|
&
|
||||||
|
{\tt {{ item.denompub_h }} } & {{ item.execution_date }} \\ \hline
|
||||||
|
{% endfor %}
|
||||||
|
\end{longtable}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
\end{document}
|
\end{document}
|
||||||
|
@ -125,20 +125,65 @@ static json_t *report_emergencies;
|
|||||||
static json_t *report_row_inconsistencies;
|
static json_t *report_row_inconsistencies;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of reports about minor row inconcistencies.
|
* Array of reports about the denomination key not being
|
||||||
|
* valid at the time of withdrawal.
|
||||||
*/
|
*/
|
||||||
static json_t *report_row_minor_inconsistencies;
|
static json_t *denomination_key_validity_withdraw_inconsistencies;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of reports about reserve inconsitencies.
|
* Array of reports about reserve balance insufficient inconsitencies.
|
||||||
*/
|
*/
|
||||||
static json_t *report_reserve_inconsistencies;
|
static json_t *report_reserve_balance_insufficient_inconsistencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total amount reserves were charged beyond their balance.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_balance_insufficient_loss;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of reports about reserve balance summary wrong in database.
|
||||||
|
*/
|
||||||
|
static json_t *report_reserve_balance_summary_wrong_inconsistencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total delta between expected and stored reserve balance summaries,
|
||||||
|
* for positive deltas.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_balance_summary_delta_plus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total delta between expected and stored reserve balance summaries,
|
||||||
|
* for negative deltas.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_balance_summary_delta_minus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array of reports about reserve's not being closed inconsitencies.
|
||||||
|
*/
|
||||||
|
static json_t *report_reserve_not_closed_inconsistencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total amount affected by reserves not having been closed on time.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_balance_reserve_not_closed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of reports about irregular wire out entries.
|
* Array of reports about irregular wire out entries.
|
||||||
*/
|
*/
|
||||||
static json_t *report_wire_out_inconsistencies;
|
static json_t *report_wire_out_inconsistencies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total delta between calculated and stored wire out transfers,
|
||||||
|
* for positive deltas.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_wire_out_delta_plus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total delta between calculated and stored wire out transfers
|
||||||
|
* for negative deltas.
|
||||||
|
*/
|
||||||
|
static struct TALER_Amount total_wire_out_delta_minus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of reports about inconsistencies about coins.
|
* Array of reports about inconsistencies about coins.
|
||||||
*/
|
*/
|
||||||
@ -265,85 +310,6 @@ report_row_inconsistency (const char *table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report a global inconsistency with respect to a reserve.
|
|
||||||
*
|
|
||||||
* @param reserve_pub the affected reserve
|
|
||||||
* @param expected expected amount
|
|
||||||
* @param observed observed amount
|
|
||||||
* @param diagnostic message explaining what @a expected and @a observed refer to
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
report_reserve_inconsistency (const struct TALER_ReservePublicKeyP *reserve_pub,
|
|
||||||
const struct TALER_Amount *expected,
|
|
||||||
const struct TALER_Amount *observed,
|
|
||||||
const char *diagnostic)
|
|
||||||
{
|
|
||||||
report (report_reserve_inconsistencies,
|
|
||||||
json_pack ("{s:o, s:o, s:o, s:s}",
|
|
||||||
"reserve_pub",
|
|
||||||
GNUNET_JSON_from_data_auto (reserve_pub),
|
|
||||||
"expected",
|
|
||||||
TALER_JSON_from_amount (expected),
|
|
||||||
"observed",
|
|
||||||
TALER_JSON_from_amount (observed),
|
|
||||||
"diagnostic",
|
|
||||||
diagnostic));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Report a global inconsistency with respect to a wire transfer.
|
|
||||||
*
|
|
||||||
* @param destination wire transfer target account
|
|
||||||
* @param rowid which row is the inconsitency in
|
|
||||||
* @param expected expected amount
|
|
||||||
* @param observed observed amount
|
|
||||||
* @param diagnostic message explaining what @a expected and @a observed refer to
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
report_wire_out_inconsistency (const json_t *destination,
|
|
||||||
uint64_t rowid,
|
|
||||||
const struct TALER_Amount *expected,
|
|
||||||
const struct TALER_Amount *observed,
|
|
||||||
const char *diagnostic)
|
|
||||||
{
|
|
||||||
report (report_wire_out_inconsistencies,
|
|
||||||
json_pack ("{s:O, s:I, s:o, s:o, s:s}",
|
|
||||||
"destination_account",
|
|
||||||
destination,
|
|
||||||
"rowid",
|
|
||||||
(json_int_t) rowid,
|
|
||||||
"expected",
|
|
||||||
TALER_JSON_from_amount (expected),
|
|
||||||
"observed",
|
|
||||||
TALER_JSON_from_amount (observed),
|
|
||||||
"diagnostic",
|
|
||||||
diagnostic));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Report a global inconsistency with respect to a coin's history.
|
* Report a global inconsistency with respect to a coin's history.
|
||||||
*
|
*
|
||||||
@ -594,10 +560,6 @@ load_auditor_reserve_summary (struct ReserveSummary *rs)
|
|||||||
TALER_amount_cmp_currency (&rs->total_in,
|
TALER_amount_cmp_currency (&rs->total_in,
|
||||||
&rs->a_balance)) )
|
&rs->a_balance)) )
|
||||||
{
|
{
|
||||||
report_row_inconsistency ("auditor-reserve-info",
|
|
||||||
rowid,
|
|
||||||
"currencies for reserve differ");
|
|
||||||
/* TODO: find a sane way to continue... */
|
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
return GNUNET_DB_STATUS_HARD_ERROR;
|
||||||
}
|
}
|
||||||
@ -781,9 +743,12 @@ handle_reserve_out (void *cls,
|
|||||||
if ( (valid_start.abs_value_us > execution_date.abs_value_us) ||
|
if ( (valid_start.abs_value_us > execution_date.abs_value_us) ||
|
||||||
(expire_withdraw.abs_value_us < execution_date.abs_value_us) )
|
(expire_withdraw.abs_value_us < execution_date.abs_value_us) )
|
||||||
{
|
{
|
||||||
report_row_minor_inconsistency ("withdraw",
|
report (denomination_key_validity_withdraw_inconsistencies,
|
||||||
rowid,
|
json_pack ("{s:I, s:s, s:o, s:o}",
|
||||||
"denomination key not valid at time of withdrawal");
|
"row", (json_int_t) rowid,
|
||||||
|
"execution_date", GNUNET_STRINGS_absolute_time_to_string (execution_date),
|
||||||
|
"reserve_pub", GNUNET_JSON_from_data_auto (reserve_pub),
|
||||||
|
"denompub_h", GNUNET_JSON_from_data_auto (&wsrd.h_denomination_pub)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check reserve_sig */
|
/* check reserve_sig */
|
||||||
@ -1155,10 +1120,7 @@ verify_reserve_balance (void *cls,
|
|||||||
&rs->total_in,
|
&rs->total_in,
|
||||||
&rs->a_balance))
|
&rs->a_balance))
|
||||||
{
|
{
|
||||||
report_reserve_inconsistency (&rs->reserve_pub,
|
GNUNET_break (0);
|
||||||
&rs->total_in,
|
|
||||||
&rs->a_balance,
|
|
||||||
"could not add old balance to new balance");
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1167,19 +1129,62 @@ verify_reserve_balance (void *cls,
|
|||||||
&balance,
|
&balance,
|
||||||
&rs->total_out))
|
&rs->total_out))
|
||||||
{
|
{
|
||||||
report_reserve_inconsistency (&rs->reserve_pub,
|
struct TALER_Amount loss;
|
||||||
&rs->total_in,
|
|
||||||
|
GNUNET_break (GNUNET_SYSERR !=
|
||||||
|
TALER_amount_subtract (&loss,
|
||||||
&rs->total_out,
|
&rs->total_out,
|
||||||
"available balance insufficient to cover transfers");
|
&balance));
|
||||||
|
GNUNET_break (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_balance_insufficient_loss,
|
||||||
|
&total_balance_insufficient_loss,
|
||||||
|
&loss));
|
||||||
|
report (report_reserve_balance_insufficient_inconsistencies,
|
||||||
|
json_pack ("{s:o, s:o, s:o, s:s}",
|
||||||
|
"reserve_pub",
|
||||||
|
GNUNET_JSON_from_data_auto (&rs->reserve_pub),
|
||||||
|
"loss",
|
||||||
|
TALER_JSON_from_amount (&loss)));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (0 != TALER_amount_cmp (&balance,
|
if (0 != TALER_amount_cmp (&balance,
|
||||||
&reserve.balance))
|
&reserve.balance))
|
||||||
{
|
{
|
||||||
report_reserve_inconsistency (&rs->reserve_pub,
|
struct TALER_Amount delta;
|
||||||
|
|
||||||
|
if (0 < TALER_amount_cmp (&balance,
|
||||||
|
&reserve.balance))
|
||||||
|
{
|
||||||
|
/* balance > reserve.balance */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_subtract (&delta,
|
||||||
&balance,
|
&balance,
|
||||||
|
&reserve.balance));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_balance_summary_delta_plus,
|
||||||
|
&total_balance_summary_delta_plus,
|
||||||
|
&delta));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* balance < reserve.balance */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_subtract (&delta,
|
||||||
&reserve.balance,
|
&reserve.balance,
|
||||||
"computed balance does not match stored balance");
|
&balance));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_balance_summary_delta_minus,
|
||||||
|
&total_balance_summary_delta_minus,
|
||||||
|
&delta));
|
||||||
|
}
|
||||||
|
report (report_reserve_balance_summary_wrong_inconsistencies,
|
||||||
|
json_pack ("{s:o, s:o, s:o}",
|
||||||
|
"reserve_pub",
|
||||||
|
GNUNET_JSON_from_data_auto (&rs->reserve_pub),
|
||||||
|
"exchange",
|
||||||
|
TALER_JSON_from_amount (&reserve.balance),
|
||||||
|
"auditor",
|
||||||
|
TALER_JSON_from_amount (&balance)));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,16 +1194,18 @@ verify_reserve_balance (void *cls,
|
|||||||
( (0 != balance.value) ||
|
( (0 != balance.value) ||
|
||||||
(0 != balance.fraction) ) )
|
(0 != balance.fraction) ) )
|
||||||
{
|
{
|
||||||
struct TALER_Amount zero;
|
|
||||||
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (balance.currency,
|
TALER_amount_add (&total_balance_reserve_not_closed,
|
||||||
&zero));
|
&total_balance_reserve_not_closed,
|
||||||
|
&balance));
|
||||||
report_reserve_inconsistency (&rs->reserve_pub,
|
report (report_reserve_not_closed_inconsistencies,
|
||||||
&balance,
|
json_pack ("{s:o, s:o, s:s}",
|
||||||
&zero,
|
"reserve_pub",
|
||||||
"expired reserve needs to be closed");
|
GNUNET_JSON_from_data_auto (&rs->reserve_pub),
|
||||||
|
"balance",
|
||||||
|
TALER_JSON_from_amount (&balance),
|
||||||
|
"expiration_time",
|
||||||
|
GNUNET_STRINGS_absolute_time_to_string (rs->a_expiration_date)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add withdraw fees we encountered to totals */
|
/* Add withdraw fees we encountered to totals */
|
||||||
@ -2206,10 +2213,8 @@ check_wire_out_cb (void *cls,
|
|||||||
TALER_JSON_hash (wire,
|
TALER_JSON_hash (wire,
|
||||||
&wcc.h_wire))
|
&wcc.h_wire))
|
||||||
{
|
{
|
||||||
report_row_inconsistency ("wire_out",
|
GNUNET_break (0);
|
||||||
rowid,
|
return GNUNET_SYSERR;
|
||||||
"could not hash wire address");
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
}
|
||||||
qs = edb->lookup_wire_transfer (edb->cls,
|
qs = edb->lookup_wire_transfer (edb->cls,
|
||||||
esession,
|
esession,
|
||||||
@ -2256,20 +2261,13 @@ check_wire_out_cb (void *cls,
|
|||||||
wcc.method);
|
wcc.method);
|
||||||
if (NULL == plugin)
|
if (NULL == plugin)
|
||||||
{
|
{
|
||||||
report_row_inconsistency ("wire_out",
|
GNUNET_break (0);
|
||||||
rowid,
|
return GNUNET_SYSERR;
|
||||||
"could not load required wire plugin to validate");
|
|
||||||
return GNUNET_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GNUNET_SYSERR ==
|
GNUNET_break (GNUNET_SYSERR !=
|
||||||
plugin->amount_round (plugin->cls,
|
plugin->amount_round (plugin->cls,
|
||||||
&final_amount))
|
&final_amount));
|
||||||
{
|
|
||||||
report_row_minor_inconsistency ("wire_out",
|
|
||||||
rowid,
|
|
||||||
"wire plugin failed to round given amount");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the exchange's gain as the fees plus rounding differences! */
|
/* Calculate the exchange's gain as the fees plus rounding differences! */
|
||||||
if (GNUNET_OK !=
|
if (GNUNET_OK !=
|
||||||
@ -2297,11 +2295,44 @@ check_wire_out_cb (void *cls,
|
|||||||
if (0 != TALER_amount_cmp (amount,
|
if (0 != TALER_amount_cmp (amount,
|
||||||
&final_amount))
|
&final_amount))
|
||||||
{
|
{
|
||||||
report_wire_out_inconsistency (wire,
|
struct TALER_Amount delta;
|
||||||
rowid,
|
|
||||||
&final_amount,
|
if (0 < TALER_amount_cmp (amount,
|
||||||
|
&final_amount))
|
||||||
|
{
|
||||||
|
/* amount > final_amount */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_subtract (&delta,
|
||||||
amount,
|
amount,
|
||||||
"computed amount inconsistent with wire amount");
|
&final_amount));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_wire_out_delta_plus,
|
||||||
|
&total_wire_out_delta_plus,
|
||||||
|
&delta));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* amount < final_amount */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_subtract (&delta,
|
||||||
|
&final_amount,
|
||||||
|
amount));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_wire_out_delta_minus,
|
||||||
|
&total_wire_out_delta_minus,
|
||||||
|
&delta));
|
||||||
|
}
|
||||||
|
|
||||||
|
report (report_wire_out_inconsistencies,
|
||||||
|
json_pack ("{s:O, s:I, s:o, s:o}",
|
||||||
|
"destination_account",
|
||||||
|
wire,
|
||||||
|
"rowid",
|
||||||
|
(json_int_t) rowid,
|
||||||
|
"expected",
|
||||||
|
TALER_JSON_from_amount (&final_amount),
|
||||||
|
"claimed",
|
||||||
|
TALER_JSON_from_amount (amount)));
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
@ -3777,14 +3808,36 @@ run (void *cls,
|
|||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_get_zero (currency,
|
TALER_amount_get_zero (currency,
|
||||||
&total_aggregation_fee_income));
|
&total_aggregation_fee_income));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_balance_insufficient_loss));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_balance_summary_delta_plus));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_balance_summary_delta_minus));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_wire_out_delta_plus));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_wire_out_delta_minus));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (currency,
|
||||||
|
&total_balance_reserve_not_closed));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_emergencies = json_array ()));
|
(report_emergencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_row_inconsistencies = json_array ()));
|
(report_row_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_row_minor_inconsistencies = json_array ()));
|
(denomination_key_validity_withdraw_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_reserve_inconsistencies = json_array ()));
|
(report_reserve_balance_summary_wrong_inconsistencies = json_array ()));
|
||||||
|
GNUNET_assert (NULL !=
|
||||||
|
(report_reserve_balance_insufficient_inconsistencies = json_array ()));
|
||||||
|
GNUNET_assert (NULL !=
|
||||||
|
(report_reserve_not_closed_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
(report_wire_out_inconsistencies = json_array ()));
|
(report_wire_out_inconsistencies = json_array ()));
|
||||||
GNUNET_assert (NULL !=
|
GNUNET_assert (NULL !=
|
||||||
@ -3810,26 +3863,62 @@ run (void *cls,
|
|||||||
&income_fee_total,
|
&income_fee_total,
|
||||||
&total_aggregation_fee_income));
|
&total_aggregation_fee_income));
|
||||||
report = json_pack ("{s:o, s:o, s:o, s:o, s:o,"
|
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, 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 */
|
/* blocks of 5 for easier counting/matching to format string */
|
||||||
"emergencies", report_emergencies,
|
|
||||||
"emergencies_risk_total", TALER_JSON_from_amount (&reported_emergency_sum),
|
|
||||||
"row_inconsistencies", report_row_inconsistencies,
|
|
||||||
"row_minor_inconsistencies", report_row_minor_inconsistencies,
|
|
||||||
"reserve_inconsistencies", report_reserve_inconsistencies,
|
|
||||||
/* block */
|
/* block */
|
||||||
"wire_out_inconsistencies", report_wire_out_inconsistencies,
|
"reserve_balance_insufficient_inconsistencies",
|
||||||
"coin_inconsistencies", report_coin_inconsistencies,
|
report_reserve_balance_insufficient_inconsistencies,
|
||||||
"total_aggregation_fee_income", TALER_JSON_from_amount (&total_aggregation_fee_income),
|
"total_loss_balance_insufficient",
|
||||||
"total_escrow_balance", TALER_JSON_from_amount (&total_escrow_balance),
|
TALER_JSON_from_amount (&total_balance_insufficient_loss),
|
||||||
"total_active_risk", TALER_JSON_from_amount (&total_risk),
|
"reserve_balance_summary_wrong_inconsistencies",
|
||||||
|
report_reserve_balance_summary_wrong_inconsistencies,
|
||||||
|
"total_balance_summary_delta_plus",
|
||||||
|
TALER_JSON_from_amount (&total_balance_summary_delta_plus),
|
||||||
|
"total_balance_summary_delta_minus",
|
||||||
|
TALER_JSON_from_amount (&total_balance_summary_delta_minus),
|
||||||
/* block */
|
/* block */
|
||||||
"total_withdraw_fee_income", TALER_JSON_from_amount (&total_withdraw_fee_income),
|
"total_escrow_balance",
|
||||||
"total_deposit_fee_income", TALER_JSON_from_amount (&total_deposit_fee_income),
|
TALER_JSON_from_amount (&total_escrow_balance),
|
||||||
"total_melt_fee_income", TALER_JSON_from_amount (&total_melt_fee_income),
|
"total_active_risk",
|
||||||
"total_refund_fee_income", TALER_JSON_from_amount (&total_refund_fee_income),
|
TALER_JSON_from_amount (&total_risk),
|
||||||
"income_fee_total", TALER_JSON_from_amount (&income_fee_total)
|
"total_withdraw_fee_income",
|
||||||
|
TALER_JSON_from_amount (&total_withdraw_fee_income),
|
||||||
|
"total_deposit_fee_income",
|
||||||
|
TALER_JSON_from_amount (&total_deposit_fee_income),
|
||||||
|
"total_melt_fee_income",
|
||||||
|
/* block */
|
||||||
|
TALER_JSON_from_amount (&total_melt_fee_income),
|
||||||
|
"total_refund_fee_income",
|
||||||
|
TALER_JSON_from_amount (&total_refund_fee_income),
|
||||||
|
"income_fee_total",
|
||||||
|
TALER_JSON_from_amount (&income_fee_total),
|
||||||
|
"emergencies",
|
||||||
|
report_emergencies,
|
||||||
|
"emergencies_risk_total",
|
||||||
|
TALER_JSON_from_amount (&reported_emergency_sum),
|
||||||
|
/* block */
|
||||||
|
"reserve_not_closed_inconsistencies",
|
||||||
|
report_reserve_not_closed_inconsistencies,
|
||||||
|
"total_balance_reserve_not_closed",
|
||||||
|
TALER_JSON_from_amount (&total_balance_reserve_not_closed),
|
||||||
|
"wire_out_inconsistencies",
|
||||||
|
report_wire_out_inconsistencies,
|
||||||
|
"total_wire_out_delta_plus",
|
||||||
|
TALER_JSON_from_amount (&total_wire_out_delta_plus),
|
||||||
|
"total_wire_out_delta_minus",
|
||||||
|
TALER_JSON_from_amount (&total_wire_out_delta_minus),
|
||||||
|
/* block */
|
||||||
|
"row_inconsistencies",
|
||||||
|
report_row_inconsistencies,
|
||||||
|
"denomination_key_validity_withdraw_inconsistencies",
|
||||||
|
denomination_key_validity_withdraw_inconsistencies,
|
||||||
|
"coin_inconsistencies",
|
||||||
|
report_coin_inconsistencies,
|
||||||
|
"total_aggregation_fee_income",
|
||||||
|
TALER_JSON_from_amount (&total_aggregation_fee_income)
|
||||||
);
|
);
|
||||||
json_dumpf (report,
|
json_dumpf (report,
|
||||||
stdout,
|
stdout,
|
||||||
|
Loading…
Reference in New Issue
Block a user