finish review of coins auditor analysis logic, improve error handling
This commit is contained in:
parent
0bd53ed443
commit
240b23684d
@ -910,13 +910,13 @@ reveal_data_cb (void *cls,
|
|||||||
report_row_inconsistency ("refresh_reveal",
|
report_row_inconsistency ("refresh_reveal",
|
||||||
rctx->rowid,
|
rctx->rowid,
|
||||||
"denomination key not found");
|
"denomination key not found");
|
||||||
rctx->err = GNUNET_NO; /* terminate, but return "OK" */
|
rctx->err = GNUNET_NO; /* terminate here, but return "OK" to commit transaction */
|
||||||
}
|
}
|
||||||
else if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
else if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
|
||||||
{
|
{
|
||||||
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
|
||||||
rctx->qs = qs;
|
rctx->qs = qs;
|
||||||
rctx->err = GNUNET_SYSERR; /* terminate, return GNUNET_SYSERR */
|
rctx->err = GNUNET_SYSERR; /* terminate, return #GNUNET_SYSERR: abort transaction */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1101,9 +1101,9 @@ refresh_session_cb (void *cls,
|
|||||||
if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
|
if ( (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) ||
|
||||||
(0 == reveal_ctx.num_freshcoins) )
|
(0 == reveal_ctx.num_freshcoins) )
|
||||||
{
|
{
|
||||||
/* This can happen if reveal was not yet called or only
|
/* This can legitimately happen if reveal was not yet called or only
|
||||||
with invalid data, even if the exchange is correctly
|
with invalid data, even if the exchange is correctly operating. We
|
||||||
operating. We still report it. */
|
still report it. */
|
||||||
TALER_ARL_report (report_refreshs_hanging,
|
TALER_ARL_report (report_refreshs_hanging,
|
||||||
json_pack ("{s:I, s:o, s:o}",
|
json_pack ("{s:I, s:o, s:o}",
|
||||||
"row", (json_int_t) rowid,
|
"row", (json_int_t) rowid,
|
||||||
@ -1162,15 +1162,22 @@ refresh_session_cb (void *cls,
|
|||||||
amount_with_fee,
|
amount_with_fee,
|
||||||
&melt_fee))
|
&melt_fee))
|
||||||
{
|
{
|
||||||
// FIXME: handle properly!
|
/* Melt fee higher than contribution of melted coin; this makes
|
||||||
GNUNET_break (0);
|
no sense (exchange should never have accepted the operation) */
|
||||||
cc->qs = GNUNET_DB_STATUS_HARD_ERROR;
|
report_amount_arithmetic_inconsistency ("melt contribution vs. fee",
|
||||||
GNUNET_free_non_null (reveal_ctx.new_issues);
|
rowid,
|
||||||
return GNUNET_SYSERR;
|
amount_with_fee,
|
||||||
|
&melt_fee,
|
||||||
|
-1);
|
||||||
|
/* To continue, best assumption is the melted coin contributed
|
||||||
|
nothing (=> all withdrawal amounts will be counted as losses) */
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_get_zero (TALER_ARL_currency,
|
||||||
|
&amount_without_fee));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check old coin covers complete expenses */
|
/* check old coin covers complete expenses (of withdraw operations) */
|
||||||
if (1 == TALER_amount_cmp (&refresh_cost,
|
if (1 == TALER_amount_cmp (&refresh_cost,
|
||||||
&amount_without_fee))
|
&amount_without_fee))
|
||||||
{
|
{
|
||||||
@ -1184,7 +1191,7 @@ refresh_session_cb (void *cls,
|
|||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update outstanding denomination amounts */
|
/* update outstanding denomination amounts for fresh coins withdrawn */
|
||||||
for (unsigned int i = 0; i<reveal_ctx.num_freshcoins; i++)
|
for (unsigned int i = 0; i<reveal_ctx.num_freshcoins; i++)
|
||||||
{
|
{
|
||||||
struct DenominationSummary *dsi;
|
struct DenominationSummary *dsi;
|
||||||
@ -1195,36 +1202,40 @@ refresh_session_cb (void *cls,
|
|||||||
&reveal_ctx.new_issues[i]->denom_hash);
|
&reveal_ctx.new_issues[i]->denom_hash);
|
||||||
if (NULL == dsi)
|
if (NULL == dsi)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
report_row_inconsistency ("refresh_reveal",
|
||||||
return GNUNET_SYSERR;
|
rowid,
|
||||||
|
"denomination key for fresh coin unknown to auditor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TALER_amount_ntoh (&value,
|
||||||
|
&reveal_ctx.new_issues[i]->value);
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"Created fresh coin in denomination `%s' of value %s\n",
|
||||||
|
GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
|
||||||
|
TALER_amount2s (&value));
|
||||||
|
dsi->num_issued++;
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&dsi->denom_balance,
|
||||||
|
&dsi->denom_balance,
|
||||||
|
&value));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&dsi->denom_risk,
|
||||||
|
&dsi->denom_risk,
|
||||||
|
&value));
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"New balance of denomination `%s' is %s\n",
|
||||||
|
GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
|
||||||
|
TALER_amount2s (&dsi->denom_balance));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_escrow_balance,
|
||||||
|
&total_escrow_balance,
|
||||||
|
&value));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_risk,
|
||||||
|
&total_risk,
|
||||||
|
&value));
|
||||||
}
|
}
|
||||||
TALER_amount_ntoh (&value,
|
|
||||||
&reveal_ctx.new_issues[i]->value);
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"Created fresh coin in denomination `%s' of value %s\n",
|
|
||||||
GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
|
|
||||||
TALER_amount2s (&value));
|
|
||||||
dsi->num_issued++;
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&dsi->denom_balance,
|
|
||||||
&dsi->denom_balance,
|
|
||||||
&value));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&dsi->denom_risk,
|
|
||||||
&dsi->denom_risk,
|
|
||||||
&value));
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"New balance of denomination `%s' is %s\n",
|
|
||||||
GNUNET_h2s (&reveal_ctx.new_issues[i]->denom_hash),
|
|
||||||
TALER_amount2s (&dsi->denom_balance));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&total_escrow_balance,
|
|
||||||
&total_escrow_balance,
|
|
||||||
&value));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&total_risk,
|
|
||||||
&total_risk,
|
|
||||||
&value));
|
|
||||||
}
|
}
|
||||||
GNUNET_free_non_null (reveal_ctx.new_issues);
|
GNUNET_free_non_null (reveal_ctx.new_issues);
|
||||||
}
|
}
|
||||||
@ -1235,52 +1246,55 @@ refresh_session_cb (void *cls,
|
|||||||
&issue->denom_hash);
|
&issue->denom_hash);
|
||||||
if (NULL == dso)
|
if (NULL == dso)
|
||||||
{
|
{
|
||||||
// FIXME: handle more nicely!?!
|
report_row_inconsistency ("refresh_reveal",
|
||||||
GNUNET_break (0);
|
rowid,
|
||||||
return GNUNET_SYSERR;
|
"denomination key for dirty coin unknown to auditor");
|
||||||
}
|
|
||||||
if (GNUNET_SYSERR ==
|
|
||||||
TALER_amount_subtract (&tmp,
|
|
||||||
&dso->denom_balance,
|
|
||||||
amount_with_fee))
|
|
||||||
{
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&dso->denom_loss,
|
|
||||||
&dso->denom_loss,
|
|
||||||
amount_with_fee));
|
|
||||||
dso->report_emergency = GNUNET_YES;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dso->denom_balance = tmp;
|
if (GNUNET_SYSERR ==
|
||||||
|
TALER_amount_subtract (&tmp,
|
||||||
|
&dso->denom_balance,
|
||||||
|
amount_with_fee))
|
||||||
|
{
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&dso->denom_loss,
|
||||||
|
&dso->denom_loss,
|
||||||
|
amount_with_fee));
|
||||||
|
dso->report_emergency = GNUNET_YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dso->denom_balance = tmp;
|
||||||
|
}
|
||||||
|
if (-1 == TALER_amount_cmp (&total_escrow_balance,
|
||||||
|
amount_with_fee))
|
||||||
|
{
|
||||||
|
/* This can theoretically happen if for example the exchange
|
||||||
|
never issued any coins (i.e. escrow balance is zero), but
|
||||||
|
accepted a forged coin (i.e. emergency situation after
|
||||||
|
private key compromise). In that case, we cannot even
|
||||||
|
subtract the profit we make from the fee from the escrow
|
||||||
|
balance. Tested as part of test-auditor.sh, case #18 *///
|
||||||
|
report_amount_arithmetic_inconsistency (
|
||||||
|
"subtracting refresh fee from escrow balance",
|
||||||
|
rowid,
|
||||||
|
&total_escrow_balance,
|
||||||
|
amount_with_fee,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_assert (GNUNET_SYSERR !=
|
||||||
|
TALER_amount_subtract (&total_escrow_balance,
|
||||||
|
&total_escrow_balance,
|
||||||
|
amount_with_fee));
|
||||||
|
}
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"New balance of denomination `%s' after melt is %s\n",
|
||||||
|
GNUNET_h2s (&issue->denom_hash),
|
||||||
|
TALER_amount2s (&dso->denom_balance));
|
||||||
}
|
}
|
||||||
if (-1 == TALER_amount_cmp (&total_escrow_balance,
|
|
||||||
amount_with_fee))
|
|
||||||
{
|
|
||||||
/* This can theoretically happen if for example the exchange
|
|
||||||
never issued any coins (i.e. escrow balance is zero), but
|
|
||||||
accepted a forged coin (i.e. emergency situation after
|
|
||||||
private key compromise). In that case, we cannot even
|
|
||||||
subtract the profit we make from the fee from the escrow
|
|
||||||
balance. Tested as part of test-auditor.sh, case #18 */report_amount_arithmetic_inconsistency (
|
|
||||||
"subtracting refresh fee from escrow balance",
|
|
||||||
rowid,
|
|
||||||
&total_escrow_balance,
|
|
||||||
amount_with_fee,
|
|
||||||
0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GNUNET_assert (GNUNET_SYSERR !=
|
|
||||||
TALER_amount_subtract (&total_escrow_balance,
|
|
||||||
&total_escrow_balance,
|
|
||||||
amount_with_fee));
|
|
||||||
}
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"New balance of denomination `%s' after melt is %s\n",
|
|
||||||
GNUNET_h2s (&issue->denom_hash),
|
|
||||||
TALER_amount2s (&dso->denom_balance));
|
|
||||||
|
|
||||||
/* update global melt fees */
|
/* update global melt fees */
|
||||||
{
|
{
|
||||||
@ -1440,54 +1454,57 @@ deposit_cb (void *cls,
|
|||||||
&issue->denom_hash);
|
&issue->denom_hash);
|
||||||
if (NULL == ds)
|
if (NULL == ds)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
report_row_inconsistency ("deposit",
|
||||||
// FIXME: handle/report more nicely!??!
|
rowid,
|
||||||
return GNUNET_SYSERR;
|
"denomination key for deposited coin unknown to auditor");
|
||||||
}
|
|
||||||
if (GNUNET_SYSERR ==
|
|
||||||
TALER_amount_subtract (&tmp,
|
|
||||||
&ds->denom_balance,
|
|
||||||
amount_with_fee))
|
|
||||||
{
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&ds->denom_loss,
|
|
||||||
&ds->denom_loss,
|
|
||||||
amount_with_fee));
|
|
||||||
ds->report_emergency = GNUNET_YES;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ds->denom_balance = tmp;
|
if (GNUNET_SYSERR ==
|
||||||
}
|
TALER_amount_subtract (&tmp,
|
||||||
|
&ds->denom_balance,
|
||||||
|
amount_with_fee))
|
||||||
|
{
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&ds->denom_loss,
|
||||||
|
&ds->denom_loss,
|
||||||
|
amount_with_fee));
|
||||||
|
ds->report_emergency = GNUNET_YES;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ds->denom_balance = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
if (-1 == TALER_amount_cmp (&total_escrow_balance,
|
if (-1 == TALER_amount_cmp (&total_escrow_balance,
|
||||||
amount_with_fee))
|
amount_with_fee))
|
||||||
{
|
{
|
||||||
/* This can theoretically happen if for example the exchange
|
/* This can theoretically happen if for example the exchange
|
||||||
never issued any coins (i.e. escrow balance is zero), but
|
never issued any coins (i.e. escrow balance is zero), but
|
||||||
accepted a forged coin (i.e. emergency situation after
|
accepted a forged coin (i.e. emergency situation after
|
||||||
private key compromise). In that case, we cannot even
|
private key compromise). In that case, we cannot even
|
||||||
subtract the profit we make from the fee from the escrow
|
subtract the profit we make from the fee from the escrow
|
||||||
balance. Tested as part of test-auditor.sh, case #18 *///
|
balance. Tested as part of test-auditor.sh, case #18 *///
|
||||||
report_amount_arithmetic_inconsistency (
|
report_amount_arithmetic_inconsistency (
|
||||||
"subtracting deposit fee from escrow balance",
|
"subtracting deposit fee from escrow balance",
|
||||||
rowid,
|
rowid,
|
||||||
&total_escrow_balance,
|
&total_escrow_balance,
|
||||||
amount_with_fee,
|
amount_with_fee,
|
||||||
0);
|
0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
GNUNET_assert (GNUNET_SYSERR !=
|
GNUNET_assert (GNUNET_SYSERR !=
|
||||||
TALER_amount_subtract (&total_escrow_balance,
|
TALER_amount_subtract (&total_escrow_balance,
|
||||||
&total_escrow_balance,
|
&total_escrow_balance,
|
||||||
amount_with_fee));
|
amount_with_fee));
|
||||||
}
|
}
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
"New balance of denomination `%s' after deposit is %s\n",
|
"New balance of denomination `%s' after deposit is %s\n",
|
||||||
GNUNET_h2s (&issue->denom_hash),
|
GNUNET_h2s (&issue->denom_hash),
|
||||||
TALER_amount2s (&ds->denom_balance));
|
TALER_amount2s (&ds->denom_balance));
|
||||||
|
}
|
||||||
|
|
||||||
/* update global deposit fees */
|
/* update global deposit fees */
|
||||||
{
|
{
|
||||||
@ -1622,31 +1639,33 @@ refund_cb (void *cls,
|
|||||||
&issue->denom_hash);
|
&issue->denom_hash);
|
||||||
if (NULL == ds)
|
if (NULL == ds)
|
||||||
{
|
{
|
||||||
GNUNET_break (0);
|
report_row_inconsistency ("refund",
|
||||||
// FIXME: handle more nicely!?!?
|
rowid,
|
||||||
return GNUNET_SYSERR;
|
"denomination key for refunded coin unknown to auditor");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&ds->denom_balance,
|
||||||
|
&ds->denom_balance,
|
||||||
|
&amount_without_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&ds->denom_risk,
|
||||||
|
&ds->denom_risk,
|
||||||
|
&amount_without_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_escrow_balance,
|
||||||
|
&total_escrow_balance,
|
||||||
|
&amount_without_fee));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_risk,
|
||||||
|
&total_risk,
|
||||||
|
&amount_without_fee));
|
||||||
|
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||||
|
"New balance of denomination `%s' after refund is %s\n",
|
||||||
|
GNUNET_h2s (&issue->denom_hash),
|
||||||
|
TALER_amount2s (&ds->denom_balance));
|
||||||
}
|
}
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&ds->denom_balance,
|
|
||||||
&ds->denom_balance,
|
|
||||||
&amount_without_fee));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&ds->denom_risk,
|
|
||||||
&ds->denom_risk,
|
|
||||||
&amount_without_fee));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&total_escrow_balance,
|
|
||||||
&total_escrow_balance,
|
|
||||||
&amount_without_fee));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&total_risk,
|
|
||||||
&total_risk,
|
|
||||||
&amount_without_fee));
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
|
||||||
"New balance of denomination `%s' after refund is %s\n",
|
|
||||||
GNUNET_h2s (&issue->denom_hash),
|
|
||||||
TALER_amount2s (&ds->denom_balance));
|
|
||||||
|
|
||||||
/* update total refund fee balance */
|
/* update total refund fee balance */
|
||||||
GNUNET_assert (GNUNET_OK ==
|
GNUNET_assert (GNUNET_OK ==
|
||||||
TALER_amount_add (&total_refund_fee_income,
|
TALER_amount_add (&total_refund_fee_income,
|
||||||
@ -1743,26 +1762,35 @@ check_recoup (struct CoinContext *cc,
|
|||||||
ds = get_denomination_summary (cc,
|
ds = get_denomination_summary (cc,
|
||||||
issue,
|
issue,
|
||||||
&issue->denom_hash);
|
&issue->denom_hash);
|
||||||
if (GNUNET_NO == ds->was_revoked)
|
if (NULL == ds)
|
||||||
{
|
{
|
||||||
/* Woopsie, we allowed recoup on non-revoked denomination!? */
|
report_row_inconsistency ("recoup",
|
||||||
TALER_ARL_report (report_bad_sig_losses,
|
rowid,
|
||||||
json_pack ("{s:s, s:I, s:o, s:o}",
|
"denomination key for recouped coin unknown to auditor");
|
||||||
"operation",
|
}
|
||||||
"recoup (denomination not revoked)",
|
else
|
||||||
"row", (json_int_t) rowid,
|
{
|
||||||
"loss", TALER_JSON_from_amount (amount),
|
if (GNUNET_NO == ds->was_revoked)
|
||||||
"coin_pub", GNUNET_JSON_from_data_auto (
|
{
|
||||||
&coin->coin_pub)));
|
/* Woopsie, we allowed recoup on non-revoked denomination!? */
|
||||||
|
TALER_ARL_report (report_bad_sig_losses,
|
||||||
|
json_pack ("{s:s, s:I, s:o, s:o}",
|
||||||
|
"operation",
|
||||||
|
"recoup (denomination not revoked)",
|
||||||
|
"row", (json_int_t) rowid,
|
||||||
|
"loss", TALER_JSON_from_amount (amount),
|
||||||
|
"coin_pub", GNUNET_JSON_from_data_auto (
|
||||||
|
&coin->coin_pub)));
|
||||||
|
}
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&ds->denom_recoup,
|
||||||
|
&ds->denom_recoup,
|
||||||
|
amount));
|
||||||
|
GNUNET_assert (GNUNET_OK ==
|
||||||
|
TALER_amount_add (&total_recoup_loss,
|
||||||
|
&total_recoup_loss,
|
||||||
|
amount));
|
||||||
}
|
}
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&ds->denom_recoup,
|
|
||||||
&ds->denom_recoup,
|
|
||||||
amount));
|
|
||||||
GNUNET_assert (GNUNET_OK ==
|
|
||||||
TALER_amount_add (&total_recoup_loss,
|
|
||||||
&total_recoup_loss,
|
|
||||||
amount));
|
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user