aboutsummaryrefslogtreecommitdiff
path: root/src/auditor
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2022-10-30 17:36:57 +0100
committerChristian Grothoff <christian@grothoff.org>2022-10-30 17:36:57 +0100
commit2d55647f2aab1feb37d5439049f6824d11cda56c (patch)
treeaef525c04a030b318a97b9d8ae77573ca73a8237 /src/auditor
parent38a078d543f53ca4925ea364919306395e7e4597 (diff)
add support for reserve open/close operations to auditor, begin to split off purse auditing logic
Diffstat (limited to 'src/auditor')
-rw-r--r--src/auditor/Makefile.am41
-rw-r--r--src/auditor/taler-auditor-sync.c2
-rw-r--r--src/auditor/taler-auditor.in1
-rw-r--r--src/auditor/taler-helper-auditor-coins.c402
-rw-r--r--src/auditor/taler-helper-auditor-purses.c1123
-rw-r--r--src/auditor/taler-helper-auditor-render.py12
-rw-r--r--src/auditor/taler-helper-auditor-reserves.c1258
-rw-r--r--src/auditor/taler-helper-auditor-wire.c30
-rwxr-xr-xsrc/auditor/test-auditor.sh18
-rwxr-xr-xsrc/auditor/test-revocation.sh4
10 files changed, 1967 insertions, 924 deletions
diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index 6eaff39fc..34f6334e8 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -65,9 +65,9 @@ taler_auditor_dbinit_CPPFLAGS = \
-I$(top_srcdir)/src/pq/ \
$(POSTGRESQL_CPPFLAGS)
-taler_helper_auditor_reserves_SOURCES = \
- taler-helper-auditor-reserves.c
-taler_helper_auditor_reserves_LDADD = \
+taler_helper_auditor_coins_SOURCES = \
+ taler-helper-auditor-coins.c
+taler_helper_auditor_coins_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/json/libtalerjson.la \
@@ -80,9 +80,9 @@ taler_helper_auditor_reserves_LDADD = \
-lgnunetutil \
$(XLIB)
-taler_helper_auditor_coins_SOURCES = \
- taler-helper-auditor-coins.c
-taler_helper_auditor_coins_LDADD = \
+taler_helper_auditor_aggregation_SOURCES = \
+ taler-helper-auditor-aggregation.c
+taler_helper_auditor_aggregation_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/json/libtalerjson.la \
@@ -95,9 +95,9 @@ taler_helper_auditor_coins_LDADD = \
-lgnunetutil \
$(XLIB)
-taler_helper_auditor_aggregation_SOURCES = \
- taler-helper-auditor-aggregation.c
-taler_helper_auditor_aggregation_LDADD = \
+taler_helper_auditor_deposits_SOURCES = \
+ taler-helper-auditor-deposits.c
+taler_helper_auditor_deposits_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/json/libtalerjson.la \
@@ -110,9 +110,9 @@ taler_helper_auditor_aggregation_LDADD = \
-lgnunetutil \
$(XLIB)
-taler_helper_auditor_deposits_SOURCES = \
- taler-helper-auditor-deposits.c
-taler_helper_auditor_deposits_LDADD = \
+taler_helper_auditor_purses_SOURCES = \
+ taler-helper-auditor-purses.c
+taler_helper_auditor_purses_LDADD = \
$(LIBGCRYPT_LIBS) \
$(top_builddir)/src/util/libtalerutil.la \
$(top_builddir)/src/json/libtalerjson.la \
@@ -125,6 +125,23 @@ taler_helper_auditor_deposits_LDADD = \
-lgnunetutil \
$(XLIB)
+taler_helper_auditor_reserves_SOURCES = \
+ taler-helper-auditor-reserves.c
+taler_helper_auditor_reserves_LDADD = \
+ $(LIBGCRYPT_LIBS) \
+ $(top_builddir)/src/util/libtalerutil.la \
+ $(top_builddir)/src/json/libtalerjson.la \
+ $(top_builddir)/src/bank-lib/libtalerbank.la \
+ $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
+ $(top_builddir)/src/auditordb/libtalerauditordb.la \
+ libauditorreport.la \
+ -ljansson \
+ -lgnunetjson \
+ -lgnunetutil \
+ $(XLIB)
+
+
+
taler_helper_auditor_wire_SOURCES = \
taler-helper-auditor-wire.c
taler_helper_auditor_wire_LDADD = \
diff --git a/src/auditor/taler-auditor-sync.c b/src/auditor/taler-auditor-sync.c
index 803328f2e..3c4c7e4c7 100644
--- a/src/auditor/taler-auditor-sync.c
+++ b/src/auditor/taler-auditor-sync.c
@@ -119,7 +119,7 @@ static struct Table tables[] = {
{ .rt = TALER_EXCHANGEDB_RT_EXTENSIONS},
{ .rt = TALER_EXCHANGEDB_RT_EXTENSION_DETAILS },
{ .rt = TALER_EXCHANGEDB_RT_PURSE_REQUESTS},
- { .rt = TALER_EXCHANGEDB_RT_PURSE_REFUNDS},
+ { .rt = TALER_EXCHANGEDB_RT_PURSE_DECISION},
{ .rt = TALER_EXCHANGEDB_RT_PURSE_MERGES},
{ .rt = TALER_EXCHANGEDB_RT_PURSE_DEPOSITS},
{ .rt = TALER_EXCHANGEDB_RT_ACCOUNT_MERGES},
diff --git a/src/auditor/taler-auditor.in b/src/auditor/taler-auditor.in
index 6a8e88daa..e883acb44 100644
--- a/src/auditor/taler-auditor.in
+++ b/src/auditor/taler-auditor.in
@@ -91,6 +91,7 @@ done
taler-helper-auditor-wire $INF ${ARGS[*]} > ${DIR}/wire.json
+echo "Generating auditor report in ${DIR}."
taler-helper-auditor-render.py \
${DIR}/aggregation.json \
${DIR}/coins.json \
diff --git a/src/auditor/taler-helper-auditor-coins.c b/src/auditor/taler-helper-auditor-coins.c
index 23d543dcb..f263e5732 100644
--- a/src/auditor/taler-helper-auditor-coins.c
+++ b/src/auditor/taler-helper-auditor-coins.c
@@ -113,39 +113,9 @@ static struct TALER_Amount reported_emergency_loss;
static struct TALER_Amount reported_emergency_loss_by_count;
/**
- * Expected balance in the escrow account.
+ * Global coin balance sheet (for coins).
*/
-static struct TALER_Amount total_escrow_balance;
-
-/**
- * Active risk exposure.
- */
-static struct TALER_Amount total_risk;
-
-/**
- * Actualized risk (= loss) from recoups.
- */
-static struct TALER_Amount total_recoup_loss;
-
-/**
- * Recoups we made on denominations that were not revoked (!?).
- */
-static struct TALER_Amount total_irregular_recoups;
-
-/**
- * Total deposit fees earned.
- */
-static struct TALER_Amount total_deposit_fee_income;
-
-/**
- * Total melt fees earned.
- */
-static struct TALER_Amount total_melt_fee_income;
-
-/**
- * Total refund fees earned.
- */
-static struct TALER_Amount total_refund_fee_income;
+static struct TALER_AUDITORDB_GlobalCoinBalance balance;
/**
* Array of reports about coin operations with bad signatures.
@@ -153,11 +123,6 @@ static struct TALER_Amount total_refund_fee_income;
static json_t *report_bad_sig_losses;
/**
- * Total amount lost by operations for which signatures were invalid.
- */
-static struct TALER_Amount total_bad_sig_loss;
-
-/**
* Array of refresh transactions where the /refresh/reveal has not yet
* happened (and may of course never happen).
*/
@@ -605,33 +570,9 @@ check_coin_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
struct DenominationSummary
{
/**
- * Total value of outstanding (not deposited) coins issued with this
- * denomination key.
- */
- struct TALER_Amount denom_balance;
-
- /**
- * Total losses made (once coins deposited exceed
- * coins withdrawn and thus the @e denom_balance is
- * effectively negative).
+ * Information about the circulation.
*/
- struct TALER_Amount denom_loss;
-
- /**
- * Total value of coins issued with this denomination key.
- */
- struct TALER_Amount denom_risk;
-
- /**
- * Total value of coins subjected to recoup with this denomination key.
- */
- struct TALER_Amount denom_recoup;
-
- /**
- * How many coins (not their amount!) of this denomination
- * did the exchange issue overall?
- */
- uint64_t num_issued;
+ struct TALER_AUDITORDB_DenominationCirculationData dcd;
/**
* Denomination key information for this denomination.
@@ -694,11 +635,7 @@ init_denomination (const struct TALER_DenominationHashP *denom_hash,
qs = TALER_ARL_adb->get_denomination_balance (TALER_ARL_adb->cls,
denom_hash,
- &ds->denom_balance,
- &ds->denom_loss,
- &ds->denom_risk,
- &ds->denom_recoup,
- &ds->num_issued);
+ &ds->dcd);
if (0 > qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -712,22 +649,22 @@ init_denomination (const struct TALER_DenominationHashP *denom_hash,
{
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &ds->denom_balance));
+ &ds->dcd.denom_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &ds->denom_loss));
+ &ds->dcd.denom_loss));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &ds->denom_risk));
+ &ds->dcd.denom_risk));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &ds->denom_recoup));
+ &ds->dcd.recoup_loss));
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Starting balance for denomination `%s' is %s (%llu)\n",
GNUNET_h2s (&denom_hash->hash),
- TALER_amount2s (&ds->denom_balance),
- (unsigned long long) ds->num_issued);
+ TALER_amount2s (&ds->dcd.denom_balance),
+ (unsigned long long) ds->dcd.num_issued);
qs = TALER_ARL_edb->get_denomination_revocation (TALER_ARL_edb->cls,
denom_hash,
&msig,
@@ -842,15 +779,14 @@ sync_denomination (void *cls,
else
qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
- ( (0 != ds->denom_risk.value) ||
- (0 != ds->denom_risk.fraction) ) )
+ (! TALER_amount_is_zero (&ds->dcd.denom_risk)) )
{
/* The denomination expired and carried a balance; we can now
book the remaining balance as profit, and reduce our risk
exposure by the accumulated risk of the denomination. */
- TALER_ARL_amount_subtract (&total_risk,
- &total_risk,
- &ds->denom_risk);
+ TALER_ARL_amount_subtract (&balance.risk,
+ &balance.risk,
+ &ds->dcd.denom_risk);
/* If the above fails, our risk assessment is inconsistent!
This is really, really bad (auditor-internal invariant
would be violated). Hence we can "safely" assert. If
@@ -858,22 +794,21 @@ sync_denomination (void *cls,
in the auditor _or_ the auditor's database is corrupt. */
}
if ( (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs) &&
- ( (0 != ds->denom_balance.value) ||
- (0 != ds->denom_balance.fraction) ) )
+ (! TALER_amount_is_zero (&ds->dcd.denom_balance)) )
{
/* book denom_balance coin expiration profits! */
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Denomination `%s' expired, booking %s in expiration profits\n",
GNUNET_h2s (denom_hash),
- TALER_amount2s (&ds->denom_balance));
+ TALER_amount2s (&ds->dcd.denom_balance));
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
(qs = TALER_ARL_adb->insert_historic_denom_revenue (
TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
&denom_h,
expire_deposit,
- &ds->denom_balance,
- &ds->denom_recoup)))
+ &ds->dcd.denom_balance,
+ &ds->dcd.recoup_loss)))
{
/* Failed to store profits? Bad database */
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -890,8 +825,8 @@ sync_denomination (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Final balance for denomination `%s' is %s (%llu)\n",
GNUNET_h2s (denom_hash),
- TALER_amount2s (&ds->denom_balance),
- (unsigned long long) ds->num_issued);
+ TALER_amount2s (&ds->dcd.denom_balance),
+ (unsigned long long) ds->dcd.num_issued);
cnt = TALER_ARL_edb->count_known_coins (TALER_ARL_edb->cls,
&denom_h);
if (0 > cnt)
@@ -903,39 +838,31 @@ sync_denomination (void *cls,
}
else
{
- if (ds->num_issued < (uint64_t) cnt)
+ if (ds->dcd.num_issued < (uint64_t) cnt)
{
/* more coins deposited than issued! very bad */
report_emergency_by_count (issue,
- ds->num_issued,
+ ds->dcd.num_issued,
cnt,
- &ds->denom_risk);
+ &ds->dcd.denom_risk);
}
if (ds->report_emergency)
{
/* Value of coins deposited exceed value of coins
issued! Also very bad! */
report_emergency_by_amount (issue,
- &ds->denom_risk,
- &ds->denom_loss);
+ &ds->dcd.denom_risk,
+ &ds->dcd.denom_loss);
}
if (ds->in_db)
qs = TALER_ARL_adb->update_denomination_balance (TALER_ARL_adb->cls,
&denom_h,
- &ds->denom_balance,
- &ds->denom_loss,
- &ds->denom_risk,
- &ds->denom_recoup,
- ds->num_issued);
+ &ds->dcd);
else
qs = TALER_ARL_adb->insert_denomination_balance (TALER_ARL_adb->cls,
&denom_h,
- &ds->denom_balance,
- &ds->denom_loss,
- &ds->denom_risk,
- &ds->denom_recoup,
- ds->num_issued);
+ &ds->dcd);
}
}
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
@@ -1032,22 +959,22 @@ withdraw_cb (void *cls,
"Issued coin in denomination `%s' of total value %s\n",
GNUNET_h2s (&dh.hash),
TALER_amount2s (&issue->value));
- ds->num_issued++;
- TALER_ARL_amount_add (&ds->denom_balance,
- &ds->denom_balance,
- &issue->value);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"New balance of denomination `%s' is %s\n",
GNUNET_h2s (&dh.hash),
- TALER_amount2s (&ds->denom_balance));
- TALER_ARL_amount_add (&total_escrow_balance,
- &total_escrow_balance,
+ TALER_amount2s (&ds->dcd.denom_balance));
+ TALER_ARL_amount_add (&balance.total_escrowed,
+ &balance.total_escrowed,
+ &issue->value);
+ TALER_ARL_amount_add (&balance.risk,
+ &balance.risk,
&issue->value);
- TALER_ARL_amount_add (&total_risk,
- &total_risk,
+ ds->dcd.num_issued++;
+ TALER_ARL_amount_add (&ds->dcd.denom_balance,
+ &ds->dcd.denom_balance,
&issue->value);
- TALER_ARL_amount_add (&ds->denom_risk,
- &ds->denom_risk,
+ TALER_ARL_amount_add (&ds->dcd.denom_risk,
+ &ds->dcd.denom_risk,
&issue->value);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -1201,8 +1128,8 @@ check_known_coin (
loss_potential),
GNUNET_JSON_pack_data_auto ("coin_pub",
coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
loss_potential);
}
TALER_denom_sig_free (&ci.denom_sig);
@@ -1228,19 +1155,19 @@ reduce_denom_balance (struct DenominationSummary *dso,
if (TALER_ARL_SR_INVALID_NEGATIVE ==
TALER_ARL_amount_subtract_neg (&tmp,
- &dso->denom_balance,
+ &dso->dcd.denom_balance,
amount_with_fee))
{
- TALER_ARL_amount_add (&dso->denom_loss,
- &dso->denom_loss,
+ TALER_ARL_amount_add (&dso->dcd.denom_loss,
+ &dso->dcd.denom_loss,
amount_with_fee);
dso->report_emergency = true;
}
else
{
- dso->denom_balance = tmp;
+ dso->dcd.denom_balance = tmp;
}
- if (-1 == TALER_amount_cmp (&total_escrow_balance,
+ if (-1 == TALER_amount_cmp (&balance.total_escrowed,
amount_with_fee))
{
/* This can theoretically happen if for example the exchange
@@ -1252,20 +1179,20 @@ reduce_denom_balance (struct DenominationSummary *dso,
report_amount_arithmetic_inconsistency (
"subtracting amount from escrow balance",
rowid,
- &total_escrow_balance,
+ &balance.total_escrowed,
amount_with_fee,
0);
}
else
{
- TALER_ARL_amount_subtract (&total_escrow_balance,
- &total_escrow_balance,
+ TALER_ARL_amount_subtract (&balance.total_escrowed,
+ &balance.total_escrowed,
amount_with_fee);
}
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"New balance of denomination `%s' is %s\n",
GNUNET_h2s (&dso->issue->denom_hash.hash),
- TALER_amount2s (&dso->denom_balance));
+ TALER_amount2s (&dso->dcd.denom_balance));
}
@@ -1365,8 +1292,8 @@ refresh_session_cb (void *cls,
amount_with_fee),
GNUNET_JSON_pack_data_auto ("coin_pub",
coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount_with_fee);
}
}
@@ -1501,22 +1428,22 @@ refresh_session_cb (void *cls,
"Created fresh coin in denomination `%s' of value %s\n",
GNUNET_h2s (&ni->denom_hash.hash),
TALER_amount2s (&ni->value));
- dsi->num_issued++;
- TALER_ARL_amount_add (&dsi->denom_balance,
- &dsi->denom_balance,
+ dsi->dcd.num_issued++;
+ TALER_ARL_amount_add (&dsi->dcd.denom_balance,
+ &dsi->dcd.denom_balance,
&ni->value);
- TALER_ARL_amount_add (&dsi->denom_risk,
- &dsi->denom_risk,
+ TALER_ARL_amount_add (&dsi->dcd.denom_risk,
+ &dsi->dcd.denom_risk,
&ni->value);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"New balance of denomination `%s' is %s\n",
GNUNET_h2s (&ni->denom_hash.hash),
- TALER_amount2s (&dsi->denom_balance));
- TALER_ARL_amount_add (&total_escrow_balance,
- &total_escrow_balance,
+ TALER_amount2s (&dsi->dcd.denom_balance));
+ TALER_ARL_amount_add (&balance.total_escrowed,
+ &balance.total_escrowed,
&ni->value);
- TALER_ARL_amount_add (&total_risk,
- &total_risk,
+ TALER_ARL_amount_add (&balance.risk,
+ &balance.risk,
&ni->value);
}
}
@@ -1541,8 +1468,8 @@ refresh_session_cb (void *cls,
}
/* update global melt fees */
- TALER_ARL_amount_add (&total_melt_fee_income,
- &total_melt_fee_income,
+ TALER_ARL_amount_add (&balance.melt_fee_balance,
+ &balance.melt_fee_balance,
&issue->fees.refresh);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -1657,8 +1584,8 @@ deposit_cb (void *cls,
&deposit->amount_with_fee),
GNUNET_JSON_pack_data_auto ("coin_pub",
&deposit->coin.coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
&deposit->amount_with_fee);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -1689,8 +1616,8 @@ deposit_cb (void *cls,
}
/* update global deposit fees */
- TALER_ARL_amount_add (&total_deposit_fee_income,
- &total_deposit_fee_income,
+ TALER_ARL_amount_add (&balance.deposit_fee_balance,
+ &balance.deposit_fee_balance,
&issue->fees.deposit);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -1774,8 +1701,8 @@ refund_cb (void *cls,
amount_with_fee),
GNUNET_JSON_pack_data_auto ("coin_pub",
coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount_with_fee);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -1815,31 +1742,31 @@ refund_cb (void *cls,
}
else
{
- TALER_ARL_amount_add (&ds->denom_balance,
- &ds->denom_balance,
+ TALER_ARL_amount_add (&ds->dcd.denom_balance,
+ &ds->dcd.denom_balance,
&amount_without_fee);
- TALER_ARL_amount_add (&ds->denom_risk,
- &ds->denom_risk,
+ TALER_ARL_amount_add (&ds->dcd.denom_risk,
+ &ds->dcd.denom_risk,
&amount_without_fee);
- TALER_ARL_amount_add (&total_escrow_balance,
- &total_escrow_balance,
+ TALER_ARL_amount_add (&balance.total_escrowed,
+ &balance.total_escrowed,
&amount_without_fee);
- TALER_ARL_amount_add (&total_risk,
- &total_risk,
+ TALER_ARL_amount_add (&balance.risk,
+ &balance.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.hash),
- TALER_amount2s (&ds->denom_balance));
+ TALER_amount2s (&ds->dcd.denom_balance));
}
/* update total refund fee balance */
- TALER_ARL_amount_add (&total_refund_fee_income,
- &total_refund_fee_income,
+ TALER_ARL_amount_add (&balance.refund_fee_balance,
+ &balance.refund_fee_balance,
&issue->fees.refund);
if (full_refund)
{
- TALER_ARL_amount_subtract (&total_deposit_fee_income,
- &total_deposit_fee_income,
+ TALER_ARL_amount_subtract (&balance.deposit_fee_balance,
+ &balance.deposit_fee_balance,
&issue->fees.deposit);
}
if (TALER_ARL_do_abort ())
@@ -1907,26 +1834,26 @@ purse_refund_coin_cb (
}
else
{
- TALER_ARL_amount_add (&ds->denom_balance,
- &ds->denom_balance,
+ TALER_ARL_amount_add (&ds->dcd.denom_balance,
+ &ds->dcd.denom_balance,
amount_with_fee);
- TALER_ARL_amount_add (&ds->denom_risk,
- &ds->denom_risk,
+ TALER_ARL_amount_add (&ds->dcd.denom_risk,
+ &ds->dcd.denom_risk,
amount_with_fee);
- TALER_ARL_amount_add (&total_escrow_balance,
- &total_escrow_balance,
+ TALER_ARL_amount_add (&balance.total_escrowed,
+ &balance.total_escrowed,
amount_with_fee);
- TALER_ARL_amount_add (&total_risk,
- &total_risk,
+ TALER_ARL_amount_add (&balance.risk,
+ &balance.risk,
amount_with_fee);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"New balance of denomination `%s' after purse-refund is %s\n",
GNUNET_h2s (&issue->denom_hash.hash),
- TALER_amount2s (&ds->denom_balance));
+ TALER_amount2s (&ds->dcd.denom_balance));
}
/* update total deposit fee balance */
- TALER_ARL_amount_subtract (&total_deposit_fee_income,
- &total_deposit_fee_income,
+ TALER_ARL_amount_subtract (&balance.deposit_fee_balance,
+ &balance.deposit_fee_balance,
&issue->fees.deposit);
return GNUNET_OK;
@@ -1941,16 +1868,22 @@ purse_refund_coin_cb (
* @param cls closure
* @param rowid unique serial ID for the refund in our DB
* @param purse_pub public key of the purse
+ * @param reserve_pub public key of the targeted reserve (ignored)
+ * @param val targeted amount to be in the reserve (ignored)
* @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
*/
static enum GNUNET_GenericReturnValue
purse_refund_cb (void *cls,
uint64_t rowid,
- const struct TALER_PurseContractPublicKeyP *purse_pub)
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *val)
{
struct CoinContext *cc = cls;
enum GNUNET_DB_QueryStatus qs;
+ (void) val; /* irrelevant on refund */
+ (void) reserve_pub; /* irrelevant, may even be NULL */
GNUNET_assert (rowid >= ppc.last_purse_refunds_serial_id); /* should be monotonically increasing */
ppc.last_purse_refunds_serial_id = rowid + 1;
qs = TALER_ARL_edb->select_purse_deposits_by_purse (TALER_ARL_edb->cls,
@@ -2020,8 +1953,8 @@ check_recoup (struct CoinContext *cc,
amount),
GNUNET_JSON_pack_data_auto ("coin_pub",
&coin->denom_pub_hash)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount);
}
qs = TALER_ARL_get_denomination_info_by_hash (&coin->denom_pub_hash,
@@ -2081,15 +2014,15 @@ check_recoup (struct CoinContext *cc,
amount),
GNUNET_JSON_pack_data_auto ("coin_pub",
&coin->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount);
}
- TALER_ARL_amount_add (&ds->denom_recoup,
- &ds->denom_recoup,
+ TALER_ARL_amount_add (&ds->dcd.recoup_loss,
+ &ds->dcd.recoup_loss,
amount);
- TALER_ARL_amount_add (&total_recoup_loss,
- &total_recoup_loss,
+ TALER_ARL_amount_add (&balance.loss,
+ &balance.loss,
amount);
}
if (TALER_ARL_do_abort ())
@@ -2145,8 +2078,8 @@ recoup_cb (void *cls,
amount),
GNUNET_JSON_pack_data_auto ("coin_pub",
&coin->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -2233,13 +2166,13 @@ recoup_refresh_cb (void *cls,
}
else
{
- TALER_ARL_amount_add (&dso->denom_balance,
- &dso->denom_balance,
+ TALER_ARL_amount_add (&dso->dcd.denom_balance,
+ &dso->dcd.denom_balance,
amount);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"New balance of denomination `%s' after refresh-recoup is %s\n",
GNUNET_h2s (&issue->denom_hash.hash),
- TALER_amount2s (&dso->denom_balance));
+ TALER_amount2s (&dso->dcd.denom_balance));
}
}
@@ -2259,8 +2192,8 @@ recoup_refresh_cb (void *cls,
amount),
GNUNET_JSON_pack_data_auto ("coin_pub",
&coin->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
amount);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -2432,8 +2365,8 @@ purse_deposit_cb (
&deposit->amount),
GNUNET_JSON_pack_data_auto ("coin_pub",
&deposit->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
+ TALER_ARL_amount_add (&balance.irregular_loss,
+ &balance.irregular_loss,
&deposit->amount);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -2458,8 +2391,8 @@ purse_deposit_cb (
}
/* update global deposit fees */
- TALER_ARL_amount_add (&total_deposit_fee_income,
- &total_deposit_fee_income,
+ TALER_ARL_amount_add (&balance.deposit_fee_balance,
+ &balance.deposit_fee_balance,
&issue->fees.deposit);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
@@ -2511,13 +2444,15 @@ analyze_coins (void *cls)
{
ppc_start = ppc;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Resuming coin audit at %llu/%llu/%llu/%llu/%llu/%llu\n",
+ "Resuming coin audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
(unsigned long long) ppc.last_deposit_serial_id,
(unsigned long long) ppc.last_melt_serial_id,
(unsigned long long) ppc.last_refund_serial_id,
(unsigned long long) ppc.last_withdraw_serial_id,
(unsigned long long) ppc.last_recoup_refresh_serial_id,
- (unsigned long long) ppc.last_purse_deposits_serial_id);
+ (unsigned long long) ppc.last_open_deposits_serial_id,
+ (unsigned long long) ppc.last_purse_deposits_serial_id,
+ (unsigned long long) ppc.last_purse_refunds_serial_id);
}
/* setup 'cc' */
@@ -2526,13 +2461,7 @@ analyze_coins (void *cls)
GNUNET_NO);
qsx = TALER_ARL_adb->get_balance_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_deposit_fee_income,
- &total_melt_fee_income,
- &total_refund_fee_income,
- &total_risk,
- &total_recoup_loss,
- &total_irregular_recoups);
+ &balance);
if (0 > qsx)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
@@ -2569,9 +2498,10 @@ analyze_coins (void *cls)
/* process purse_refunds */
if (0 >
- (qs = TALER_ARL_edb->select_purse_refunds_above_serial_id (
+ (qs = TALER_ARL_edb->select_purse_decisions_above_serial_id (
TALER_ARL_edb->cls,
ppc.last_purse_refunds_serial_id,
+ true, /* only go for refunds! */
&purse_refund_cb,
&cc)))
{
@@ -2663,23 +2593,11 @@ analyze_coins (void *cls)
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsx)
qs = TALER_ARL_adb->update_balance_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_deposit_fee_income,
- &total_melt_fee_income,
- &total_refund_fee_income,
- &total_risk,
- &total_recoup_loss,
- &total_irregular_recoups);
+ &balance);
else
qs = TALER_ARL_adb->insert_balance_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_deposit_fee_income,
- &total_melt_fee_income,
- &total_refund_fee_income,
- &total_risk,
- &total_recoup_loss,
- &total_irregular_recoups);
+ &balance);
if (0 >= qs)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
@@ -2702,13 +2620,15 @@ analyze_coins (void *cls)
return qs;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu/%llu\n",
+ "Concluded coin audit step at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
(unsigned long long) ppc.last_deposit_serial_id,
(unsigned long long) ppc.last_melt_serial_id,
(unsigned long long) ppc.last_refund_serial_id,
(unsigned long long) ppc.last_withdraw_serial_id,
(unsigned long long) ppc.last_recoup_refresh_serial_id,
- (unsigned long long) ppc.last_purse_deposits_serial_id);
+ (unsigned long long) ppc.last_open_deposits_serial_id,
+ (unsigned long long) ppc.last_purse_deposits_serial_id,
+ (unsigned long long) ppc.last_purse_refunds_serial_id);
return qs;
}
@@ -2754,34 +2674,37 @@ run (void *cls,
&reported_emergency_loss_by_count));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_escrow_balance));
+ &balance.total_escrowed));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_risk));
+ &balance.deposit_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_recoup_loss));
+ &balance.melt_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_irregular_recoups));
+ &balance.refund_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_deposit_fee_income));
+ &balance.purse_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_melt_fee_income));
+ &balance.open_deposit_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_refund_fee_income));
+ &balance.risk));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_arithmetic_delta_plus));
+ &balance.loss));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_arithmetic_delta_minus));
+ &balance.irregular_loss));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_arithmetic_delta_plus));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_bad_sig_loss));
+ &total_arithmetic_delta_minus));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
&total_refresh_hanging));
@@ -2812,27 +2735,30 @@ run (void *cls,
TALER_ARL_done (
GNUNET_JSON_PACK (
TALER_JSON_pack_amount ("total_escrow_balance",
- &total_escrow_balance),
- TALER_JSON_pack_amount ("total_active_risk",
- &total_risk),
+ &balance.total_escrowed),
TALER_JSON_pack_amount ("total_deposit_fee_income",
- &total_deposit_fee_income),
+ &balance.deposit_fee_balance),
TALER_JSON_pack_amount ("total_melt_fee_income",
- &total_melt_fee_income),
+ &balance.melt_fee_balance),
TALER_JSON_pack_amount ("total_refund_fee_income",
- &total_refund_fee_income),
+ &balance.refund_fee_balance),
+ TALER_JSON_pack_amount ("total_purse_fee_income",
+ &balance.purse_fee_balance),
+ TALER_JSON_pack_amount ("total_open_deposit_fee_income",
+ &balance.open_deposit_fee_balance),
+ TALER_JSON_pack_amount ("total_active_risk",
+ &balance.risk),
+ TALER_JSON_pack_amount ("total_recoup_loss",
+ &balance.loss),
+ /* Tested in test-auditor.sh #4/#5/#6/#13/#26 */
+ TALER_JSON_pack_amount ("irregular_loss",
+ &balance.irregular_loss),
/* Tested in test-auditor.sh #18 */
GNUNET_JSON_pack_array_steal ("emergencies",
report_emergencies),
/* Tested in test-auditor.sh #18 */
TALER_JSON_pack_amount ("emergencies_risk_by_amount",
&reported_emergency_risk_by_amount),
- /* Tested in test-auditor.sh #4/#5/#6/#13/#26 */
- GNUNET_JSON_pack_array_steal ("bad_sig_losses",
- report_bad_sig_losses),
- /* Tested in test-auditor.sh #4/#5/#6/#13/#26 */
- TALER_JSON_pack_amount ("total_bad_sig_loss",
- &total_bad_sig_loss),
/* Tested in test-auditor.sh #31 */
GNUNET_JSON_pack_array_steal ("row_inconsistencies",
report_row_inconsistencies),
@@ -2845,11 +2771,11 @@ run (void *cls,
&total_arithmetic_delta_minus),
TALER_JSON_pack_amount ("total_refresh_hanging",
&total_refresh_hanging),
+ GNUNET_JSON_pack_array_steal ("bad_sig_losses",
+ report_bad_sig_losses),
/* Tested in test-auditor.sh #12 */
GNUNET_JSON_pack_array_steal ("refresh_hanging",
report_refreshs_hanging),
- TALER_JSON_pack_amount ("total_recoup_loss",
- &total_recoup_loss),
/* Tested in test-auditor.sh #18 */
GNUNET_JSON_pack_array_steal ("emergencies_by_count",
report_emergencies_by_count),
@@ -2898,8 +2824,6 @@ run (void *cls,
start_time),
TALER_JSON_pack_time_abs_human ("auditor_end_time",
GNUNET_TIME_absolute_get ()),
- TALER_JSON_pack_amount ("total_irregular_recoups",
- &total_irregular_recoups),
GNUNET_JSON_pack_array_steal ("unsigned_denominations",
report_denominations_without_sigs)));
}
diff --git a/src/auditor/taler-helper-auditor-purses.c b/src/auditor/taler-helper-auditor-purses.c
new file mode 100644
index 000000000..e0c939faa
--- /dev/null
+++ b/src/auditor/taler-helper-auditor-purses.c
@@ -0,0 +1,1123 @@
+/*
+ This file is part of TALER
+ Copyright (C) 2016-2022 Taler Systems SA
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Affero Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero Public License for more details.
+
+ You should have received a copy of the GNU Affero Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor/taler-helper-auditor-purses.c
+ * @brief audits the purses of an exchange database
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_auditordb_plugin.h"
+#include "taler_exchangedb_lib.h"
+#include "taler_json_lib.h"
+#include "taler_bank_service.h"
+#include "taler_signatures.h"
+#include "report-lib.h"
+
+
+/**
+ * Use a 1 day grace period to deal with clocks not being perfectly synchronized.
+ */
+#define CLOSING_GRACE_PERIOD GNUNET_TIME_UNIT_DAYS
+
+/**
+ * Return value from main().
+ */
+static int global_ret;
+
+/**
+ * Checkpointing our progress for purses.
+ */
+static struct TALER_AUDITORDB_ProgressPointPurse ppp;
+
+/**
+ * Checkpointing our progress for purses.
+ */
+static struct TALER_AUDITORDB_ProgressPointPurse ppp_start;
+
+/**
+ * Array of reports about row inconsitencies.
+ */
+static json_t *report_row_inconsistencies;
+
+/**
+ * Array of reports about purse balance insufficient inconsitencies.
+ */
+static json_t *report_purse_balance_insufficient_inconsistencies;
+
+/**
+ * Total amount purses were merged with insufficient balance.
+ */
+static struct TALER_Amount total_balance_insufficient_loss;
+
+/**
+ * Array of reports about purses's not being closed inconsitencies.
+ */
+static json_t *report_purse_not_closed_inconsistencies;
+
+/**
+ * Total amount affected by purses not having been closed on time.
+ */
+static struct TALER_Amount total_balance_purse_not_closed;
+
+/**
+ * Report about amount calculation differences (causing profit
+ * or loss at the exchange).
+ */
+static json_t *report_amount_arithmetic_inconsistencies;
+
+/**
+ * Profits the exchange made by bad amount calculations.
+ */
+static struct TALER_Amount total_arithmetic_delta_plus;
+
+/**
+ * Losses the exchange made by bad amount calculations.
+ */
+static struct TALER_Amount total_arithmetic_delta_minus;
+
+/**
+ * Array of reports about coin operations with bad signatures.
+ */
+static json_t *report_bad_sig_losses;
+
+/**
+ * Total amount lost by operations for which signatures were invalid.
+ */
+static struct TALER_Amount total_bad_sig_loss;
+
+/**
+ * Should we run checks that only work for exchange-internal audits?
+ */
+static int internal_checks;
+
+/* ***************************** Report logic **************************** */
+
+
+/**
+ * Report a (serious) inconsistency in the exchange's database with
+ * respect to calculations involving amounts.
+ *
+ * @param operation what operation had the inconsistency
+ * @param rowid affected row, 0 if row is missing
+ * @param exchange amount calculated by exchange
+ * @param auditor amount calculated by auditor
+ * @param profitable 1 if @a exchange being larger than @a auditor is
+ * profitable for the exchange for this operation,
+ * -1 if @a exchange being smaller than @a auditor is
+ * profitable for the exchange, and 0 if it is unclear
+ */
+static void
+report_amount_arithmetic_inconsistency (
+ const char *operation,
+ uint64_t rowid,
+ const struct TALER_Amount *exchange,
+ const struct TALER_Amount *auditor,
+ int profitable)
+{
+ struct TALER_Amount delta;
+ struct TALER_Amount *target;
+
+ if (0 < TALER_amount_cmp (exchange,
+ auditor))
+ {
+ /* exchange > auditor */
+ TALER_ARL_amount_subtract (&delta,
+ exchange,
+ auditor);
+ }
+ else
+ {
+ /* auditor < exchange */
+ profitable = -profitable;
+ TALER_ARL_amount_subtract (&delta,
+ auditor,
+ exchange);
+ }
+ TALER_ARL_report (report_amount_arithmetic_inconsistencies,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ operation),
+ GNUNET_JSON_pack_uint64 ("rowid",
+ rowid),
+ TALER_JSON_pack_amount ("exchange",
+ exchange),
+ TALER_JSON_pack_amount ("auditor",
+ auditor),
+ GNUNET_JSON_pack_int64 ("profitable",
+ profitable)));
+ if (0 != profitable)
+ {
+ target = (1 == profitable)
+ ? &total_arithmetic_delta_plus
+ : &total_arithmetic_delta_minus;
+ TALER_ARL_amount_add (target,
+ target,
+ &delta);
+ }
+}
+
+
+/**
+ * Report a (serious) inconsistency in the exchange's database.
+ *
+ * @param table affected table
+ * @param rowid affected row, 0 if row is missing
+ * @param diagnostic message explaining the problem
+ */
+static void
+report_row_inconsistency (const char *table,
+ uint64_t rowid,
+ const char *diagnostic)
+{
+ TALER_ARL_report (report_row_inconsistencies,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("table",
+ table),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ GNUNET_JSON_pack_string ("diagnostic",
+ diagnostic)));
+}
+
+
+/* ***************************** Analyze purses ************************ */
+/* This logic checks the purses_requests, purse_deposits,
+ purse_refunds, purse_merges and account_merges */
+
+/**
+ * Summary data we keep per purse.
+ */
+struct PurseSummary
+{
+ /**
+ * Public key of the purse.
+ * Always set when the struct is first initialized.
+ */
+ struct TALER_PursePublicKeyP purse_pub;
+
+ /**
+ * Sum of all incoming transfers during this transaction.
+ * Updated only in #handle_purse_deposits().
+ */
+ struct TALER_Amount total_in;
+
+ /**
+ * Expected value of the purse.
+ */
+ struct TALER_Amount total_value;
+
+ /**
+ * Purse expiration date.
+ */
+ struct GNUNET_TIME_Timestamp expiration_date;
+
+ /**
+ * Did we have a previous purse info? Used to decide between UPDATE and
+ * INSERT later. Initialized in #load_auditor_purse_summary().
+ */
+ bool had_pi;
+
+};
+
+
+/**
+ * Load the auditor's remembered state about the purse into @a ps.
+ *
+ * @param[in,out] ps purse summary to (fully) initialize
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+load_auditor_purse_summary (struct PurseSummary *ps)
+{
+ enum GNUNET_DB_QueryStatus qs;
+ uint64_t rowid;
+
+ qs = TALER_ARL_adb->get_purse_info (TALER_ARL_adb->cls,
+ &ps->purse_pub,
+ &TALER_ARL_master_pub,
+ &rowid,
+ &ps->total_in,
+ &ps->expiration_date);
+ if (0 > qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ ps->had_pi = false;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &ps->prev_balance.reserve_balance));
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Creating fresh purse `%s'\n",
+ TALER_B2S (&ps->purse_pub));
+ return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+ }
+ ps->had_ri = true;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Auditor remembers purse `%s' has balance %s\n",
+ TALER_B2S (&ps->purse_pub),
+ TALER_amount2s (&ps->total_in));
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+/**
+ * Closure to the various callbacks we make while checking a purse.
+ */
+struct PurseContext
+{
+ /**
+ * Map from hash of purse's public key to a `struct PurseSummary`.
+ */
+ struct GNUNET_CONTAINER_MultiHashMap *purses;
+
+ /**
+ * Transaction status code, set to error codes if applicable.
+ */
+ enum GNUNET_DB_QueryStatus qs;
+
+};
+
+
+/**
+ * Create a new reserve for @a reserve_pub in @a rc.
+ *
+ * @param[in,out] pc context to update
+ * @param purse_pub key for which to create a purse
+ * @return NULL on error
+ */
+static struct PurseSummary *
+setup_purse (struct PurseContext *pc,
+ const struct TALER_PursePublicKeyP *purse_pub)
+{
+ struct PurseSummary *rs;
+ struct GNUNET_HashCode key;
+ enum GNUNET_DB_QueryStatus qs;
+
+ GNUNET_CRYPTO_hash (purse_pub,
+ sizeof (*purse_pub),
+ &key);
+ ps = GNUNET_CONTAINER_multihashmap_get (rc->purses,
+ &key);
+ if (NULL != ps)
+ return ps;
+ ps = GNUNET_new (struct PurseSummary);
+ ps->purse_pub = *purse_pub;
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &ps->total_in));
+ if (0 > (qs = load_auditor_purse_summary (ps)))
+ {
+ GNUNET_free (ps);
+ rc->qs = qs;
+ return NULL;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CONTAINER_multihashmap_put (rc->purses,
+ &key,
+ ps,
+ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+ return ps;
+}
+
+
+/**
+ * Check that the purse summary matches what the exchange database
+ * thinks about the purse, and update our own state of the purse.
+ *
+ * Remove all purses that we are happy with from the DB.
+ *
+ * @param cls our `struct PurseContext`
+ * @param key hash of the purse public key
+ * @param value a `struct PurseSummary`
+ * @return #GNUNET_OK to process more entries
+ */
+static enum GNUNET_GenericReturnValue
+verify_purse_balance (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
+{
+ struct PurseContext *rc = cls;
+ struct PurseSummary *ps = value;
+ enum GNUNET_GenericReturnValue ret;
+
+ ret = GNUNET_OK;
+ // FIXME: implement!
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap_remove (rc->purses,
+ key,
+ rp));
+ GNUNET_free (ps);
+ return ret;
+}
+
+
+/**
+ * Function called with details about purse deposits that have been made, with
+ * the goal of auditing the deposit's execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param deposit deposit details
+ * @param reserve_pub which reserve is the purse merged into, NULL if unknown
+ * @param flags purse flags
+ * @param auditor_balance purse balance (according to the
+ * auditor during auditing)
+ * @param purse_total target amount the purse should reach
+ * @param denom_pub denomination public key of @a coin_pub
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_purse_deposits (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_EXCHANGEDB_PurseDeposit *deposit,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *auditor_balance,
+ const struct TALER_Amount *purse_total,
+ const struct TALER_DenominationPublicKey *denom_pub)
+{
+ struct PurseContext *rc = cls;
+ const char *base_url
+ = (NULL == deposit->exchange_base_url)
+ ? TALER_ARL_exchange_url
+ : deposit->exchange_base_url;
+ enum GNUNET_DB_QueryStatus qs;
+ struct TALER_Amount amount_minus_fee;
+ struct TALER_Amount new_balance;
+ struct PurseSummary *rs;
+ struct TALER_DenominationHashP h_denom_pub;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_purse_deposits_serial_id);
+ ppr.last_purse_deposits_serial_id = rowid + 1;
+
+ {
+ const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TALER_ARL_get_denomination_info (denom_pub,
+ &issue,
+ &h_denom_pub);
+ if (0 > qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ if (GNUNET_DB_STATUS_HARD_ERROR == qs)
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Hard database error trying to get denomination %s from database!\n",
+ TALER_B2S (denom_pub));
+ rc->qs = qs;
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+ {
+ report_row_inconsistency ("purse-deposit",
+ rowid,
+ "denomination key not found");
+ if (TALER_ARL_do_abort ())
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+ }
+ TALER_ARL_amount_subtract (&amount_minus_fee,
+ &deposit->amount,
+ &issue->fees.deposit);
+ }
+
+ if (GNUNET_OK !=
+ TALER_wallet_purse_deposit_verify (base_url,
+ &deposit->purse_pub,
+ &deposit->amount,
+ &h_denom_pub,
+ &deposit->h_age_commitment,
+ &deposit->coin_pub,
+ &deposit->coin_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "purse-deposit"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ &deposit->amount),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ &deposit->coin_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ &deposit->amount);
+ return GNUNET_OK;
+ }
+
+ TALER_ARL_amount_add (&new_balance,
+ auditor_balance,
+ &amount_minus_fee);
+ qs = TALER_ARL_edb->set_purse_balance (TALER_ARL_edb->cls,
+ &deposit->purse_pub,
+ &new_balance);
+ GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
+ rc->qs = qs;
+ return GNUNET_SYSERR;
+ }
+ if (TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE !=
+ (flags & TALER_WAMF_MERGE_MODE_MASK))
+ {
+ /* This just created the purse, actual credit to
+ the reserve will be done in handle_account_merged() */
+ return GNUNET_OK;
+ }
+ if ( (NULL != deposit->exchange_base_url) &&
+ (0 != strcmp (deposit->exchange_base_url,
+ TALER_ARL_exchange_url)) )
+ {
+ /* credited reserve is at another exchange, do NOT credit here! */
+ return GNUNET_OK;
+ }
+
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if ( (-1 != TALER_amount_cmp (&new_balance,
+ purse_total)) &&
+ (-1 == TALER_amount_cmp (auditor_balance,
+ purse_total)) )
+ {
+ /* new balance at or above purse_total
+ (and previous balance was below); thus
+ credit reserve with purse value! */
+ TALER_ARL_amount_add (&rs->total_in,
+ &rs->total_in,
+ purse_total);
+ }
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about purse
+ * merges that have been made, with
+ * the goal of auditing the purse merge execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param partner_base_url where is the reserve, NULL for this exchange
+ * @param amount total amount expected in the purse
+ * @param balance current balance in the purse (according to the auditor)
+ * @param flags purse flags
+ * @param merge_pub merge capability key
+ * @param reserve_pub reserve the merge affects
+ * @param merge_sig signature affirming the merge
+ * @param purse_pub purse key
+ * @param merge_timestamp when did the merge happen
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_purse_merged (
+ void *cls,
+ uint64_t rowid,
+ const char *partner_base_url,
+ const struct TALER_Amount *amount,
+ const struct TALER_Amount *balance,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_PurseMergePublicKeyP *merge_pub,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PurseMergeSignatureP *merge_sig,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ struct GNUNET_TIME_Timestamp merge_timestamp)
+{
+ struct PurseContext *rc = cls;
+ struct PurseSummary *rs;
+ char *reserve_url;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_purse_merges_serial_id);
+ ppr.last_purse_merges_serial_id = rowid + 1;
+ reserve_url
+ = TALER_reserve_make_payto (NULL == partner_base_url
+ ? TALER_ARL_exchange_url
+ : partner_base_url,
+ reserve_pub);
+ if (GNUNET_OK !=
+ TALER_wallet_purse_merge_verify (reserve_url,
+ merge_timestamp,
+ purse_pub,
+ merge_pub,
+ merge_sig))
+ {
+ GNUNET_free (reserve_url);
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "merge-purse"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ amount),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ merge_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ amount);
+ return GNUNET_OK;
+ }
+ GNUNET_free (reserve_url);
+ if (TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE ==
+ (flags & TALER_WAMF_MERGE_MODE_MASK))
+ {
+ /* This just created the purse, actual credit to
+ the reserve will be done in handle_purse_deposits() */
+ return GNUNET_OK;
+ }
+ if ( (NULL != partner_base_url) &&
+ (0 != strcmp (partner_base_url,
+ TALER_ARL_exchange_url)) )
+ {
+ /* credited reserve is at another exchange, do NOT credit here! */
+ return GNUNET_OK;
+ }
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (-1 == TALER_amount_cmp (balance,
+ amount))
+ {
+ struct TALER_Amount loss;
+
+ TALER_ARL_amount_subtract (&loss,
+ amount,
+ balance);
+ /* illegal merge, balance is still below total purse value */
+ TALER_ARL_report (report_purse_balance_insufficient_inconsistencies,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "merge-purse"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ &loss),
+ GNUNET_JSON_pack_data_auto ("purse_pub",
+ purse_pub)));
+ TALER_ARL_amount_add (&total_balance_insufficient_loss,
+ &total_balance_insufficient_loss,
+ &loss);
+ return GNUNET_OK;
+ }
+ TALER_ARL_amount_add (&rs->total_in,
+ &rs->total_in,
+ amount);
+ // rs->a_expiration_date = FIXME: do we care? If so, set to what (so that the auditor no longer complains about the reserve not being closed)
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about
+ * account merge requests that have been made, with
+ * the goal of auditing the account merge execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param reserve_pub reserve affected by the merge
+ * @param purse_pub purse being merged
+ * @param h_contract_terms hash over contract of the purse
+ * @param purse_expiration when would the purse expire
+ * @param amount total amount in the purse
+ * @param min_age minimum age of all coins deposited into the purse
+ * @param flags how was the purse created
+ * @param purse_fee if a purse fee was paid, how high is it
+ * @param merge_timestamp when was the merge approved
+ * @param reserve_sig signature by reserve approving the merge
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_account_merged (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp purse_expiration,
+ const struct TALER_Amount *amount,
+ uint32_t min_age,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *purse_fee,
+ struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_PursesignatureP *reserve_sig)
+{
+ struct PurseContext *rc = cls;
+ struct PurseSummary *rs;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_account_merges_serial_id);
+ ppr.last_account_merges_serial_id = rowid + 1;
+ if (GNUNET_OK !=
+ TALER_wallet_account_merge_verify (merge_timestamp,
+ purse_pub,
+ purse_expiration,
+ h_contract_terms,
+ amount,
+ purse_fee,
+ min_age,
+ flags,
+ reserve_pub,
+ reserve_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "account-merge"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ purse_fee),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ reserve_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ purse_fee);
+ return GNUNET_OK;
+ }
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ // FIXME: This is to be done per purse_requests,
+ // not per account_merges!
+ if ( (flags & TALER_WAMF_MERGE_MODE_MASK) ==
+ TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE)
+ {
+ TALER_ARL_amount_add (&balance.purse_fee_balance,
+ &balance.purse_fee_balance,
+ purse_fee);
+ TALER_ARL_amount_add (&rs->curr_balance.purse_fee_balance,
+ &rs->curr_balance.purse_fee_balance,
+ purse_fee);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ purse_fee);
+ }
+ TALER_ARL_amount_add (&rs->total_in,
+ &rs->total_in,
+ amount);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Analyze purses for being well-formed.
+ *
+ * @param cls NULL
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+analyze_purses (void *cls)
+{
+ struct PurseContext rc;
+ enum GNUNET_DB_QueryStatus qsx;
+ enum GNUNET_DB_QueryStatus qs;
+ enum GNUNET_DB_QueryStatus qsp;
+
+ (void) cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Analyzing purses\n");
+ qsp = TALER_ARL_adb->get_auditor_progress_purse (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &ppp);
+ if (0 > qsp)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsp);
+ return qsp;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsp)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+ "First analysis using this auditor, starting audit from scratch\n");
+ }
+ else
+ {
+ ppr_start = ppr;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Resuming purse audit at %llu/%llu/%llu\n",
+ (unsigned long long) ppp.last_purse_merges_serial_id,
+ (unsigned long long) ppp.last_purse_deposits_serial_id,
+ (unsigned long long) ppp.last_account_merges_serial_id);
+ }
+ rc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+ qsx = TALER_ARL_adb->get_reserve_summary (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &balance);
+ if (qsx < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
+ return qsx;
+ }
+ rc.purses = GNUNET_CONTAINER_multihashmap_create (512,
+ GNUNET_NO);
+ qs = TALER_ARL_edb->select_purse_merges_above_serial_id (
+ TALER_ARL_edb->cls,
+ ppr.last_purse_merges_serial_id,
+ &handle_purse_merged,
+ &rc);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ qs = TALER_ARL_edb->select_purse_deposits_above_serial_id (
+ TALER_ARL_edb->cls,
+ ppr.last_purse_deposits_serial_id,
+ &handle_purse_deposits,
+ &rc);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ /* Charge purse fee! */
+ qs = TALER_ARL_edb->select_account_merges_above_serial_id (
+ TALER_ARL_edb->cls,
+ ppr.last_account_merges_serial_id,
+ &handle_account_merged,
+ &rc);
+ if (qs < 0)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+
+ GNUNET_CONTAINER_multihashmap_iterate (rc.purses,
+ &verify_purse_balance,
+ &rc);
+ GNUNET_break (0 ==
+ GNUNET_CONTAINER_multihashmap_size (rc.purses));
+ GNUNET_CONTAINER_multihashmap_destroy (rc.purses);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != rc.qs)
+ return qs;
+ if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx)
+ {
+ qs = TALER_ARL_adb->insert_reserve_summary (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &balance);
+ }
+ else
+ {
+ qs = TALER_ARL_adb->update_reserve_summary (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &balance);
+ }
+ if (0 >= qs)
+ {
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsp)
+ qs = TALER_ARL_adb->update_auditor_progress_purse (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &ppp);
+ else
+ qs = TALER_ARL_adb->insert_auditor_progress_purse (TALER_ARL_adb->cls,
+ &TALER_ARL_master_pub,
+ &ppp);
+ if (0 >= qs)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to update auditor DB, not recording progress\n");
+ GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+ return qs;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Concluded purse audit step at %llu/%llu/%llu\n",
+ (unsigned long long) ppp.last_purse_merges_serial_id,
+ (unsigned long long) ppp.last_purse_deposits_serial_id,
+ (unsigned long long) ppp.last_account_merges_serial_id);
+ return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+/**
+ * Main function that will be run.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param c configuration
+ */
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *c)
+{
+ (void) cls;
+ (void) args;
+ (void) cfgfile;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Launching auditor\n");
+ if (GNUNET_OK !=
+ TALER_ARL_init (c))
+ {
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.reserve_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.reserve_loss));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.withdraw_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.close_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.purse_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.open_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.history_fee_balance));
+ // REVIEW:
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_balance_summary_delta_plus));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_balance_summary_delta_minus));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_arithmetic_delta_plus));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_arithmetic_delta_minus));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_balance_reserve_not_closed));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &total_bad_sig_loss));
+
+ GNUNET_assert (NULL !=
+ (report_row_inconsistencies = json_array ()));
+ GNUNET_assert (NULL !=
+ (denomination_key_validity_withdraw_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_reserve_balance_summary_wrong_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_reserve_balance_insufficient_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_purse_balance_insufficient_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_reserve_not_closed_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_amount_arithmetic_inconsistencies
+ = json_array ()));
+ GNUNET_assert (NULL !=
+ (report_bad_sig_losses = json_array ()));
+ if (GNUNET_OK !=
+ TALER_ARL_setup_sessions_and_run (&analyze_purses,
+ NULL))
+ {
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ TALER_ARL_done (
+ GNUNET_JSON_PACK (
+ /* Globals (REVIEW!) */
+ /* Tested in test-auditor.sh #3 */
+ TALER_JSON_pack_amount ("total_loss_balance_insufficient",
+ &total_balance_insufficient_loss),
+ /* Tested in test-auditor.sh #3 */
+ GNUNET_JSON_pack_array_steal (
+ "reserve_balance_summary_wrong_inconsistencies",
+ report_reserve_balance_summary_wrong_inconsistencies),
+ TALER_JSON_pack_amount ("total_balance_summary_delta_plus",
+ &total_balance_summary_delta_plus),
+ TALER_JSON_pack_amount ("total_balance_summary_delta_minus",
+ &total_balance_summary_delta_minus),
+ /* Tested in test-auditor.sh #21 */
+ TALER_JSON_pack_amount ("total_balance_reserve_not_closed",
+ &total_balance_reserve_not_closed),
+ /* Tested in test-auditor.sh #7 */
+ TALER_JSON_pack_amount ("total_bad_sig_loss",
+ &total_bad_sig_loss),
+ TALER_JSON_pack_amount ("total_arithmetic_delta_plus",
+ &total_arithmetic_delta_plus),
+ TALER_JSON_pack_amount ("total_arithmetic_delta_minus",
+ &total_arithmetic_delta_minus),
+
+ /* Global 'balances' */
+ TALER_JSON_pack_amount ("total_escrow_balance",
+ &balance.reserve_balance),
+ TALER_JSON_pack_amount ("total_irregular_loss",
+ &balance.reserve_loss),
+ TALER_JSON_pack_amount ("total_withdraw_fee_income",
+ &balance.withdraw_fee_balance),
+ TALER_JSON_pack_amount ("total_close_fee_income",
+ &balance.close_fee_balance),
+ TALER_JSON_pack_amount ("total_purse_fee_income",
+ &balance.purse_fee_balance),
+ TALER_JSON_pack_amount ("total_open_fee_income",
+ &balance.open_fee_balance),
+ TALER_JSON_pack_amount ("total_history_fee_income",
+ &balance.history_fee_balance),
+
+ /* Detailed report tables */
+ GNUNET_JSON_pack_array_steal (
+ "reserve_balance_insufficient_inconsistencies",
+ report_reserve_balance_insufficient_inconsistencies),
+ GNUNET_JSON_pack_array_steal (
+ "purse_balance_insufficient_inconsistencies",
+ report_purse_balance_insufficient_inconsistencies),
+ /* Tested in test-auditor.sh #21 */
+ GNUNET_JSON_pack_array_steal ("reserve_not_closed_inconsistencies",
+ report_reserve_not_closed_inconsistencies),
+ /* Tested in test-auditor.sh #7 */
+ GNUNET_JSON_pack_array_steal ("bad_sig_losses",
+ report_bad_sig_losses),
+ /* Tested in test-revocation.sh #4 */
+ GNUNET_JSON_pack_array_steal ("row_inconsistencies",
+ report_row_inconsistencies),
+ /* Tested in test-auditor.sh #23 */
+ GNUNET_JSON_pack_array_steal (
+ "denomination_key_validity_withdraw_inconsistencies",
+ denomination_key_validity_withdraw_inconsistencies),
+ GNUNET_JSON_pack_array_steal ("amount_arithmetic_inconsistencies",
+ report_amount_arithmetic_inconsistencies),
+
+ /* Information about audited range ... */
+ TALER_JSON_pack_time_abs_human ("auditor_start_time",
+ start_time),
+ TALER_JSON_pack_time_abs_human ("auditor_end_time",
+ GNUNET_TIME_absolute_get ()),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_in_serial_id",
+ ppr_start.last_reserve_in_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_out_serial_id",
+ ppr_start.last_reserve_out_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_recoup_serial_id",
+ ppr_start.last_reserve_recoup_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_open_serial_id",
+ ppr_start.last_reserve_open_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_close_serial_id",
+ ppr_start.last_reserve_close_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_purse_merges_serial_id",
+ ppr_start.last_purse_merges_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_purse_deposits_serial_id",
+ ppr_start.last_purse_deposits_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_account_merges_serial_id",
+ ppr_start.last_account_merges_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_history_requests_serial_id",
+ ppr_start.last_history_requests_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_in_serial_id",
+ ppr.last_reserve_in_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_out_serial_id",
+ ppr.last_reserve_out_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_recoup_serial_id",
+ ppr.last_reserve_recoup_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_open_serial_id",
+ ppr.last_reserve_open_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_close_serial_id",
+ ppr.last_reserve_close_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_purse_merges_serial_id",
+ ppr.last_purse_merges_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_purse_deposits_serial_id",
+ ppr.last_purse_deposits_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_account_merges_serial_id",
+ ppr.last_account_merges_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_history_requests_serial_id",
+ ppr.last_history_requests_serial_id)));
+}
+
+
+/**
+ * The main function to check the database's handling of purses.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc,
+ char *const *argv)
+{
+ const struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_option_flag ('i',
+ "internal",
+ "perform checks only applicable for exchange-internal audits",
+ &internal_checks),
+ GNUNET_GETOPT_option_base32_auto ('m',
+ "exchange-key",
+ "KEY",
+ "public key of the exchange (Crockford base32 encoded)",
+ &TALER_ARL_master_pub),
+ GNUNET_GETOPT_option_timetravel ('T',
+ "timetravel"),
+ GNUNET_GETOPT_OPTION_END
+ };
+ enum GNUNET_GenericReturnValue ret;
+
+ /* force linker to link against libtalerutil; if we do
+ not do this, the linker may "optimize" libtalerutil
+ away and skip #TALER_OS_init(), which we do need */
+ (void) TALER_project_data_default ();
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_get_utf8_args (argc, argv,
+ &argc, &argv))
+ return EXIT_INVALIDARGUMENT;
+ ret = GNUNET_PROGRAM_run (
+ argc,
+ argv,
+ "taler-helper-auditor-purses",
+ gettext_noop ("Audit Taler exchange purse handling"),
+ options,
+ &run,
+ NULL);
+ GNUNET_free_nz ((void *) argv);
+ if (GNUNET_SYSERR == ret)
+ return EXIT_INVALIDARGUMENT;
+ if (GNUNET_NO == ret)
+ return EXIT_SUCCESS;
+ return global_ret;
+}
+
+
+/* end of taler-helper-auditor-purses.c */
diff --git a/src/auditor/taler-helper-auditor-render.py b/src/auditor/taler-helper-auditor-render.py
index 4b086cb62..b9c92b29c 100644
--- a/src/auditor/taler-helper-auditor-render.py
+++ b/src/auditor/taler-helper-auditor-render.py
@@ -53,4 +53,14 @@ jinjaEnv = jinja2.Environment(loader=StdinLoader(),
autoescape=False)
tmpl = jinjaEnv.get_template('stdin');
-print(tmpl.render(aggregation = jsonData1, coins = jsonData2, deposits = jsonData3, reserves = jsonData4, wire = jsonData5))
+try:
+ print(tmpl.render(aggregation = jsonData1, coins = jsonData2, deposits = jsonData3, reserves = jsonData4, wire = jsonData5))
+except jinja2.TemplateSyntaxError as error:
+ print("Template syntax error: {error.message} on line {error.lineno}.".format(error=error))
+ exit(1)
+except jinja2.UndefinedError as error:
+ print("Template undefined error: {error.message}.".format(error=error))
+ exit(1)
+except TypeError as error:
+ print("Template type error: {0}.".format(error.args[0]))
+ exit(1)
diff --git a/src/auditor/taler-helper-auditor-reserves.c b/src/auditor/taler-helper-auditor-reserves.c
index 331dfab77..2a1e990c0 100644
--- a/src/auditor/taler-helper-auditor-reserves.c
+++ b/src/auditor/taler-helper-auditor-reserves.c
@@ -75,24 +75,21 @@ static json_t *report_reserve_balance_insufficient_inconsistencies;
static json_t *report_purse_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.
+ * for positive deltas. Used only when internal checks are
+ * enabled.
*/
static struct TALER_Amount total_balance_summary_delta_plus;
/**
* Total delta between expected and stored reserve balance summaries,
- * for negative deltas.
+ * for negative deltas. Used only when internal checks are
+ * enabled.
*/
static struct TALER_Amount total_balance_summary_delta_minus;
@@ -123,29 +120,9 @@ static struct TALER_Amount total_arithmetic_delta_plus;
static struct TALER_Amount total_arithmetic_delta_minus;
/**
- * Expected balance in the escrow account.
- */
-static struct TALER_Amount total_escrow_balance;
-
-/**
- * Recoups we made on denominations that were not revoked (!?).
- */
-static struct TALER_Amount total_irregular_recoups;
-
-/**
- * Total withdraw fees earned.
- */
-static struct TALER_Amount total_withdraw_fee_income;
-
-/**
- * Total purse fees earned.
- */
-static struct TALER_Amount total_purse_fee_income;
-
-/**
- * Total history fees earned.
+ * Expected reserve balances.
*/
-static struct TALER_Amount total_history_fee_income;
+static struct TALER_AUDITORDB_ReserveFeeBalance balance;
/**
* Array of reports about coin operations with bad signatures.
@@ -220,8 +197,8 @@ report_amount_arithmetic_inconsistency (
if (0 != profitable)
{
target = (1 == profitable)
- ? &total_arithmetic_delta_plus
- : &total_arithmetic_delta_minus;
+ ? &total_arithmetic_delta_plus
+ : &total_arithmetic_delta_minus;
TALER_ARL_amount_add (target,
target,
&delta);
@@ -279,21 +256,15 @@ struct ReserveSummary
struct TALER_Amount total_out;
/**
- * Sum of withdraw fees encountered during this transaction.
+ * Sum of balance and fees encountered during this transaction.
*/
- struct TALER_Amount total_fee;
+ struct TALER_AUDITORDB_ReserveFeeBalance curr_balance;
/**
- * Previous balance of the reserve as remembered by the auditor.
+ * Previous balances of the reserve as remembered by the auditor.
* (updated based on @e total_in and @e total_out at the end).
*/
- struct TALER_Amount balance_at_previous_audit;
-
- /**
- * Previous withdraw fee balance of the reserve, as remembered by the auditor.
- * (updated based on @e total_fee at the end).
- */
- struct TALER_Amount a_withdraw_fee_balance;
+ struct TALER_AUDITORDB_ReserveFeeBalance prev_balance;
/**
* Previous reserve expiration data, as remembered by the auditor.
@@ -335,8 +306,7 @@ load_auditor_reserve_summary (struct ReserveSummary *rs)
&rs->reserve_pub,
&TALER_ARL_master_pub,
&rowid,
- &rs->balance_at_previous_audit,
- &rs->a_withdraw_fee_balance,
+ &rs->prev_balance,
&rs->a_expiration_date,
&rs->sender_account);
if (0 > qs)
@@ -349,31 +319,35 @@ load_auditor_reserve_summary (struct ReserveSummary *rs)
rs->had_ri = false;
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (rs->total_in.currency,
- &rs->balance_at_previous_audit));
+ &rs->prev_balance.reserve_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (rs->total_in.currency,
+ &rs->prev_balance.reserve_loss));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (rs->total_in.currency,
+ &rs->prev_balance.withdraw_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (rs->total_in.currency,
- &rs->a_withdraw_fee_balance));
+ &rs->prev_balance.close_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (rs->total_in.currency,
+ &rs->prev_balance.purse_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (rs->total_in.currency,
+ &rs->prev_balance.open_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (rs->total_in.currency,
+ &rs->prev_balance.history_fee_balance));
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Creating fresh reserve `%s' with starting balance %s\n",
- TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&rs->balance_at_previous_audit));
+ "Creating fresh reserve `%s'\n",
+ TALER_B2S (&rs->reserve_pub));
return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
}
rs->had_ri = true;
- if ( (GNUNET_YES !=
- TALER_amount_cmp_currency (&rs->balance_at_previous_audit,
- &rs->a_withdraw_fee_balance)) ||
- (GNUNET_YES !=
- TALER_amount_cmp_currency (&rs->total_in,
- &rs->balance_at_previous_audit)) )
- {
- GNUNET_break (0);
- return GNUNET_DB_STATUS_HARD_ERROR;
- }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Auditor remembers reserve `%s' has balance %s\n",
TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&rs->balance_at_previous_audit));
+ TALER_amount2s (&rs->prev_balance.reserve_balance));
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
@@ -436,7 +410,25 @@ setup_reserve (struct ReserveContext *rc,
&rs->total_out));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &rs->total_fee));
+ &rs->curr_balance.reserve_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.reserve_loss));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.withdraw_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.close_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.purse_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.open_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.history_fee_balance));
if (0 > (qs = load_auditor_reserve_summary (rs)))
{
GNUNET_free (rs);
@@ -481,7 +473,6 @@ handle_reserve_in (void *cls,
/* should be monotonically increasing */
GNUNET_assert (rowid >= ppr.last_reserve_in_serial_id);
ppr.last_reserve_in_serial_id = rowid + 1;
-
rs = setup_reserve (rc,
reserve_pub);
if (NULL == rs)
@@ -489,9 +480,6 @@ handle_reserve_in (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- TALER_ARL_amount_add (&rs->total_in,
- &rs->total_in,
- credit);
if (NULL == rs->sender_account)
rs->sender_account = GNUNET_strdup (sender_account_details);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -503,6 +491,9 @@ handle_reserve_in (void *cls,
idle_reserve_expiration_time));
rs->a_expiration_date = GNUNET_TIME_timestamp_max (rs->a_expiration_date,
expiry);
+ TALER_ARL_amount_add (&rs->total_in,
+ &rs->total_in,
+ credit);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
return GNUNET_OK;
@@ -618,7 +609,7 @@ handle_reserve_out (void *cls,
amount_with_fee);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
- return GNUNET_OK; /* exit function here, we cannot add this to the legitimate withdrawals */
+ return GNUNET_OK; /* exit function here, we cannot add this to the legitimate withdrawals */
}
TALER_ARL_amount_add (&auditor_amount_with_fee,
@@ -639,9 +630,6 @@ handle_reserve_out (void *cls,
GNUNET_break (0);
return GNUNET_SYSERR;
}
- TALER_ARL_amount_add (&rs->total_out,
- &rs->total_out,
- &auditor_amount_with_fee);
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Reserve `%s' reduced by %s from withdraw\n",
TALER_B2S (reserve_pub),
@@ -649,9 +637,15 @@ handle_reserve_out (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Increasing withdraw profits by fee %s\n",
TALER_amount2s (&issue->fees.withdraw));
- TALER_ARL_amount_add (&rs->total_fee,
- &rs->total_fee,
+ TALER_ARL_amount_add (&rs->curr_balance.withdraw_fee_balance,
+ &rs->curr_balance.withdraw_fee_balance,
&issue->fees.withdraw);
+ TALER_ARL_amount_add (&balance.withdraw_fee_balance,
+ &balance.withdraw_fee_balance,
+ &issue->fees.withdraw);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ &auditor_amount_with_fee);
if (TALER_ARL_do_abort ())
return GNUNET_SYSERR;
return GNUNET_OK;
@@ -741,8 +735,8 @@ handle_recoup_by_reserve (
report_row_inconsistency ("recoup",
rowid,
"denomination key not in revocation set");
- TALER_ARL_amount_add (&total_irregular_recoups,
- &total_irregular_recoups,
+ TALER_ARL_amount_add (&balance.reserve_loss,
+ &balance.reserve_loss,
amount);
}
else
@@ -770,10 +764,11 @@ handle_recoup_by_reserve (
}
else
{
- rev_rowid = 0; /* reported elsewhere */
+ rev_rowid = 0; /* reported elsewhere */
}
if ( (NULL != rev) &&
- (0 == strcmp (rev, "master signature invalid")) )
+ (0 == strcmp (rev,
+ "master signature invalid")) )
{
TALER_ARL_report (report_bad_sig_losses,
GNUNET_JSON_PACK (
@@ -868,6 +863,88 @@ get_closing_fee (const char *receiver_account,
/**
+ * Function called about reserve opening operations.
+ *
+ * @param cls closure
+ * @param rowid row identifier used to uniquely identify the reserve closing operation
+ * @param reserve_payment how much to pay from the
+ * reserve's own balance for opening the reserve
+ * @param request_timestamp when was the request created
+ * @param reserve_expiration desired expiration time for the reserve
+ * @param purse_limit minimum number of purses the client
+ * wants to have concurrently open for this reserve
+ * @param reserve_pub public key of the reserve
+ * @param reserve_sig signature affirming the operation
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_reserve_open (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_Amount *reserve_payment,
+ struct GNUNET_TIME_Timestamp request_timestamp,
+ struct GNUNET_TIME_Timestamp reserve_expiration,
+ uint32_t purse_limit,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_ReserveSignatureP *reserve_sig)
+{
+ struct ReserveContext *rc = cls;
+ struct ReserveSummary *rs;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_reserve_open_serial_id);
+ ppr.last_reserve_open_serial_id = rowid + 1;
+
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ if (GNUNET_OK !=
+ TALER_wallet_reserve_open_verify (reserve_payment,
+ request_timestamp,
+ reserve_expiration,
+ purse_limit,
+ reserve_pub,
+ reserve_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "reserve-open"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ reserve_payment),
+ GNUNET_JSON_pack_data_auto ("reserve_pub",
+ reserve_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ reserve_payment);
+ return GNUNET_OK;
+ }
+ TALER_ARL_amount_add (&rs->curr_balance.open_fee_balance,
+ &rs->curr_balance.open_fee_balance,
+ reserve_payment);
+ TALER_ARL_amount_add (&balance.open_fee_balance,
+ &balance.open_fee_balance,
+ reserve_payment);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ reserve_payment);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Additional open operation for reserve `%s' of %s\n",
+ TALER_B2S (reserve_pub),
+ TALER_amount2s (reserve_payment));
+ if (TALER_ARL_do_abort ())
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
+
+/**
* Function called about reserve closing operations
* the aggregator triggered.
*
@@ -890,7 +967,8 @@ handle_reserve_closed (
const struct TALER_Amount *closing_fee,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *receiver_account,
- const struct TALER_WireTransferIdentifierRawP *transfer_details)
+ const struct TALER_WireTransferIdentifierRawP *transfer_details,
+ uint64_t close_request_row)
{
struct ReserveContext *rc = cls;
struct ReserveSummary *rs;
@@ -910,12 +988,6 @@ handle_reserve_closed (
{
struct TALER_Amount expected_fee;
- TALER_ARL_amount_add (&rs->total_out,
- &rs->total_out,
- amount_with_fee);
- TALER_ARL_amount_add (&rs->total_fee,
- &rs->total_fee,
- closing_fee);
/* verify closing_fee is correct! */
if (GNUNET_OK !=
get_closing_fee (receiver_account,
@@ -935,20 +1007,117 @@ handle_reserve_closed (
1);
}
}
- if (NULL == rs->sender_account)
- {
- GNUNET_break (! rs->had_ri);
- report_row_inconsistency ("reserves_close",
- rowid,
- "target account not verified, auditor does not know reserve");
+
+ TALER_ARL_amount_add (&rs->curr_balance.close_fee_balance,
+ &rs->curr_balance.close_fee_balance,
+ closing_fee);
+ TALER_ARL_amount_add (&balance.close_fee_balance,
+ &balance.close_fee_balance,
+ closing_fee);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ amount_with_fee);
+ if (0 != close_request_row)
+ {
+ struct TALER_ReserveSignatureP reserve_sig;
+ struct GNUNET_TIME_Timestamp request_timestamp;
+ struct TALER_Amount close_balance;
+ struct TALER_Amount close_fee;
+ char *payto_uri;
+ enum GNUNET_DB_QueryStatus qs;
+
+ qs = TALER_ARL_edb->select_reserve_close_request_info (
+ TALER_ARL_edb->cls,
+ reserve_pub,
+ close_request_row,
+ &reserve_sig,
+ &request_timestamp,
+ &close_balance,
+ &close_fee,
+ &payto_uri);
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
+ {
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "reserve close request unknown");
+ }
+ else
+ {
+ struct TALER_PaytoHashP h_payto;
+
+ TALER_payto_hash (payto_uri,
+ &h_payto);
+ if (GNUNET_OK !=
+ TALER_wallet_reserve_close_verify (
+ request_timestamp,
+ &h_payto,
+ reserve_pub,
+ &reserve_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "close-request"),
+ GNUNET_JSON_pack_uint64 ("row",
+ close_request_row),
+ TALER_JSON_pack_amount ("loss",
+ amount_with_fee),
+ GNUNET_JSON_pack_data_auto ("reserve_pub",
+ reserve_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ amount_with_fee);
+ }
+ }
+ if ( (NULL == payto_uri) &&
+ (NULL == rs->sender_account) )
+ {
+ GNUNET_break (! rs->had_ri);
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "target account not verified, auditor does not know reserve");
+ }
+ if (NULL == payto_uri)
+ {
+ if (0 != strcmp (rs->sender_account,
+ receiver_account))
+ {
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "target account does not match origin account");
+ }
+ }
+ else
+ {
+ if (0 != strcmp (payto_uri,
+ receiver_account))
+ {
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "target account does not match origin account");
+ }
+ }
+ GNUNET_free (payto_uri);
}
- else if (0 != strcmp (rs->sender_account,
- receiver_account))
+ else
{
- report_row_inconsistency ("reserves_close",
- rowid,
- "target account does not match origin account");
+ if (NULL == rs->sender_account)
+ {
+ GNUNET_break (! rs->had_ri);
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "target account not verified, auditor does not know reserve");
+ }
+ if (0 != strcmp (rs->sender_account,
+ receiver_account))
+ {
+ report_row_inconsistency ("reserves_close",
+ rowid,
+ "target account does not match origin account");
+ }
}
+
+ // FIXME: support/check for reserve close requests here!
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Additional closing operation for reserve `%s' of %s\n",
TALER_B2S (reserve_pub),
@@ -960,6 +1129,203 @@ handle_reserve_closed (
/**
+ * Function called with details about account merge requests that have been
+ * made, with the goal of accounting for the merge fee paid by the reserve (if
+ * applicable).
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param reserve_pub reserve affected by the merge
+ * @param purse_pub purse being merged
+ * @param h_contract_terms hash over contract of the purse
+ * @param purse_expiration when would the purse expire
+ * @param amount total amount in the purse
+ * @param min_age minimum age of all coins deposited into the purse
+ * @param flags how was the purse created
+ * @param purse_fee if a purse fee was paid, how high is it
+ * @param merge_timestamp when was the merge approved
+ * @param reserve_sig signature by reserve approving the merge
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_account_merged (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_PrivateContractHashP *h_contract_terms,
+ struct GNUNET_TIME_Timestamp purse_expiration,
+ const struct TALER_Amount *amount,
+ uint32_t min_age,
+ enum TALER_WalletAccountMergeFlags flags,
+ const struct TALER_Amount *purse_fee,
+ struct GNUNET_TIME_Timestamp merge_timestamp,
+ const struct TALER_ReserveSignatureP *reserve_sig)
+{
+ struct ReserveContext *rc = cls;
+ struct ReserveSummary *rs;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_account_merges_serial_id);
+ ppr.last_account_merges_serial_id = rowid + 1;
+ if (GNUNET_OK !=
+ TALER_wallet_account_merge_verify (merge_timestamp,
+ purse_pub,
+ purse_expiration,
+ h_contract_terms,
+ amount,
+ purse_fee,
+ min_age,
+ flags,
+ reserve_pub,
+ reserve_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "account-merge"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ purse_fee),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ reserve_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ purse_fee);
+ return GNUNET_OK;
+ }
+ if ( (flags & TALER_WAMF_MERGE_MODE_MASK) !=
+ TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE)
+ return GNUNET_OK; /* no impact on reserve balance */
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ TALER_ARL_amount_add (&balance.purse_fee_balance,
+ &balance.purse_fee_balance,
+ purse_fee);
+ TALER_ARL_amount_add (&rs->curr_balance.purse_fee_balance,
+ &rs->curr_balance.purse_fee_balance,
+ purse_fee);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ purse_fee);
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about a purse that was merged into an account.
+ * Only updates the reserve balance, the actual verifications are done in the
+ * purse helper.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the refund in our DB
+ * @param purse_pub public key of the purse
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+purse_decision_cb (void *cls,
+ uint64_t rowid,
+ const struct TALER_PurseContractPublicKeyP *purse_pub,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_Amount *purse_value)
+{
+ struct ReserveContext *rc = cls;
+ struct ReserveSummary *rs;
+
+ GNUNET_assert (rowid >= ppr.last_purse_decisions_serial_id); /* should be monotonically increasing */
+ ppr.last_purse_decisions_serial_id = rowid + 1;
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ TALER_ARL_amount_add (&rs->total_in,
+ &rs->total_in,
+ purse_value);
+ if (TALER_ARL_do_abort ())
+ return GNUNET_SYSERR;
+ return GNUNET_OK;
+}
+
+
+/**
+ * Function called with details about
+ * history requests that have been made, with
+ * the goal of auditing the history request execution.
+ *
+ * @param cls closure
+ * @param rowid unique serial ID for the deposit in our DB
+ * @param history_fee fee paid for the request
+ * @param ts timestamp of the request
+ * @param reserve_pub reserve history was requested for
+ * @param reserve_sig signature approving the @a history_fee
+ * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
+ */
+static enum GNUNET_GenericReturnValue
+handle_history_request (
+ void *cls,
+ uint64_t rowid,
+ const struct TALER_Amount *history_fee,
+ const struct GNUNET_TIME_Timestamp ts,
+ const struct TALER_ReservePublicKeyP *reserve_pub,
+ const struct TALER_ReserveSignatureP *reserve_sig)
+{
+ struct ReserveContext *rc = cls;
+ struct ReserveSummary *rs;
+
+ /* should be monotonically increasing */
+ GNUNET_assert (rowid >= ppr.last_history_requests_serial_id);
+ ppr.last_history_requests_serial_id = rowid + 1;
+ if (GNUNET_OK !=
+ TALER_wallet_reserve_history_verify (ts,
+ history_fee,
+ reserve_pub,
+ reserve_sig))
+ {
+ TALER_ARL_report (report_bad_sig_losses,
+ GNUNET_JSON_PACK (
+ GNUNET_JSON_pack_string ("operation",
+ "account-history"),
+ GNUNET_JSON_pack_uint64 ("row",
+ rowid),
+ TALER_JSON_pack_amount ("loss",
+ history_fee),
+ GNUNET_JSON_pack_data_auto ("key_pub",
+ reserve_pub)));
+ TALER_ARL_amount_add (&total_bad_sig_loss,
+ &total_bad_sig_loss,
+ history_fee);
+ return GNUNET_OK;
+ }
+ rs = setup_reserve (rc,
+ reserve_pub);
+ if (NULL == rs)
+ {
+ GNUNET_break (0);
+ return GNUNET_SYSERR;
+ }
+ TALER_ARL_amount_add (&balance.history_fee_balance,
+ &balance.history_fee_balance,
+ history_fee);
+ TALER_ARL_amount_add (&rs->curr_balance.history_fee_balance,
+ &rs->curr_balance.history_fee_balance,
+ history_fee);
+ TALER_ARL_amount_add (&rs->total_out,
+ &rs->total_out,
+ history_fee);
+ return GNUNET_OK;
+}
+
+
+/**
* Check that the reserve summary matches what the exchange database
* thinks about the reserve, and update our own state of the reserve.
*
@@ -977,29 +1343,32 @@ verify_reserve_balance (void *cls,
{
struct ReserveContext *rc = cls;
struct ReserveSummary *rs = value;
- struct TALER_Amount balance;
+ struct TALER_Amount mbalance;
struct TALER_Amount nbalance;
enum GNUNET_DB_QueryStatus qs;
- int ret;
+ enum GNUNET_GenericReturnValue ret;
ret = GNUNET_OK;
/* Check our reserve summary balance calculation shows that
the reserve balance is acceptable (i.e. non-negative) */
- TALER_ARL_amount_add (&balance,
+ TALER_ARL_amount_add (&mbalance,
&rs->total_in,
- &rs->balance_at_previous_audit);
+ &rs->prev_balance.reserve_balance);
if (TALER_ARL_SR_INVALID_NEGATIVE ==
TALER_ARL_amount_subtract_neg (&nbalance,
- &balance,
+ &mbalance,
&rs->total_out))
{
struct TALER_Amount loss;
TALER_ARL_amount_subtract (&loss,
&rs->total_out,
- &balance);
- TALER_ARL_amount_add (&total_balance_insufficient_loss,
- &total_balance_insufficient_loss,
+ &mbalance);
+ TALER_ARL_amount_add (&rs->curr_balance.reserve_loss,
+ &rs->prev_balance.reserve_loss,
+ &loss);
+ TALER_ARL_amount_add (&balance.reserve_loss,
+ &balance.reserve_loss,
&loss);
TALER_ARL_report (report_reserve_balance_insufficient_inconsistencies,
GNUNET_JSON_PACK (
@@ -1009,8 +1378,13 @@ verify_reserve_balance (void *cls,
&loss)));
/* Continue with a reserve balance of zero */
GNUNET_assert (GNUNET_OK ==
- TALER_amount_set_zero (balance.currency,
- &nbalance));
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &rs->curr_balance.reserve_balance));
+ }
+ else
+ {
+ /* Update remaining reserve balance! */
+ rs->curr_balance.reserve_balance = nbalance;
}
if (internal_checks)
@@ -1048,17 +1422,17 @@ verify_reserve_balance (void *cls,
else
{
/* Check that exchange's balance matches our expected balance for the reserve */
- if (0 != TALER_amount_cmp (&nbalance,
+ if (0 != TALER_amount_cmp (&rs->curr_balance.reserve_balance,
&reserve.balance))
{
struct TALER_Amount delta;
- if (0 < TALER_amount_cmp (&nbalance,
+ if (0 < TALER_amount_cmp (&rs->curr_balance.reserve_balance,
&reserve.balance))
{
/* balance > reserve.balance */
TALER_ARL_amount_subtract (&delta,
- &nbalance,
+ &rs->curr_balance.reserve_balance,
&reserve.balance);
TALER_ARL_amount_add (&total_balance_summary_delta_plus,
&total_balance_summary_delta_plus,
@@ -1069,7 +1443,7 @@ verify_reserve_balance (void *cls,
/* balance < reserve.balance */
TALER_ARL_amount_subtract (&delta,
&reserve.balance,
- &nbalance);
+ &rs->curr_balance.reserve_balance);
TALER_ARL_amount_add (&total_balance_summary_delta_minus,
&total_balance_summary_delta_minus,
&delta);
@@ -1081,10 +1455,11 @@ verify_reserve_balance (void *cls,
TALER_JSON_pack_amount ("exchange",
&reserve.balance),
TALER_JSON_pack_amount ("auditor",
- &nbalance)));
+ &rs->curr_balance.
+ reserve_balance)));
}
}
- } /* end of 'if (internal_checks)' */
+ } /* end of 'if (internal_checks)' */
/* Check that reserve is being closed if it is past its expiration date
(and the closing fee would not exceed the remaining balance) */
@@ -1141,26 +1516,42 @@ verify_reserve_balance (void *cls,
}
}
- /* Add withdraw fees we encountered to totals */
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Reserve reserve `%s' made %s in withdraw fees\n",
- TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&rs->total_fee));
- TALER_ARL_amount_add (&rs->a_withdraw_fee_balance,
- &rs->a_withdraw_fee_balance,
- &rs->total_fee);
- TALER_ARL_amount_add (&total_escrow_balance,
- &total_escrow_balance,
+ /* We already computed the 'new' balance in 'curr_balance'
+ to include the previous balance, so this one is just
+ an assignment, not adding up! */
+ rs->prev_balance.reserve_balance = rs->curr_balance.reserve_balance;
+
+ /* Add up new totals to previous totals */
+ TALER_ARL_amount_add (&rs->prev_balance.reserve_loss,
+ &rs->prev_balance.reserve_loss,
+ &rs->curr_balance.reserve_loss);
+ TALER_ARL_amount_add (&rs->prev_balance.withdraw_fee_balance,
+ &rs->prev_balance.withdraw_fee_balance,
+ &rs->curr_balance.withdraw_fee_balance);
+ TALER_ARL_amount_add (&rs->prev_balance.close_fee_balance,
+ &rs->prev_balance.close_fee_balance,
+ &rs->curr_balance.close_fee_balance);
+ TALER_ARL_amount_add (&rs->prev_balance.purse_fee_balance,
+ &rs->prev_balance.purse_fee_balance,
+ &rs->curr_balance.purse_fee_balance);
+ TALER_ARL_amount_add (&rs->prev_balance.open_fee_balance,
+ &rs->prev_balance.open_fee_balance,
+ &rs->curr_balance.open_fee_balance);
+ TALER_ARL_amount_add (&rs->prev_balance.history_fee_balance,
+ &rs->prev_balance.history_fee_balance,
+ &rs->curr_balance.history_fee_balance);
+
+ /* Update global balance: add incoming first, then try
+ to subtract outgoing... */
+ TALER_ARL_amount_add (&balance.reserve_balance,
+ &balance.reserve_balance,
&rs->total_in);
- TALER_ARL_amount_add (&total_withdraw_fee_income,
- &total_withdraw_fee_income,
- &rs->total_fee);
{
struct TALER_Amount r;
if (TALER_ARL_SR_INVALID_NEGATIVE ==
TALER_ARL_amount_subtract_neg (&r,
- &total_escrow_balance,
+ &balance.reserve_balance,
&rs->total_out))
{
/* We could not reduce our total balance, i.e. exchange allowed IN TOTAL (!)
@@ -1168,31 +1559,29 @@ verify_reserve_balance (void *cls,
went negative!). Woopsie. Calculate how badly it went and log. */
report_amount_arithmetic_inconsistency ("global escrow balance",
0,
- &total_escrow_balance, /* what we had */
- &rs->total_out, /* what we needed */
+ &balance.reserve_balance, /* what we had */
+ &rs->total_out, /* what we needed */
0 /* specific profit/loss does not apply to the total summary */);
/* We unexpectedly went negative, so a sane value to continue from
would be zero. */
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_escrow_balance));
+ &balance.reserve_balance));
}
else
{
- total_escrow_balance = r;
+ balance.reserve_balance = r;
}
}
- if ( (0ULL == balance.value) &&
- (0U == balance.fraction) )
+ if (TALER_amount_is_zero (&rs->prev_balance.reserve_balance))
{
/* balance is zero, drop reserve details (and then do not update/insert) */
if (rs->had_ri)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Final balance of reserve `%s' is %s, dropping it\n",
- TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&nbalance));
+ "Final balance of reserve `%s' is zero, dropping it\n",
+ TALER_B2S (&rs->reserve_pub));
qs = TALER_ARL_adb->del_reserve_info (TALER_ARL_adb->cls,
&rs->reserve_pub,
&TALER_ARL_master_pub);
@@ -1206,9 +1595,8 @@ verify_reserve_balance (void *cls,
else
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Final balance of reserve `%s' is %s, no need to remember it\n",
- TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&nbalance));
+ "Final balance of reserve `%s' is zero, no need to remember it\n",
+ TALER_B2S (&rs->reserve_pub));
}
}
else
@@ -1217,20 +1605,18 @@ verify_reserve_balance (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Remembering final balance of reserve `%s' as %s\n",
TALER_B2S (&rs->reserve_pub),
- TALER_amount2s (&nbalance));
+ TALER_amount2s (&rs->prev_balance.reserve_balance));
if (rs->had_ri)
qs = TALER_ARL_adb->update_reserve_info (TALER_ARL_adb->cls,
&rs->reserve_pub,
&TALER_ARL_master_pub,
- &nbalance,
- &rs->a_withdraw_fee_balance,
+ &rs->prev_balance,
rs->a_expiration_date);
else
qs = TALER_ARL_adb->insert_reserve_info (TALER_ARL_adb->cls,
&rs->reserve_pub,
&TALER_ARL_master_pub,
- &nbalance,
- &rs->a_withdraw_fee_balance,
+ &rs->prev_balance,
rs->a_expiration_date,
rs->sender_account);
if (0 >= qs)
@@ -1240,7 +1626,7 @@ verify_reserve_balance (void *cls,
rc->qs = qs;
}
}
-
+ /* now we can discard the cached entry */
GNUNET_assert (GNUNET_YES ==
GNUNET_CONTAINER_multihashmap_remove (rc->reserves,
key,
@@ -1252,426 +1638,6 @@ verify_reserve_balance (void *cls,
/**
- * Function called with details about purse deposits that have been made, with
- * the goal of auditing the deposit's execution.
- *
- * @param cls closure
- * @param rowid unique serial ID for the deposit in our DB
- * @param deposit deposit details
- * @param reserve_pub which reserve is the purse merged into, NULL if unknown
- * @param flags purse flags
- * @param auditor_balance purse balance (according to the
- * auditor during auditing)
- * @param purse_total target amount the purse should reach
- * @param denom_pub denomination public key of @a coin_pub
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static enum GNUNET_GenericReturnValue
-handle_purse_deposits (
- void *cls,
- uint64_t rowid,
- const struct TALER_EXCHANGEDB_PurseDeposit *deposit,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- enum TALER_WalletAccountMergeFlags flags,
- const struct TALER_Amount *auditor_balance,
- const struct TALER_Amount *purse_total,
- const struct TALER_DenominationPublicKey *denom_pub)
-{
- struct ReserveContext *rc = cls;
- const char *base_url
- = (NULL == deposit->exchange_base_url)
- ? TALER_ARL_exchange_url
- : deposit->exchange_base_url;
- enum GNUNET_DB_QueryStatus qs;
- struct TALER_Amount amount_minus_fee;
- struct TALER_Amount new_balance;
- struct ReserveSummary *rs;
- struct TALER_DenominationHashP h_denom_pub;
-
- /* should be monotonically increasing */
- GNUNET_assert (rowid >= ppr.last_purse_deposits_serial_id);
- ppr.last_purse_deposits_serial_id = rowid + 1;
-
- {
- const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue;
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TALER_ARL_get_denomination_info (denom_pub,
- &issue,
- &h_denom_pub);
- if (0 > qs)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- if (GNUNET_DB_STATUS_HARD_ERROR == qs)
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "Hard database error trying to get denomination %s from database!\n",
- TALER_B2S (denom_pub));
- rc->qs = qs;
- return GNUNET_SYSERR;
- }
- if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
- {
- report_row_inconsistency ("purse-deposit",
- rowid,
- "denomination key not found");
- if (TALER_ARL_do_abort ())
- return GNUNET_SYSERR;
- return GNUNET_OK;
- }
- TALER_ARL_amount_subtract (&amount_minus_fee,
- &deposit->amount,
- &issue->fees.deposit);
- }
-
- if (GNUNET_OK !=
- TALER_wallet_purse_deposit_verify (base_url,
- &deposit->purse_pub,
- &deposit->amount,
- &h_denom_pub,
- &deposit->h_age_commitment,
- &deposit->coin_pub,
- &deposit->coin_sig))
- {
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "purse-deposit"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- &deposit->amount),
- GNUNET_JSON_pack_data_auto ("key_pub",
- &deposit->coin_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- &deposit->amount);
- return GNUNET_OK;
- }
-
- TALER_ARL_amount_add (&new_balance,
- auditor_balance,
- &amount_minus_fee);
- qs = TALER_ARL_edb->set_purse_balance (TALER_ARL_edb->cls,
- &deposit->purse_pub,
- &new_balance);
- GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != qs);
- if (qs < 0)
- {
- GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
- GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs);
- rc->qs = qs;
- return GNUNET_SYSERR;
- }
- if (TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE !=
- (flags & TALER_WAMF_MERGE_MODE_MASK))
- {
- /* This just created the purse, actual credit to
- the reserve will be done in handle_account_merged() */
- return GNUNET_OK;
- }
- if ( (NULL != deposit->exchange_base_url) &&
- (0 != strcmp (deposit->exchange_base_url,
- TALER_ARL_exchange_url)) )
- {
- /* credited reserve is at another exchange, do NOT credit here! */
- return GNUNET_OK;
- }
-
- rs = setup_reserve (rc,
- reserve_pub);
- if (NULL == rs)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if ( (-1 != TALER_amount_cmp (&new_balance,
- purse_total)) &&
- (-1 == TALER_amount_cmp (auditor_balance,
- purse_total)) )
- {
- /* new balance at or above purse_total
- (and previous balance was below); thus
- credit reserve with purse value! */
- TALER_ARL_amount_add (&rs->total_in,
- &rs->total_in,
- purse_total);
- }
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with details about purse
- * merges that have been made, with
- * the goal of auditing the purse merge execution.
- *
- * @param cls closure
- * @param rowid unique serial ID for the deposit in our DB
- * @param partner_base_url where is the reserve, NULL for this exchange
- * @param amount total amount expected in the purse
- * @param balance current balance in the purse (according to the auditor)
- * @param flags purse flags
- * @param merge_pub merge capability key
- * @param reserve_pub reserve the merge affects
- * @param merge_sig signature affirming the merge
- * @param purse_pub purse key
- * @param merge_timestamp when did the merge happen
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static enum GNUNET_GenericReturnValue
-handle_purse_merged (
- void *cls,
- uint64_t rowid,
- const char *partner_base_url,
- const struct TALER_Amount *amount,
- const struct TALER_Amount *balance,
- enum TALER_WalletAccountMergeFlags flags,
- const struct TALER_PurseMergePublicKeyP *merge_pub,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_PurseMergeSignatureP *merge_sig,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- struct GNUNET_TIME_Timestamp merge_timestamp)
-{
- struct ReserveContext *rc = cls;
- struct ReserveSummary *rs;
- char *reserve_url;
-
- /* should be monotonically increasing */
- GNUNET_assert (rowid >= ppr.last_purse_merges_serial_id);
- ppr.last_purse_merges_serial_id = rowid + 1;
- reserve_url
- = TALER_reserve_make_payto (NULL == partner_base_url
- ? TALER_ARL_exchange_url
- : partner_base_url,
- reserve_pub);
- if (GNUNET_OK !=
- TALER_wallet_purse_merge_verify (reserve_url,
- merge_timestamp,
- purse_pub,
- merge_pub,
- merge_sig))
- {
- GNUNET_free (reserve_url);
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "merge-purse"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- amount),
- GNUNET_JSON_pack_data_auto ("key_pub",
- merge_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- amount);
- return GNUNET_OK;
- }
- GNUNET_free (reserve_url);
- if (TALER_WAMF_MODE_CREATE_WITH_PURSE_FEE ==
- (flags & TALER_WAMF_MERGE_MODE_MASK))
- {
- /* This just created the purse, actual credit to
- the reserve will be done in handle_purse_deposits() */
- return GNUNET_OK;
- }
- if ( (NULL != partner_base_url) &&
- (0 != strcmp (partner_base_url,
- TALER_ARL_exchange_url)) )
- {
- /* credited reserve is at another exchange, do NOT credit here! */
- return GNUNET_OK;
- }
- rs = setup_reserve (rc,
- reserve_pub);
- if (NULL == rs)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- if (-1 == TALER_amount_cmp (balance,
- amount))
- {
- struct TALER_Amount loss;
-
- TALER_ARL_amount_subtract (&loss,
- amount,
- balance);
- /* illegal merge, balance is still below total purse value */
- TALER_ARL_report (report_purse_balance_insufficient_inconsistencies,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "merge-purse"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- &loss),
- GNUNET_JSON_pack_data_auto ("purse_pub",
- purse_pub)));
- TALER_ARL_amount_add (&total_balance_insufficient_loss,
- &total_balance_insufficient_loss,
- &loss);
- return GNUNET_OK;
- }
- TALER_ARL_amount_add (&rs->total_in,
- &rs->total_in,
- amount);
- // rs->a_expiration_date = FIXME: do we care? If so, set to what (so that the auditor no longer complains about the reserve not being closed)
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with details about
- * account merge requests that have been made, with
- * the goal of auditing the account merge execution.
- *
- * @param cls closure
- * @param rowid unique serial ID for the deposit in our DB
- * @param reserve_pub reserve affected by the merge
- * @param purse_pub purse being merged
- * @param h_contract_terms hash over contract of the purse
- * @param purse_expiration when would the purse expire
- * @param amount total amount in the purse
- * @param min_age minimum age of all coins deposited into the purse
- * @param flags how was the purse created
- * @param purse_fee if a purse fee was paid, how high is it
- * @param merge_timestamp when was the merge approved
- * @param reserve_sig signature by reserve approving the merge
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static enum GNUNET_GenericReturnValue
-handle_account_merged (
- void *cls,
- uint64_t rowid,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_PurseContractPublicKeyP *purse_pub,
- const struct TALER_PrivateContractHashP *h_contract_terms,
- struct GNUNET_TIME_Timestamp purse_expiration,
- const struct TALER_Amount *amount,
- uint32_t min_age,
- enum TALER_WalletAccountMergeFlags flags,
- const struct TALER_Amount *purse_fee,
- struct GNUNET_TIME_Timestamp merge_timestamp,
- const struct TALER_ReserveSignatureP *reserve_sig)
-{
- struct ReserveContext *rc = cls;
- struct ReserveSummary *rs;
-
- /* should be monotonically increasing */
- GNUNET_assert (rowid >= ppr.last_account_merges_serial_id);
- ppr.last_account_merges_serial_id = rowid + 1;
- if (GNUNET_OK !=
- TALER_wallet_account_merge_verify (merge_timestamp,
- purse_pub,
- purse_expiration,
- h_contract_terms,
- amount,
- purse_fee,
- min_age,
- flags,
- reserve_pub,
- reserve_sig))
- {
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "account-merge"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- purse_fee),
- GNUNET_JSON_pack_data_auto ("key_pub",
- reserve_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- purse_fee);
- return GNUNET_OK;
- }
- rs = setup_reserve (rc,
- reserve_pub);
- if (NULL == rs)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- TALER_ARL_amount_add (&total_purse_fee_income,
- &total_purse_fee_income,
- purse_fee);
- TALER_ARL_amount_add (&rs->total_out,
- &rs->total_out,
- purse_fee);
- return GNUNET_OK;
-}
-
-
-/**
- * Function called with details about
- * history requests that have been made, with
- * the goal of auditing the history request execution.
- *
- * @param cls closure
- * @param rowid unique serial ID for the deposit in our DB
- * @param history_fee fee paid for the request
- * @param ts timestamp of the request
- * @param reserve_pub reserve history was requested for
- * @param reserve_sig signature approving the @a history_fee
- * @return #GNUNET_OK to continue to iterate, #GNUNET_SYSERR to stop
- */
-static enum GNUNET_GenericReturnValue
-handle_history_request (
- void *cls,
- uint64_t rowid,
- const struct TALER_Amount *history_fee,
- const struct GNUNET_TIME_Timestamp ts,
- const struct TALER_ReservePublicKeyP *reserve_pub,
- const struct TALER_ReserveSignatureP *reserve_sig)
-{
- struct ReserveContext *rc = cls;
- struct ReserveSummary *rs;
-
- /* should be monotonically increasing */
- GNUNET_assert (rowid >= ppr.last_history_requests_serial_id);
- ppr.last_history_requests_serial_id = rowid + 1;
- if (GNUNET_OK !=
- TALER_wallet_reserve_history_verify (ts,
- history_fee,
- reserve_pub,
- reserve_sig))
- {
- TALER_ARL_report (report_bad_sig_losses,
- GNUNET_JSON_PACK (
- GNUNET_JSON_pack_string ("operation",
- "account-history"),
- GNUNET_JSON_pack_uint64 ("row",
- rowid),
- TALER_JSON_pack_amount ("loss",
- history_fee),
- GNUNET_JSON_pack_data_auto ("key_pub",
- reserve_pub)));
- TALER_ARL_amount_add (&total_bad_sig_loss,
- &total_bad_sig_loss,
- history_fee);
- return GNUNET_OK;
- }
- rs = setup_reserve (rc,
- reserve_pub);
- if (NULL == rs)
- {
- GNUNET_break (0);
- return GNUNET_SYSERR;
- }
- TALER_ARL_amount_add (&total_history_fee_income,
- &total_history_fee_income,
- history_fee);
- TALER_ARL_amount_add (&rs->total_out,
- &rs->total_out,
- history_fee);
- return GNUNET_OK;
-}
-
-
-/**
* Analyze reserves for being well-formed.
*
* @param cls NULL
@@ -1705,24 +1671,20 @@ analyze_reserves (void *cls)
{
ppr_start = ppr;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Resuming reserve audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
+ "Resuming reserve audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
(unsigned long long) ppr.last_reserve_in_serial_id,
(unsigned long long) ppr.last_reserve_out_serial_id,
(unsigned long long) ppr.last_reserve_recoup_serial_id,
+ (unsigned long long) ppr.last_reserve_open_serial_id,
(unsigned long long) ppr.last_reserve_close_serial_id,
- (unsigned long long) ppr.last_purse_merges_serial_id,
- (unsigned long long) ppr.last_purse_deposits_serial_id,
+ (unsigned long long) ppr.last_purse_decisions_serial_id,
(unsigned long long) ppr.last_account_merges_serial_id,
- (unsigned long long) ppr.last_history_requests_serial_id,
- (unsigned long long) ppr.last_close_requests_serial_id);
+ (unsigned long long) ppr.last_history_requests_serial_id);
}
rc.qs = GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
qsx = TALER_ARL_adb->get_reserve_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_withdraw_fee_income,
- &total_purse_fee_income,
- &total_history_fee_income);
+ &balance);
if (qsx < 0)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
@@ -1732,7 +1694,6 @@ analyze_reserves (void *cls)
GNUNET_NO);
rc.revoked = GNUNET_CONTAINER_multihashmap_create (4,
GNUNET_NO);
-
qs = TALER_ARL_edb->select_reserves_in_above_serial_id (
TALER_ARL_edb->cls,
ppr.last_reserve_in_serial_id,
@@ -1763,42 +1724,45 @@ analyze_reserves (void *cls)
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
- qs = TALER_ARL_edb->select_reserve_closed_above_serial_id (
+ qs = TALER_ARL_edb->select_reserve_open_above_serial_id (
TALER_ARL_edb->cls,
- ppr.last_reserve_close_serial_id,
- &handle_reserve_closed,
+ ppr.last_reserve_open_serial_id,
+ &handle_reserve_open,
&rc);
if (qs < 0)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
- qs = TALER_ARL_edb->select_purse_deposits_above_serial_id (
+ qs = TALER_ARL_edb->select_reserve_closed_above_serial_id (
TALER_ARL_edb->cls,
- ppr.last_purse_deposits_serial_id,
- &handle_purse_deposits,
+ ppr.last_reserve_close_serial_id,
+ &handle_reserve_closed,
&rc);
if (qs < 0)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
- /* Charge purse fee! */
- qs = TALER_ARL_edb->select_account_merges_above_serial_id (
- TALER_ARL_edb->cls,
- ppr.last_account_merges_serial_id,
- &handle_account_merged,
- &rc);
- if (qs < 0)
+ /* process purse_decisions (to credit reserve) */
+ if (0 >
+ (qs = TALER_ARL_edb->select_purse_decisions_above_serial_id (
+ TALER_ARL_edb->cls,
+ ppr.last_purse_decisions_serial_id,
+ false, /* only go for merged purses! */
+ &purse_decision_cb,
+ &rc)))
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
return qs;
}
- /* Credit purse value (if last op)! */
- qs = TALER_ARL_edb->select_purse_merges_above_serial_id (
+ if (0 > rc.qs)
+ return rc.qs;
+ /* Charge purse fee! */
+ qs = TALER_ARL_edb->select_account_merges_above_serial_id (
TALER_ARL_edb->cls,
- ppr.last_purse_merges_serial_id,
- &handle_purse_merged,
+ ppr.last_account_merges_serial_id,
+ &handle_account_merged,
&rc);
if (qs < 0)
{
@@ -1817,7 +1781,7 @@ analyze_reserves (void *cls)
return qs;
}
#if 0
- /* FIXME #7269 (support for explicit reserve closure request) */
+ /* FIXME #7269 (support for explicit reserve closure request) -- needed??? */
qs = TALER_ARL_edb->select_close_requests_above_serial_id (
TALER_ARL_edb->cls,
ppr.last_close_requests_serial_id,
@@ -1836,27 +1800,19 @@ analyze_reserves (void *cls)
GNUNET_CONTAINER_multihashmap_size (rc.reserves));
GNUNET_CONTAINER_multihashmap_destroy (rc.reserves);
GNUNET_CONTAINER_multihashmap_destroy (rc.revoked);
-
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != rc.qs)
return qs;
-
if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx)
{
qs = TALER_ARL_adb->insert_reserve_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_withdraw_fee_income,
- &total_purse_fee_income,
- &total_history_fee_income);
+ &balance);
}
else
{
qs = TALER_ARL_adb->update_reserve_summary (TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
- &total_escrow_balance,
- &total_withdraw_fee_income,
- &total_purse_fee_income,
- &total_history_fee_income);
+ &balance);
}
if (0 >= qs)
{
@@ -1879,16 +1835,15 @@ analyze_reserves (void *cls)
return qs;
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Concluded reserve audit step at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
+ "Concluded reserve audit step at %llu/%llu/%llu/%llu/%llu/%llu/%llu/%llu\n",
(unsigned long long) ppr.last_reserve_in_serial_id,
(unsigned long long) ppr.last_reserve_out_serial_id,
(unsigned long long) ppr.last_reserve_recoup_serial_id,
+ (unsigned long long) ppr.last_reserve_open_serial_id,
(unsigned long long) ppr.last_reserve_close_serial_id,
- (unsigned long long) ppr.last_purse_merges_serial_id,
- (unsigned long long) ppr.last_purse_deposits_serial_id,
+ (unsigned long long) ppr.last_purse_decisions_serial_id,
(unsigned long long) ppr.last_account_merges_serial_id,
- (unsigned long long) ppr.last_history_requests_serial_id,
- (unsigned long long) ppr.last_close_requests_serial_id);
+ (unsigned long long) ppr.last_history_requests_serial_id);
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
}
@@ -1934,22 +1889,26 @@ run (void *cls,
"Starting audit\n");
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_escrow_balance));
+ &balance.reserve_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_irregular_recoups));
+ &balance.reserve_loss));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_withdraw_fee_income));
+ &balance.withdraw_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_history_fee_income));
+ &balance.close_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_purse_fee_income));
+ &balance.purse_fee_balance));
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
- &total_balance_insufficient_loss));
+ &balance.open_fee_balance));
+ GNUNET_assert (GNUNET_OK ==
+ TALER_amount_set_zero (TALER_ARL_currency,
+ &balance.history_fee_balance));
+ // REVIEW:
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
&total_balance_summary_delta_plus));
@@ -1968,6 +1927,7 @@ run (void *cls,
GNUNET_assert (GNUNET_OK ==
TALER_amount_set_zero (TALER_ARL_currency,
&total_bad_sig_loss));
+
GNUNET_assert (NULL !=
(report_row_inconsistencies = json_array ()));
GNUNET_assert (NULL !=
@@ -1999,15 +1959,6 @@ run (void *cls,
}
TALER_ARL_done (
GNUNET_JSON_PACK (
- GNUNET_JSON_pack_array_steal (
- "reserve_balance_insufficient_inconsistencies",
- report_reserve_balance_insufficient_inconsistencies),
- GNUNET_JSON_pack_array_steal (
- "purse_balance_insufficient_inconsistencies",
- report_purse_balance_insufficient_inconsistencies),
- /* Tested in test-auditor.sh #3 */
- TALER_JSON_pack_amount ("total_loss_balance_insufficient",
- &total_balance_insufficient_loss),
/* Tested in test-auditor.sh #3 */
GNUNET_JSON_pack_array_steal (
"reserve_balance_summary_wrong_inconsistencies",
@@ -2016,26 +1967,47 @@ run (void *cls,
&total_balance_summary_delta_plus),
TALER_JSON_pack_amount ("total_balance_summary_delta_minus",
&total_balance_summary_delta_minus),
+ /* Tested in test-auditor.sh #21 */
+ TALER_JSON_pack_amount ("total_balance_reserve_not_closed",
+ &total_balance_reserve_not_closed),
+ /* Tested in test-auditor.sh #7 */
+ TALER_JSON_pack_amount ("total_bad_sig_loss",
+ &total_bad_sig_loss),
+ TALER_JSON_pack_amount ("total_arithmetic_delta_plus",
+ &total_arithmetic_delta_plus),
+ TALER_JSON_pack_amount ("total_arithmetic_delta_minus",
+ &total_arithmetic_delta_minus),
+
+ /* Global 'balances' */
TALER_JSON_pack_amount ("total_escrow_balance",
- &total_escrow_balance),
+ &balance.reserve_balance),
+ /* Tested in test-auditor.sh #3 */
+ TALER_JSON_pack_amount ("total_irregular_loss",
+ &balance.reserve_loss),
TALER_JSON_pack_amount ("total_withdraw_fee_income",
- &total_withdraw_fee_income),
- TALER_JSON_pack_amount ("total_history_fee_income",
- &total_history_fee_income),
+ &balance.withdraw_fee_balance),
+ TALER_JSON_pack_amount ("total_close_fee_income",
+ &balance.close_fee_balance),
TALER_JSON_pack_amount ("total_purse_fee_income",
- &total_purse_fee_income),
+ &balance.purse_fee_balance),
+ TALER_JSON_pack_amount ("total_open_fee_income",
+ &balance.open_fee_balance),
+ TALER_JSON_pack_amount ("total_history_fee_income",
+ &balance.history_fee_balance),
+
+ /* Detailed report tables */
+ GNUNET_JSON_pack_array_steal (
+ "reserve_balance_insufficient_inconsistencies",
+ report_reserve_balance_insufficient_inconsistencies),
+ GNUNET_JSON_pack_array_steal (
+ "purse_balance_insufficient_inconsistencies",
+ report_purse_balance_insufficient_inconsistencies),
/* Tested in test-auditor.sh #21 */
GNUNET_JSON_pack_array_steal ("reserve_not_closed_inconsistencies",
report_reserve_not_closed_inconsistencies),
- /* Tested in test-auditor.sh #21 */
- TALER_JSON_pack_amount ("total_balance_reserve_not_closed",
- &total_balance_reserve_not_closed),
/* Tested in test-auditor.sh #7 */
GNUNET_JSON_pack_array_steal ("bad_sig_losses",
report_bad_sig_losses),
- /* Tested in test-auditor.sh #7 */
- TALER_JSON_pack_amount ("total_bad_sig_loss",
- &total_bad_sig_loss),
/* Tested in test-revocation.sh #4 */
GNUNET_JSON_pack_array_steal ("row_inconsistencies",
report_row_inconsistencies),
@@ -2045,42 +2017,44 @@ run (void *cls,
denomination_key_validity_withdraw_inconsistencies),
GNUNET_JSON_pack_array_steal ("amount_arithmetic_inconsistencies",
report_amount_arithmetic_inconsistencies),
- TALER_JSON_pack_amount ("total_arithmetic_delta_plus",
- &total_arithmetic_delta_plus),
- TALER_JSON_pack_amount ("total_arithmetic_delta_minus",
- &total_arithmetic_delta_minus),
+
+ /* Information about audited range ... */
TALER_JSON_pack_time_abs_human ("auditor_start_time",
start_time),
TALER_JSON_pack_time_abs_human ("auditor_end_time",
GNUNET_TIME_absolute_get ()),
- TALER_JSON_pack_amount ("total_irregular_recoups",
- &total_irregular_recoups),
GNUNET_JSON_pack_uint64 ("start_ppr_reserve_in_serial_id",
ppr_start.last_reserve_in_serial_id),
GNUNET_JSON_pack_uint64 ("start_ppr_reserve_out_serial_id",
ppr_start.last_reserve_out_serial_id),
GNUNET_JSON_pack_uint64 ("start_ppr_reserve_recoup_serial_id",
ppr_start.last_reserve_recoup_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_reserve_open_serial_id",
+ ppr_start.last_reserve_open_serial_id),
GNUNET_JSON_pack_uint64 ("start_ppr_reserve_close_serial_id",
ppr_start.last_reserve_close_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_purse_decisions_serial_id",
+ ppr_start.last_purse_decisions_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_account_merges_serial_id",
+ ppr_start.last_account_merges_serial_id),
+ GNUNET_JSON_pack_uint64 ("start_ppr_history_requests_serial_id",
+ ppr_start.last_history_requests_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_reserve_in_serial_id",
ppr.last_reserve_in_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_reserve_out_serial_id",
ppr.last_reserve_out_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_reserve_recoup_serial_id",
ppr.last_reserve_recoup_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_reserve_open_serial_id",
+ ppr.last_reserve_open_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_reserve_close_serial_id",
ppr.last_reserve_close_serial_id),
- GNUNET_JSON_pack_uint64 ("end_ppr_purse_merges_serial_id",
- ppr.last_purse_merges_serial_id),
- GNUNET_JSON_pack_uint64 ("end_ppr_purse_deposits_serial_id",
- ppr.last_purse_deposits_serial_id),
+ GNUNET_JSON_pack_uint64 ("end_ppr_purse_decisions_serial_id",
+ ppr.last_purse_decisions_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_account_merges_serial_id",
ppr.last_account_merges_serial_id),
GNUNET_JSON_pack_uint64 ("end_ppr_history_requests_serial_id",
- ppr.last_history_requests_serial_id),
- GNUNET_JSON_pack_uint64 ("end_ppr_close_requests_serial_id",
- ppr.last_close_requests_serial_id)));
+ ppr.last_history_requests_serial_id)));
}
diff --git a/src/auditor/taler-helper-auditor-wire.c b/src/auditor/taler-helper-auditor-wire.c
index 7d5e8a933..081ee01e6 100644
--- a/src/auditor/taler-helper-auditor-wire.c
+++ b/src/auditor/taler-helper-auditor-wire.c
@@ -93,14 +93,9 @@ struct WireAccount
struct TALER_AUDITORDB_WireAccountProgressPoint start_pp;
/**
- * Where we are in the inbound (CREDIT) transaction history.
+ * Where we are in the transaction history.
*/
- uint64_t in_wire_off;
-
- /**
- * Where we are in the inbound (DEBIT) transaction history.
- */
- uint64_t out_wire_off;
+ struct TALER_AUDITORDB_BankAccountProgressPoint wire_off;
/**
* Return value when we got this account's progress point.
@@ -772,16 +767,14 @@ commit (enum GNUNET_DB_QueryStatus qs)
&TALER_ARL_master_pub,
wa->ai->section_name,
&wa->pp,
- wa->in_wire_off,
- wa->out_wire_off);
+ &wa->wire_off);
else
qs = TALER_ARL_adb->insert_wire_auditor_account_progress (
TALER_ARL_adb->cls,
&TALER_ARL_master_pub,
wa->ai->section_name,
&wa->pp,
- wa->in_wire_off,
- wa->out_wire_off);
+ &wa->wire_off);
if (0 >= qs)
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -1520,7 +1513,7 @@ history_debit_cb (void *cls,
TALER_amount2s (&details->amount),
TALER_B2S (&details->wtid));
/* Update offset */
- wa->out_wire_off = row_off;
+ wa->wire_off.out_wire_off = row_off;
slen = strlen (details->credit_account_uri) + 1;
roi = GNUNET_malloc (sizeof (struct ReserveOutInfo)
+ slen);
@@ -1594,7 +1587,7 @@ process_debits (void *cls)
// (CG: used to be INT64_MAX, changed by MS to INT32_MAX, why? To be discussed with him!)
wa->dhh = TALER_BANK_debit_history (ctx,
wa->ai->auth,
- wa->out_wire_off,
+ wa->wire_off.out_wire_off,
INT32_MAX,
GNUNET_TIME_UNIT_ZERO,
&history_debit_cb,
@@ -1846,7 +1839,7 @@ history_credit_cb (void *cls,
}
/* Update offset */
- wa->in_wire_off = row_off;
+ wa->wire_off.in_wire_off = row_off;
/* compare records with expected data */
if (0 != GNUNET_memcmp (&details->reserve_pub,
&rii->details.reserve_pub))
@@ -2032,7 +2025,7 @@ process_credits (void *cls)
// (CG: used to be INT64_MAX, changed by MS to INT32_MAX, why? To be discussed with him!)
wa->chh = TALER_BANK_credit_history (ctx,
wa->ai->auth,
- wa->in_wire_off,
+ wa->wire_off.in_wire_off,
INT32_MAX,
GNUNET_TIME_UNIT_ZERO,
&history_credit_cb,
@@ -2084,12 +2077,14 @@ reserve_closed_cb (void *cls,
const struct TALER_Amount *closing_fee,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *receiver_account,
- const struct TALER_WireTransferIdentifierRawP *wtid)
+ const struct TALER_WireTransferIdentifierRawP *wtid,
+ uint64_t close_request_row)
{
struct ReserveClosure *rc;
struct GNUNET_HashCode key;
(void) cls;
+ (void) close_request_row;
rc = GNUNET_new (struct ReserveClosure);
if (TALER_ARL_SR_INVALID_NEGATIVE ==
TALER_ARL_amount_subtract_neg (&rc->amount,
@@ -2210,8 +2205,7 @@ begin_transaction (void)
&TALER_ARL_master_pub,
wa->ai->section_name,
&wa->pp,
- &wa->in_wire_off,
- &wa->out_wire_off);
+ &wa->wire_off);
if (0 > wa->qsx)
{
GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == wa->qsx);
diff --git a/src/auditor/test-auditor.sh b/src/auditor/test-auditor.sh
index c9895b6f3..34a3980d9 100755
--- a/src/auditor/test-auditor.sh
+++ b/src/auditor/test-auditor.sh
@@ -388,7 +388,7 @@ function test_0() {
then
exit_fail "Wrong total bad sig loss from aggregation, got unexpected loss of $LOSS"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:0"
then
exit_fail "Wrong total bad sig loss from coins, got unexpected loss of $LOSS"
@@ -613,7 +613,7 @@ function test_3() {
exit_fail "Expected reserve balance summary amount wrong, got $EXPECTED (exchange)"
fi
- WIRED=`jq -r .total_loss_balance_insufficient < test-audit-reserves.json`
+ WIRED=`jq -r .total_irregular_loss < test-audit-reserves.json`
if test $WIRED != "TESTKUDOS:0"
then
exit_fail "Wrong total loss from insufficient balance, got $WIRED"
@@ -690,7 +690,7 @@ function test_4() {
exit_fail "Wrong operation, got $OP"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:3"
then
exit_fail "Wrong total bad sig loss, got $LOSS"
@@ -734,7 +734,7 @@ function test_5() {
exit_fail "Wrong operation, got $OP"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:3"
then
exit_fail "Wrong total bad sig loss, got $LOSS"
@@ -776,7 +776,7 @@ function test_6() {
exit_fail "Wrong operation, got $OP"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS == "TESTKUDOS:0"
then
exit_fail "Wrong total bad sig loss, got $LOSS"
@@ -1093,7 +1093,7 @@ function test_13() {
fi
LOSS=`jq -er .bad_sig_losses[0].loss < test-audit-coins.json`
- TOTAL_LOSS=`jq -er .total_bad_sig_loss < test-audit-coins.json`
+ TOTAL_LOSS=`jq -er .irregular_loss < test-audit-coins.json`
if test x$LOSS != x$TOTAL_LOSS
then
exit_fail "Loss inconsistent, got $LOSS and $TOTAL_LOSS"
@@ -1644,7 +1644,7 @@ function test_26() {
exit_fail "Wrong operation, got $OP"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:3"
then
exit_fail "Wrong total bad sig loss, got $LOSS"
@@ -1805,7 +1805,7 @@ function test_31() {
run_audit aggregator
echo -n "Testing inconsistency detection... "
- AMOUNT=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ AMOUNT=`jq -r .irregular_loss < test-audit-coins.json`
if test "x$AMOUNT" == "xTESTKUDOS:0"
then
exit_fail "Reported total amount wrong: $AMOUNT"
@@ -1892,7 +1892,7 @@ function test_33() {
then
exit_fail "Wrong total bad sig loss from aggregation, got unexpected loss of $LOSS"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:0"
then
exit_fail "Wrong total bad sig loss from coins, got unexpected loss of $LOSS"
diff --git a/src/auditor/test-revocation.sh b/src/auditor/test-revocation.sh
index e21b94878..22d1c86ab 100755
--- a/src/auditor/test-revocation.sh
+++ b/src/auditor/test-revocation.sh
@@ -337,7 +337,7 @@ function test_0() {
then
exit_fail "Wrong total bad sig loss from aggregation, got unexpected loss of $LOSS"
fi
- LOSS=`jq -r .total_bad_sig_loss < test-audit-coins.json`
+ LOSS=`jq -r .irregular_loss < test-audit-coins.json`
if test $LOSS != "TESTKUDOS:0"
then
exit_fail "Wrong total bad sig loss from coins, got unexpected loss of $LOSS"
@@ -561,7 +561,7 @@ function test_4() {
echo -n "Testing inconsistency detection... "
# Coin spent exceeded coin's value
jq -e .bad_sig_losses[0] < test-audit-coins.json > /dev/null || exit_fail "Bad recoup not detected"
- AMOUNT=`jq -r .total_bad_sig_losses < test-audit-coins.json`
+ AMOUNT=`jq -r .irregular_loss < test-audit-coins.json`
if test $AMOUNT == "TESTKUDOS:0"
then
exit_fail "Total bad sig losses are wrong"