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}
|
||||
|
||||
|
||||
\section{Irregularities}
|
||||
\section{Major irregularities}
|
||||
|
||||
This section describes the possible irregularities that the auditor
|
||||
has checked, and lists all of the actual irregularities encountered
|
||||
in detail.
|
||||
This section describes the possible major irregularities that the
|
||||
auditor has checked, and lists all of the actual irregularities
|
||||
encountered in detail.
|
||||
|
||||
\subsection{Emergencies}
|
||||
|
||||
@ -108,11 +108,8 @@ compromise.
|
||||
{% 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}}
|
||||
{\bf Reserve} & \multicolumn{2}{|c|}{ {\bf Expected}} & \multicolumn{2}{|c|}{ {\bf Observed}} & {\bf Diagnostic} \\ \hline \hline
|
||||
\endfirsthead
|
||||
@ -138,6 +135,220 @@ compromise.
|
||||
{{ item.diagnostic }} \\ \hline
|
||||
{% endfor %}
|
||||
\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 %}
|
||||
|
||||
|
||||
\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}
|
||||
|
@ -125,20 +125,65 @@ static json_t *report_emergencies;
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -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.
|
||||
*
|
||||
@ -594,10 +560,6 @@ load_auditor_reserve_summary (struct ReserveSummary *rs)
|
||||
TALER_amount_cmp_currency (&rs->total_in,
|
||||
&rs->a_balance)) )
|
||||
{
|
||||
report_row_inconsistency ("auditor-reserve-info",
|
||||
rowid,
|
||||
"currencies for reserve differ");
|
||||
/* TODO: find a sane way to continue... */
|
||||
GNUNET_break (0);
|
||||
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) ||
|
||||
(expire_withdraw.abs_value_us < execution_date.abs_value_us) )
|
||||
{
|
||||
report_row_minor_inconsistency ("withdraw",
|
||||
rowid,
|
||||
"denomination key not valid at time of withdrawal");
|
||||
report (denomination_key_validity_withdraw_inconsistencies,
|
||||
json_pack ("{s:I, s:s, s:o, s:o}",
|
||||
"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 */
|
||||
@ -1155,10 +1120,7 @@ verify_reserve_balance (void *cls,
|
||||
&rs->total_in,
|
||||
&rs->a_balance))
|
||||
{
|
||||
report_reserve_inconsistency (&rs->reserve_pub,
|
||||
&rs->total_in,
|
||||
&rs->a_balance,
|
||||
"could not add old balance to new balance");
|
||||
GNUNET_break (0);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
@ -1167,19 +1129,62 @@ verify_reserve_balance (void *cls,
|
||||
&balance,
|
||||
&rs->total_out))
|
||||
{
|
||||
report_reserve_inconsistency (&rs->reserve_pub,
|
||||
&rs->total_in,
|
||||
&rs->total_out,
|
||||
"available balance insufficient to cover transfers");
|
||||
struct TALER_Amount loss;
|
||||
|
||||
GNUNET_break (GNUNET_SYSERR !=
|
||||
TALER_amount_subtract (&loss,
|
||||
&rs->total_out,
|
||||
&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;
|
||||
}
|
||||
if (0 != TALER_amount_cmp (&balance,
|
||||
&reserve.balance))
|
||||
{
|
||||
report_reserve_inconsistency (&rs->reserve_pub,
|
||||
&balance,
|
||||
&reserve.balance,
|
||||
"computed balance does not match stored balance");
|
||||
struct TALER_Amount delta;
|
||||
|
||||
if (0 < TALER_amount_cmp (&balance,
|
||||
&reserve.balance))
|
||||
{
|
||||
/* balance > reserve.balance */
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_subtract (&delta,
|
||||
&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,
|
||||
&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;
|
||||
}
|
||||
|
||||
@ -1189,16 +1194,18 @@ verify_reserve_balance (void *cls,
|
||||
( (0 != balance.value) ||
|
||||
(0 != balance.fraction) ) )
|
||||
{
|
||||
struct TALER_Amount zero;
|
||||
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (balance.currency,
|
||||
&zero));
|
||||
|
||||
report_reserve_inconsistency (&rs->reserve_pub,
|
||||
&balance,
|
||||
&zero,
|
||||
"expired reserve needs to be closed");
|
||||
TALER_amount_add (&total_balance_reserve_not_closed,
|
||||
&total_balance_reserve_not_closed,
|
||||
&balance));
|
||||
report (report_reserve_not_closed_inconsistencies,
|
||||
json_pack ("{s:o, s:o, s:s}",
|
||||
"reserve_pub",
|
||||
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 */
|
||||
@ -2206,10 +2213,8 @@ check_wire_out_cb (void *cls,
|
||||
TALER_JSON_hash (wire,
|
||||
&wcc.h_wire))
|
||||
{
|
||||
report_row_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"could not hash wire address");
|
||||
return GNUNET_OK;
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
qs = edb->lookup_wire_transfer (edb->cls,
|
||||
esession,
|
||||
@ -2256,20 +2261,13 @@ check_wire_out_cb (void *cls,
|
||||
wcc.method);
|
||||
if (NULL == plugin)
|
||||
{
|
||||
report_row_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"could not load required wire plugin to validate");
|
||||
return GNUNET_OK;
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
if (GNUNET_SYSERR ==
|
||||
plugin->amount_round (plugin->cls,
|
||||
&final_amount))
|
||||
{
|
||||
report_row_minor_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"wire plugin failed to round given amount");
|
||||
}
|
||||
GNUNET_break (GNUNET_SYSERR !=
|
||||
plugin->amount_round (plugin->cls,
|
||||
&final_amount));
|
||||
|
||||
/* Calculate the exchange's gain as the fees plus rounding differences! */
|
||||
if (GNUNET_OK !=
|
||||
@ -2297,11 +2295,44 @@ check_wire_out_cb (void *cls,
|
||||
if (0 != TALER_amount_cmp (amount,
|
||||
&final_amount))
|
||||
{
|
||||
report_wire_out_inconsistency (wire,
|
||||
rowid,
|
||||
&final_amount,
|
||||
amount,
|
||||
"computed amount inconsistent with wire amount");
|
||||
struct TALER_Amount delta;
|
||||
|
||||
if (0 < TALER_amount_cmp (amount,
|
||||
&final_amount))
|
||||
{
|
||||
/* amount > final_amount */
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_subtract (&delta,
|
||||
amount,
|
||||
&final_amount));
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_add (&total_wire_out_delta_plus,
|
||||
&total_wire_out_delta_plus,
|
||||
&delta));
|
||||
}
|
||||
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;
|
||||
}
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
@ -3777,14 +3808,36 @@ run (void *cls,
|
||||
GNUNET_assert (GNUNET_OK ==
|
||||
TALER_amount_get_zero (currency,
|
||||
&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 !=
|
||||
(report_emergencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_row_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
(report_row_minor_inconsistencies = json_array ()));
|
||||
(denomination_key_validity_withdraw_inconsistencies = json_array ()));
|
||||
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 !=
|
||||
(report_wire_out_inconsistencies = json_array ()));
|
||||
GNUNET_assert (NULL !=
|
||||
@ -3810,26 +3863,62 @@ run (void *cls,
|
||||
&income_fee_total,
|
||||
&total_aggregation_fee_income));
|
||||
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 */
|
||||
"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 */
|
||||
"wire_out_inconsistencies", report_wire_out_inconsistencies,
|
||||
"coin_inconsistencies", report_coin_inconsistencies,
|
||||
"total_aggregation_fee_income", TALER_JSON_from_amount (&total_aggregation_fee_income),
|
||||
"total_escrow_balance", TALER_JSON_from_amount (&total_escrow_balance),
|
||||
"total_active_risk", TALER_JSON_from_amount (&total_risk),
|
||||
"reserve_balance_insufficient_inconsistencies",
|
||||
report_reserve_balance_insufficient_inconsistencies,
|
||||
"total_loss_balance_insufficient",
|
||||
TALER_JSON_from_amount (&total_balance_insufficient_loss),
|
||||
"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 */
|
||||
"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", 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)
|
||||
"total_escrow_balance",
|
||||
TALER_JSON_from_amount (&total_escrow_balance),
|
||||
"total_active_risk",
|
||||
TALER_JSON_from_amount (&total_risk),
|
||||
"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,
|
||||
stdout,
|
||||
|
Loading…
Reference in New Issue
Block a user