more work on auditor
This commit is contained in:
parent
9a5cef0eb1
commit
9cfe47493c
@ -25,16 +25,16 @@
|
||||
* given in the 'wire_out' table. This needs to be checked separately!
|
||||
*
|
||||
* TODO:
|
||||
* - implement merchant deposit audit starting with 'wire_out'
|
||||
* - modify auditordb to allow multiple last serial IDs per table in progress tracking (needed?)
|
||||
* - modify auditordb to track risk with balances and fees (and rename callback
|
||||
* - COMPLETE: implement misc. FIXMEs
|
||||
* - COMPLETE: deal with risk / expired denomination keys in #sync_denomination
|
||||
* - SANITY: modify auditordb to track risk with balances and fees (and rename callback
|
||||
* to clarify what it is)
|
||||
* - modify auditordb to return DK when we inquire about deposit/refresh/refund,
|
||||
* - SANITY: rename operations to better describe what they do!
|
||||
* - OPTIMIZE/SIMPLIFY: modify auditordb to return DK when we inquire about deposit/refresh/refund,
|
||||
* so we can avoid the costly #get_coin_summary with the transaction history building
|
||||
* (at least during #analyze_coins); the logic may be partially useful in
|
||||
* #analyze_merchants (but we won't need the cache!)
|
||||
* - deal with risk / expired denomination keys in #sync_denomination
|
||||
* - write reporting logic to output nice report beyond GNUNET_log()
|
||||
* - BEAUTIFY: write reporting logic to output nice report beyond GNUNET_log()
|
||||
* - write logic to deal with emergency (#3887) -- and emergency-related tables!
|
||||
*/
|
||||
#include "platform.h"
|
||||
@ -191,6 +191,49 @@ report_reserve_inconsistency (const struct TALER_ReservePublicKeyP *reserve_pub,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Report a global inconsistency with respect to a wire transfer.
|
||||
*
|
||||
* @param reserve_pub the affected reserve
|
||||
* @param expected expected amount
|
||||
* @param observed observed amount
|
||||
* @param diagnostic message explaining what @a expected and @a observed refer to
|
||||
*/
|
||||
static void
|
||||
report_wire_out_inconsistency (const json_t *destination,
|
||||
uint64_t rowid,
|
||||
const struct TALER_Amount *expected,
|
||||
const struct TALER_Amount *observed,
|
||||
const char *diagnostic)
|
||||
{
|
||||
// TODO: implement proper reporting logic writing to file, include amounts.
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Wire out inconsistency detected: %s\n",
|
||||
diagnostic);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Report a global inconsistency with respect to a coin's history.
|
||||
*
|
||||
* @param coin_pub the affected coin
|
||||
* @param expected expected amount
|
||||
* @param observed observed amount
|
||||
* @param diagnostic message explaining what @a expected and @a observed refer to
|
||||
*/
|
||||
static void
|
||||
report_coin_inconsistency (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
const struct TALER_Amount *expected,
|
||||
const struct TALER_Amount *observed,
|
||||
const char *diagnostic)
|
||||
{
|
||||
// TODO: implement proper reporting logic writing to file, include amounts.
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Coin inconsistency detected: %s\n",
|
||||
diagnostic);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Report the final result on the reserve balances of the exchange.
|
||||
* The reserve must have @a total_balance in its escrow account just
|
||||
@ -1714,9 +1757,9 @@ deposit_cb (void *cls,
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: *if* past pay_deadline, check that
|
||||
aggregation record exists for the deposit;
|
||||
if NOT, check that full _refund_ exists. */
|
||||
/* TODO: *if* past pay_deadline, check that aggregation record
|
||||
exists for the deposit, and if NOT, check that full _refund_
|
||||
exists. */
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
@ -2113,11 +2156,6 @@ struct WireCheckContext
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute date;
|
||||
|
||||
/**
|
||||
* Set to error message of @e ok is #GNUNET_SYSERR.
|
||||
*/
|
||||
const char *emsg;
|
||||
|
||||
/**
|
||||
* Wire method used for the transfer.
|
||||
*/
|
||||
@ -2209,7 +2247,10 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
{
|
||||
/* overflow in history already!? inconceivable! Bad DB! */
|
||||
GNUNET_break (0);
|
||||
// FIXME: report!
|
||||
report_coin_inconsistency (coin_pub,
|
||||
add_to,
|
||||
amount_with_fee,
|
||||
"could not add coin's contribution to total");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
TALER_amount_ntoh (&tmp,
|
||||
@ -2220,7 +2261,10 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
{
|
||||
/* Disagreement in fee structure within DB! */
|
||||
GNUNET_break (0);
|
||||
// FIXME: report!
|
||||
report_coin_inconsistency (coin_pub,
|
||||
&tmp,
|
||||
fee,
|
||||
"coin's fee in transaction and in denomination data differ");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
@ -2230,20 +2274,26 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
{
|
||||
/* overflow in fee total? inconceivable! Bad DB! */
|
||||
GNUNET_break (0);
|
||||
// FIXME: report!
|
||||
report_coin_inconsistency (coin_pub,
|
||||
fee,
|
||||
&fees,
|
||||
"could not add coin's fee to total fees");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
} /* for 'tl' */
|
||||
|
||||
/* Finally, calculate total balance change, i.e. expenditures minus refunds */
|
||||
if (GNUNET_OK !=
|
||||
if (GNUNET_SYSERR ==
|
||||
TALER_amount_subtract (final_expenditures,
|
||||
&expenditures,
|
||||
&refunds))
|
||||
{
|
||||
/* refunds above expenditures? inconceivable! Bad DB! */
|
||||
GNUNET_break (0);
|
||||
// FIXME: report!
|
||||
report_coin_inconsistency (coin_pub,
|
||||
&expenditures,
|
||||
&refunds,
|
||||
"could not subtract refunded amount from expenditures");
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
@ -2255,6 +2305,7 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
* transaction data associated with a wire transfer identifier.
|
||||
*
|
||||
* @param cls a `struct WireCheckContext`
|
||||
* @param rowid which row in the table is the information from (for diagnostics)
|
||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param wire_method which wire plugin was used for the transfer?
|
||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||
@ -2264,9 +2315,9 @@ check_transaction_history (const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
* @param coin_value amount contributed by this coin in total (with fee)
|
||||
* @param coin_fee applicable fee for this coin
|
||||
*/
|
||||
// TODO: modify to have rowid to log errors in a more fine-grained way?
|
||||
static void
|
||||
wire_transfer_information_cb (void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
@ -2291,7 +2342,9 @@ wire_transfer_information_cb (void *cls,
|
||||
if (NULL == tl)
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "no transaction history for coin claimed in aggregation";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"no transaction history for coin claimed in aggregation");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2315,11 +2368,14 @@ wire_transfer_information_cb (void *cls,
|
||||
&dki,
|
||||
NULL))
|
||||
{
|
||||
/* This should be impossible from database constraints */
|
||||
GNUNET_break (0);
|
||||
edb->free_coin_transaction_list (edb->cls,
|
||||
tl);
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "could not find denomination key for coin claimed in aggregation";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"could not find denomination key for coin claimed in aggregation");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2336,14 +2392,18 @@ wire_transfer_information_cb (void *cls,
|
||||
coin_value))
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "coin transaction history and aggregation disagree about coin's contribution";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"coin transaction history and aggregation disagree about coin's contribution");
|
||||
}
|
||||
if (0 !=
|
||||
TALER_amount_cmp (&computed_fees,
|
||||
coin_fee))
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "coin transaction history and aggregation disagree about applicable fees";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"coin transaction history and aggregation disagree about applicable fees");
|
||||
}
|
||||
edb->free_coin_transaction_list (edb->cls,
|
||||
tl);
|
||||
@ -2353,21 +2413,28 @@ wire_transfer_information_cb (void *cls,
|
||||
wcc->method))
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "wire method of aggregate do not match wire transfer";
|
||||
return;
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"wire method of aggregate do not match wire transfer");
|
||||
}
|
||||
if (0 != memcmp (h_wire,
|
||||
&wcc->h_wire,
|
||||
sizeof (struct GNUNET_HashCode)))
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "account details of aggregate do not match account details of wire transfer";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"account details of aggregate do not match account details of wire transfer");
|
||||
return;
|
||||
}
|
||||
if (exec_time.abs_value_us != wcc->date.abs_value_us)
|
||||
{
|
||||
/* This should be impossible from database constraints */
|
||||
GNUNET_break (0);
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "date given in aggregate does not match wire transfer date";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"date given in aggregate does not match wire transfer date");
|
||||
return;
|
||||
}
|
||||
if (GNUNET_SYSERR ==
|
||||
@ -2376,7 +2443,9 @@ wire_transfer_information_cb (void *cls,
|
||||
coin_fee))
|
||||
{
|
||||
wcc->ok = GNUNET_SYSERR;
|
||||
wcc->emsg = "could not calculate contribution of coin";
|
||||
report_row_inconsistency ("aggregation",
|
||||
rowid,
|
||||
"could not calculate contribution of coin");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2418,7 +2487,10 @@ check_wire_out_cb (void *cls,
|
||||
if ( (NULL == method) ||
|
||||
(! json_is_string (method)) )
|
||||
{
|
||||
// TODO: bitch
|
||||
report_row_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"specified wire address lacks type");
|
||||
return;
|
||||
}
|
||||
wcc.method = json_string_value (method);
|
||||
wcc.ok = GNUNET_OK;
|
||||
@ -2434,24 +2506,35 @@ check_wire_out_cb (void *cls,
|
||||
&wcc);
|
||||
if (GNUNET_OK != wcc.ok)
|
||||
{
|
||||
// TODO: bitch
|
||||
report_row_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"audit of associated transactions failed");
|
||||
}
|
||||
plugin = get_wire_plugin (mc,
|
||||
wcc.method);
|
||||
if (NULL == plugin)
|
||||
{
|
||||
// TODO: bitch
|
||||
report_row_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"could not load required wire plugin to validate");
|
||||
return;
|
||||
}
|
||||
if (GNUNET_OK !=
|
||||
plugin->amount_round (plugin->cls,
|
||||
&wcc.total_deposits))
|
||||
{
|
||||
// TODO: bitch
|
||||
report_row_minor_inconsistency ("wire_out",
|
||||
rowid,
|
||||
"wire plugin failed to round given amount");
|
||||
}
|
||||
if (0 != TALER_amount_cmp (amount,
|
||||
&wcc.total_deposits))
|
||||
{
|
||||
// TODO: bitch!
|
||||
report_wire_out_inconsistency (wire,
|
||||
rowid,
|
||||
&wcc.total_deposits,
|
||||
amount,
|
||||
"computed amount inconsistent with wire amount");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1912,6 +1912,7 @@ struct WtidTransactionContext
|
||||
* transaction data for the given wire transfer identifier.
|
||||
*
|
||||
* @param cls our context for transmission
|
||||
* @param rowid which row in the DB is the information from (for diagnostics)
|
||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param exec_time execution time of the wire transfer (should be same for all callbacks with the same @e cls)
|
||||
@ -1922,6 +1923,7 @@ struct WtidTransactionContext
|
||||
*/
|
||||
static void
|
||||
handle_transaction_data (void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
|
@ -490,7 +490,8 @@ postgres_create_tables (void *cls)
|
||||
/* Table for the tracking API, mapping from wire transfer identifiers
|
||||
to transactions and back */
|
||||
SQLEXEC("CREATE TABLE IF NOT EXISTS aggregation_tracking "
|
||||
"(deposit_serial_id INT8 PRIMARY KEY REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE"
|
||||
"(aggregation_serial_id BIGSERIAL"
|
||||
",deposit_serial_id INT8 PRIMARY KEY REFERENCES deposits (deposit_serial_id) ON DELETE CASCADE"
|
||||
",wtid_raw BYTEA CONSTRAINT wire_out_ref REFERENCES wire_out(wtid_raw) ON DELETE CASCADE DEFERRABLE"
|
||||
",execution_time INT8 NOT NULL"
|
||||
")");
|
||||
@ -1235,7 +1236,8 @@ postgres_prepare (PGconn *db_conn)
|
||||
/* Used in #postgres_lookup_wire_transfer */
|
||||
PREPARE ("lookup_transactions",
|
||||
"SELECT"
|
||||
" deposits.h_proposal_data"
|
||||
" aggregation_serial_id"
|
||||
",deposits.h_proposal_data"
|
||||
",deposits.wire"
|
||||
",deposits.h_wire"
|
||||
",deposits.coin_pub"
|
||||
@ -4067,6 +4069,7 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
}
|
||||
for (i=0;i<nrows;i++)
|
||||
{
|
||||
uint64_t rowid;
|
||||
struct GNUNET_HashCode h_proposal_data;
|
||||
struct GNUNET_HashCode h_wire;
|
||||
struct TALER_CoinSpendPublicKeyP coin_pub;
|
||||
@ -4078,6 +4081,7 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
json_t *t;
|
||||
const char *wire_method;
|
||||
struct GNUNET_PQ_ResultSpec rs[] = {
|
||||
GNUNET_PQ_result_spec_uint64 ("aggregation_serial_id", &rowid),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_proposal_data", &h_proposal_data),
|
||||
TALER_PQ_result_spec_json ("wire", &wire),
|
||||
GNUNET_PQ_result_spec_auto_from_type ("h_wire", &h_wire),
|
||||
@ -4088,6 +4092,7 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
TALER_PQ_result_spec_amount ("fee_deposit", &deposit_fee),
|
||||
GNUNET_PQ_result_spec_end
|
||||
};
|
||||
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_PQ_extract_result (result,
|
||||
rs,
|
||||
@ -4112,6 +4117,7 @@ postgres_lookup_wire_transfer (void *cls,
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
cb (cb_cls,
|
||||
rowid,
|
||||
&merchant_pub,
|
||||
wire_method,
|
||||
&h_wire,
|
||||
|
@ -752,6 +752,7 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
|
||||
*/
|
||||
static void
|
||||
cb_wt_never (void *cls,
|
||||
uint64_t serial_id,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
@ -795,6 +796,7 @@ static struct TALER_WireTransferIdentifierRawP wtid_wt;
|
||||
*/
|
||||
static void
|
||||
cb_wt_check (void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
|
@ -759,6 +759,7 @@ typedef void
|
||||
* transaction data associated with a wire transfer identifier.
|
||||
*
|
||||
* @param cls closure
|
||||
* @param rowid which row in the table is the information from (for diagnostics)
|
||||
* @param merchant_pub public key of the merchant (should be same for all callbacks with the same @e cls)
|
||||
* @param wire_method which wire plugin was used for the transfer?
|
||||
* @param h_wire hash of wire transfer details of the merchant (should be same for all callbacks with the same @e cls)
|
||||
@ -770,6 +771,7 @@ typedef void
|
||||
*/
|
||||
typedef void
|
||||
(*TALER_EXCHANGEDB_WireTransferDataCallback)(void *cls,
|
||||
uint64_t rowid,
|
||||
const struct TALER_MerchantPublicKeyP *merchant_pub,
|
||||
const char *wire_method,
|
||||
const struct GNUNET_HashCode *h_wire,
|
||||
|
Loading…
Reference in New Issue
Block a user