diff options
Diffstat (limited to 'src/auditor/taler-helper-auditor-purses.c')
-rw-r--r-- | src/auditor/taler-helper-auditor-purses.c | 305 |
1 files changed, 294 insertions, 11 deletions
diff --git a/src/auditor/taler-helper-auditor-purses.c b/src/auditor/taler-helper-auditor-purses.c index 967ac13a7..0dc8833d5 100644 --- a/src/auditor/taler-helper-auditor-purses.c +++ b/src/auditor/taler-helper-auditor-purses.c @@ -26,6 +26,7 @@ #include "taler_bank_service.h" #include "taler_signatures.h" #include "report-lib.h" +#include "taler_dbevents.h" /** @@ -118,6 +119,18 @@ static struct TALER_Amount total_bad_sig_loss; */ static int internal_checks; +static struct GNUNET_DB_EventHandler *eh; + +/** + * Our database plugin. + */ +static struct TALER_AUDITORDB_Plugin *db_plugin; + +/** + * The auditors's configuration. + */ +static const struct GNUNET_CONFIGURATION_Handle *cfg; + /* ***************************** Report logic **************************** */ @@ -144,6 +157,8 @@ report_amount_arithmetic_inconsistency ( { struct TALER_Amount delta; struct TALER_Amount *target; + struct TALER_AUDITORDB_AmountArithmeticInconsistency aai; + enum GNUNET_DB_QueryStatus qs; if (0 < TALER_amount_cmp (exchange, auditor)) @@ -161,6 +176,20 @@ report_amount_arithmetic_inconsistency ( auditor, exchange); } + aai.profitable = profitable; + aai.operation = (char *) operation; + aai.exchange_amount = *exchange; + aai.auditor_amount = *auditor; + + qs = TALER_ARL_adb->insert_amount_arithmetic_inconsistency ( + TALER_ARL_adb->cls, + &aai); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_amount_arithmetic_inconsistencies, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("operation", @@ -176,8 +205,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); @@ -197,6 +226,22 @@ report_row_inconsistency (const char *table, uint64_t rowid, const char *diagnostic) { + enum GNUNET_DB_QueryStatus qs; + struct TALER_AUDITORDB_RowInconsistency ri; + + ri.diagnostic = (char *) diagnostic; + ri.row_table = (char *) table; + ri.row_id = rowid; + + qs = TALER_ARL_adb->insert_row_inconsistency ( + TALER_ARL_adb->cls, + &ri); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_row_inconsistencies, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("table", @@ -478,6 +523,8 @@ handle_purse_requested ( struct PurseContext *pc = cls; struct PurseSummary *ps; struct GNUNET_HashCode key; + struct TALER_AUDITORDB_BadSigLosses bsl; + enum GNUNET_DB_QueryStatus qs; TALER_ARL_USE_PP (purse_request_serial_id) = rowid; if (GNUNET_OK != @@ -489,6 +536,20 @@ handle_purse_requested ( purse_pub, purse_sig)) { + bsl.row_id = rowid; + bsl.operation = "purse-request"; + bsl.loss = *target_amount; + bsl.operation_specific_pub = purse_pub->eddsa_pub; + + qs = TALER_ARL_adb->insert_bad_sig_losses ( + TALER_ARL_adb->cls, + &bsl); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_bad_sig_losses, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("operation", @@ -555,9 +616,11 @@ handle_purse_deposits ( struct PurseSummary *ps; const char *base_url = (NULL == deposit->exchange_base_url) - ? TALER_ARL_exchange_url - : deposit->exchange_base_url; + ? TALER_ARL_exchange_url + : deposit->exchange_base_url; struct TALER_DenominationHashP h_denom_pub; + enum GNUNET_DB_QueryStatus qs; + struct TALER_AUDITORDB_BadSigLosses bsl; /* should be monotonically increasing */ GNUNET_assert (rowid >= TALER_ARL_USE_PP (purse_deposits_serial_id)); @@ -565,7 +628,7 @@ handle_purse_deposits ( { const struct TALER_EXCHANGEDB_DenominationKeyInformation *issue; - enum GNUNET_DB_QueryStatus qs; + qs = TALER_ARL_get_denomination_info (denom_pub, &issue, @@ -603,6 +666,20 @@ handle_purse_deposits ( &deposit->coin_pub, &deposit->coin_sig)) { + bsl.row_id = rowid; + bsl.operation = "purse-deposit"; + bsl.loss = deposit->amount; + bsl.operation_specific_pub = deposit->coin_pub.eddsa_pub; + + qs = TALER_ARL_adb->insert_bad_sig_losses ( + TALER_ARL_adb->cls, + &bsl); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_bad_sig_losses, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("operation", @@ -625,7 +702,7 @@ handle_purse_deposits ( { if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == pc->qs) { - report_row_inconsistency ("purse-deposit", + report_row_inconsistency ("purse_deposit", rowid, "purse not found"); } @@ -679,6 +756,8 @@ handle_purse_merged ( { struct PurseContext *pc = cls; struct PurseSummary *ps; + struct TALER_AUDITORDB_BadSigLosses bsl; + enum GNUNET_DB_QueryStatus qs; /* should be monotonically increasing */ GNUNET_assert (rowid >= TALER_ARL_USE_PP (purse_merges_serial_id)); @@ -689,8 +768,8 @@ handle_purse_merged ( reserve_url = TALER_reserve_make_payto (NULL == partner_base_url - ? TALER_ARL_exchange_url - : partner_base_url, + ? TALER_ARL_exchange_url + : partner_base_url, reserve_pub); if (GNUNET_OK != TALER_wallet_purse_merge_verify (reserve_url, @@ -700,6 +779,20 @@ handle_purse_merged ( merge_sig)) { GNUNET_free (reserve_url); + bsl.row_id = rowid; + bsl.operation = "merge-purse"; + bsl.loss = *amount; + bsl.operation_specific_pub = merge_pub->eddsa_pub; + + qs = TALER_ARL_adb->insert_bad_sig_losses ( + TALER_ARL_adb->cls, + &bsl); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_bad_sig_losses, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("operation", @@ -781,6 +874,8 @@ handle_account_merged ( { struct PurseContext *pc = cls; struct PurseSummary *ps; + struct TALER_AUDITORDB_BadSigLosses bsl; + enum GNUNET_DB_QueryStatus qs; /* should be monotonically increasing */ GNUNET_assert (rowid >= TALER_ARL_USE_PP (purse_account_merge_serial_id)); @@ -797,6 +892,20 @@ handle_account_merged ( reserve_pub, reserve_sig)) { + bsl.row_id = rowid; + bsl.operation = "account-merge"; + bsl.loss = *purse_fee; + bsl.operation_specific_pub = reserve_pub->eddsa_pub; + + qs = TALER_ARL_adb->insert_bad_sig_losses ( + TALER_ARL_adb->cls, + &bsl); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_bad_sig_losses, GNUNET_JSON_PACK ( GNUNET_JSON_pack_string ("operation", @@ -968,8 +1077,23 @@ handle_purse_expired ( struct GNUNET_TIME_Timestamp expiration_date) { struct PurseContext *pc = cls; + struct TALER_AUDITORDB_PurseNotClosedInconsistencies pnci; + enum GNUNET_DB_QueryStatus qs; (void) pc; + pnci.amount = *balance; + pnci.expiration_date = expiration_date.abs_time; + pnci.purse_pub = purse_pub->eddsa_pub; + + qs = TALER_ARL_adb->insert_purse_not_closed_inconsistencies ( + TALER_ARL_adb->cls, + &pnci); + + if (qs < 0) + { + GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); + } + TALER_ARL_report (report_purse_not_closed_inconsistencies, GNUNET_JSON_PACK ( GNUNET_JSON_pack_data_auto ("purse_pub", @@ -1088,6 +1212,8 @@ analyze_purses (void *cls) enum GNUNET_DB_QueryStatus qsx; enum GNUNET_DB_QueryStatus qs; enum GNUNET_DB_QueryStatus qsp; + char progress_exists = 1; + char balance_exists = 1; (void) cls; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1113,6 +1239,10 @@ analyze_purses (void *cls) } else { + if (TALER_ARL_USE_PP (purse_account_merge_serial_id) == 0) + { + progress_exists = 0; + } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resuming purse audit at %llu/%llu/%llu/%llu/%llu\n", (unsigned long long) TALER_ARL_USE_PP ( @@ -1136,6 +1266,17 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx); return qsx; } + if (GNUNET_NO == TALER_amount_is_valid (&TALER_ARL_USE_AB ( + purse_global_balance))) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Found no balance, starting by 0.\n"); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &TALER_ARL_USE_AB ( + purse_global_balance))); + balance_exists = 0; + } pc.purses = GNUNET_CONTAINER_multihashmap_create (512, GNUNET_NO); @@ -1211,7 +1352,7 @@ analyze_purses (void *cls) GNUNET_CONTAINER_multihashmap_destroy (pc.purses); if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != pc.qs) return qs; - if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx) + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsx && balance_exists == 0) { qs = TALER_ARL_adb->insert_balance ( TALER_ARL_adb->cls, @@ -1230,7 +1371,7 @@ analyze_purses (void *cls) GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs); return qs; } - if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsp) + if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsp && progress_exists == 1) qs = TALER_ARL_adb->update_auditor_progress ( TALER_ARL_adb->cls, TALER_ARL_SET_PP (purse_account_merge_serial_id), @@ -1274,6 +1415,94 @@ analyze_purses (void *cls) /** + * Function called on events received from Postgres. + * + * @param cls closure, NULL + * @param extra additional event data provided + * @param extra_size number of bytes in @a extra + */ +static void +db_notify (void *cls, + const void *extra, + size_t extra_size) +{ + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received notification to wake purses\n"); + + (void) cls; + (void) extra; + (void) extra_size; + + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &TALER_ARL_USE_AB ( + purse_global_balance))); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &total_balance_insufficient_loss)); + GNUNET_assert (GNUNET_OK == + TALER_amount_set_zero (TALER_ARL_currency, + &total_delayed_decisions)); + 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_purse_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 != + (report_purse_balance_insufficient_inconsistencies + = json_array ())); + GNUNET_assert (NULL != + (report_purse_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)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Audit failed\n"); + TALER_ARL_done (NULL); + global_ret = EXIT_FAILURE; + } + +} + + +/** + * Function called on shutdown. + */ +static void +do_shutdown (void *cls) +{ + (void) cls; + + if (test_mode != 1) + { + db_plugin->event_listen_cancel (eh); + eh = NULL; + TALER_AUDITORDB_plugin_unload (db_plugin); + db_plugin = NULL; + TALER_ARL_done (NULL); + } +} + + +/** * Main function that will be run. * * @param cls closure @@ -1290,14 +1519,61 @@ run (void *cls, (void) cls; (void) args; (void) cfgfile; + + cfg = c; + + GNUNET_SCHEDULER_add_shutdown (&do_shutdown, + NULL); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Launching auditor\n"); + "Launching purses auditor\n"); + if (GNUNET_OK != TALER_ARL_init (c)) { global_ret = EXIT_FAILURE; return; } + + if (NULL == + (db_plugin = TALER_AUDITORDB_plugin_load (cfg))) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to initialize DB subsystem\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (GNUNET_OK != + db_plugin->preflight (db_plugin->cls)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Failed to connect to database\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + + if (test_mode != 1) + { + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running helper indefinitely\n"); + + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof (es)), + .type = htons (TALER_DBEVENT_EXCHANGE_AUDITOR_WAKE_HELPER_PURSES) + }; + eh = db_plugin->event_listen (db_plugin->cls, + &es, + GNUNET_TIME_UNIT_FOREVER_REL, + &db_notify, + NULL); + return; + } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Running helper in test mode\n"); + + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Starting audit\n"); + GNUNET_assert (GNUNET_OK == TALER_amount_set_zero (TALER_ARL_currency, &TALER_ARL_USE_AB ( @@ -1338,9 +1614,16 @@ run (void *cls, TALER_ARL_setup_sessions_and_run (&analyze_purses, NULL)) { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Audit failed\n"); + TALER_ARL_done (NULL); global_ret = EXIT_FAILURE; return; } + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Audit complete\n"); + TALER_ARL_done ( GNUNET_JSON_PACK ( /* Globals (REVIEW!) */ |