This commit is contained in:
Christian Grothoff 2017-11-06 14:54:52 +01:00
parent c5f9c0ca88
commit cc09fbbb29
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
2 changed files with 459 additions and 159 deletions

View File

@ -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}

View File

@ -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,