gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [taler-exchange] branch master updated: starting point for


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: starting point for #4948
Date: Mon, 25 Sep 2017 23:27:19 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new e78e0f6  starting point for #4948
e78e0f6 is described below

commit e78e0f6c4e28e1f90fadd5d9840f5428f6ba1ea0
Author: Christian Grothoff <address@hidden>
AuthorDate: Mon Sep 25 23:26:48 2017 +0200

    starting point for #4948
---
 src/auditor/Makefile.am          |  13 ++
 src/auditor/taler-wire-auditor.c | 485 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 498 insertions(+)

diff --git a/src/auditor/Makefile.am b/src/auditor/Makefile.am
index 62dd191..5beab8b 100644
--- a/src/auditor/Makefile.am
+++ b/src/auditor/Makefile.am
@@ -13,6 +13,7 @@ pkgcfg_DATA = \
 
 bin_PROGRAMS = \
   taler-auditor \
+  taler-wire-auditor \
   taler-auditor-sign
 
 taler_auditor_SOURCES = \
@@ -27,6 +28,18 @@ taler_auditor_LDADD = \
   -ljansson \
   -lgnunetutil
 
+taler_wire_auditor_SOURCES = \
+  taler-wire-auditor.c
+taler_wire_auditor_LDADD = \
+  $(LIBGCRYPT_LIBS) \
+  $(top_builddir)/src/util/libtalerutil.la \
+  $(top_builddir)/src/json/libtalerjson.la \
+  $(top_builddir)/src/wire/libtalerwire.la \
+  $(top_builddir)/src/exchangedb/libtalerexchangedb.la \
+  $(top_builddir)/src/auditordb/libtalerauditordb.la \
+  -ljansson \
+  -lgnunetutil
+
 taler_auditor_sign_SOURCES = \
   taler-auditor-sign.c
 taler_auditor_sign_LDADD = \
diff --git a/src/auditor/taler-wire-auditor.c b/src/auditor/taler-wire-auditor.c
new file mode 100644
index 0000000..d6a98a4
--- /dev/null
+++ b/src/auditor/taler-wire-auditor.c
@@ -0,0 +1,485 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2017 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it under the
+  terms of the GNU General 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 General Public License for more details.
+
+  You should have received a copy of the GNU General Public License along with
+  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file auditor/taler-wire-auditor.c
+ * @brief audits that wire transfers match those from an exchange database.
+ * @author Christian Grothoff
+ *
+ * - First, this auditor verifies that 'reserves_in' actually matches
+ *   the incoming wire transfers from the bank.
+ * - Second, we check that the outgoing wire transfers match those
+ *   given in the 'wire_out' table.
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+#include "taler_auditordb_plugin.h"
+#include "taler_exchangedb_plugin.h"
+#include "taler_json_lib.h"
+#include "taler_wire_lib.h"
+#include "taler_signatures.h"
+
+
+/**
+ * Return value from main().
+ */
+static int global_ret;
+
+/**
+ * Command-line option "-r": restart audit from scratch
+ */
+static int restart;
+
+/**
+ * Handle to access the exchange's database.
+ */
+static struct TALER_EXCHANGEDB_Plugin *edb;
+
+/**
+ * Which currency are we doing the audit for?
+ */
+static char *currency;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Our session with the #edb.
+ */
+static struct TALER_EXCHANGEDB_Session *esession;
+
+/**
+ * Handle to access the auditor's database.
+ */
+static struct TALER_AUDITORDB_Plugin *adb;
+
+/**
+ * Our session with the #adb.
+ */
+static struct TALER_AUDITORDB_Session *asession;
+
+/**
+ * Master public key of the exchange to audit.
+ */
+static struct TALER_MasterPublicKeyP master_pub;
+
+/**
+ * Last reserve_in serial ID seen.
+ */
+static struct TALER_AUDITORDB_ProgressPoint pp;
+
+
+/* ***************************** Report logic **************************** */
+
+#if 0
+/**
+ * Report a (serious) inconsistency in the exchange's database.
+ *
+ * @param table affected table
+ * @param rowid affected row, UINT64_MAX if row is missing
+ * @param diagnostic message explaining the problem
+ */
+static void
+report_row_inconsistency (const char *table,
+                          uint64_t rowid,
+                          const char *diagnostic)
+{
+  // TODO: implement proper reporting logic writing to file.
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Database inconsistency detected in table %s at row %llu: %s\n",
+              table,
+              (unsigned long long) rowid,
+              diagnostic);
+}
+
+
+/**
+ * Report a minor inconsistency in the exchange's database (i.e. something
+ * relating to timestamps that should have no financial implications).
+ *
+ * @param table affected table
+ * @param rowid affected row, UINT64_MAX if row is missing
+ * @param diagnostic message explaining the problem
+ */
+static void
+report_row_minor_inconsistency (const char *table,
+                                uint64_t rowid,
+                                const char *diagnostic)
+{
+  // TODO: implement proper reporting logic writing to file.
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Minor inconsistency detected in table %s at row %llu: %s\n",
+              table,
+              (unsigned long long) rowid,
+              diagnostic);
+}
+#endif
+
+
+/* ***************************** Analyze reserves_in ************************ 
*/
+/* This logic checks the reserves_in table */
+
+/**
+ * Analyze reserves for being well-formed.
+ *
+ * @param cls NULL
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+analyze_reserves_in (void *cls)
+{
+  /* FIXME: #4958 */
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+/* ***************************** Analyze reserves_out ************************ 
*/
+/* This logic checks the reserves_out table */
+
+/**
+ * Analyze reserves for being well-formed.
+ *
+ * @param cls NULL
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+analyze_reserves_out (void *cls)
+{
+  /* FIXME: #4958 */
+  return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+}
+
+
+/* *************************** General transaction logic ****************** */
+
+/**
+ * Type of an analysis function.  Each analysis function runs in
+ * its own transaction scope and must thus be internally consistent.
+ *
+ * @param cls closure
+ * @return transaction status code
+ */
+typedef enum GNUNET_DB_QueryStatus
+(*Analysis)(void *cls);
+
+
+/**
+ * Perform the given @a analysis incrementally, checkpointing our
+ * progress in the auditor DB.
+ *
+ * @param analysis analysis to run
+ * @param analysis_cls closure for @a analysis
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+incremental_processing (Analysis analysis,
+                        void *analysis_cls)
+{
+  enum GNUNET_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qsx;
+
+  qsx = adb->get_auditor_progress (adb->cls,
+                                  asession,
+                                  &master_pub,
+                                  &pp);
+  if (0 > qsx)
+  {
+    GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qsx);
+    return qsx;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qsx)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
+                _("First analysis using this auditor, starting audit from 
scratch\n"));
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                _("Resuming audit at %llu/%llu/%llu/%llu/%llu/%llu/%llu\n"),
+                (unsigned long long) pp.last_reserve_in_serial_id,
+                (unsigned long long) pp.last_reserve_out_serial_id,
+                (unsigned long long) pp.last_withdraw_serial_id,
+                (unsigned long long) pp.last_deposit_serial_id,
+                (unsigned long long) pp.last_melt_serial_id,
+                (unsigned long long) pp.last_refund_serial_id,
+                (unsigned long long) pp.last_wire_out_serial_id);
+  }
+  qs = analysis (analysis_cls);
+  if (0 > qs)
+  {
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                 "Serialization issue, not recording progress\n");
+    else
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 "Hard database error, not recording progress\n");
+    return qs;
+  }
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qsx)
+    qs = adb->update_auditor_progress (adb->cls,
+                                      asession,
+                                      &master_pub,
+                                      &pp);
+  else
+    qs = adb->insert_auditor_progress (adb->cls,
+                                      asession,
+                                      &master_pub,
+                                      &pp);
+  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 audit step at 
%llu/%llu/%llu/%llu/%llu/%llu/%llu\n\n"),
+              (unsigned long long) pp.last_reserve_in_serial_id,
+              (unsigned long long) pp.last_reserve_out_serial_id,
+              (unsigned long long) pp.last_withdraw_serial_id,
+              (unsigned long long) pp.last_deposit_serial_id,
+              (unsigned long long) pp.last_melt_serial_id,
+              (unsigned long long) pp.last_refund_serial_id,
+              (unsigned long long) pp.last_wire_out_serial_id);
+  return qs;
+}
+
+
+/**
+ * Perform the given @a analysis within a transaction scope.
+ * Commit on success.
+ *
+ * @param analysis analysis to run
+ * @param analysis_cls closure for @a analysis
+ * @return #GNUNET_OK if @a analysis succeessfully committed,
+ *         #GNUNET_NO if we had an error on commit (retry may help)
+ *         #GNUNET_SYSERR on hard errors
+ */
+static int
+transact (Analysis analysis,
+          void *analysis_cls)
+{
+  int ret;
+  enum GNUNET_DB_QueryStatus qs;
+
+  ret = adb->start (adb->cls,
+                    asession);
+  if (GNUNET_OK != ret)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  ret = edb->start (edb->cls,
+                    esession);
+  if (GNUNET_OK != ret)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  qs = incremental_processing (analysis,
+                                analysis_cls);
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+  {
+    qs = edb->commit (edb->cls,
+                       esession);
+    if (0 > qs)
+    {
+      GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Exchange DB commit failed, rolling back transaction\n");
+      adb->rollback (adb->cls,
+                     asession);
+    }
+    else
+    {
+      qs = adb->commit (adb->cls,
+                       asession);
+      if (0 > qs)
+      {
+       GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    "Auditor DB commit failed!\n");
+      }
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Processing failed, rolling back transaction\n");
+    adb->rollback (adb->cls,
+                   asession);
+    edb->rollback (edb->cls,
+                   esession);
+  }
+  return qs;
+}
+
+
+/**
+ * Initialize DB sessions and run the analysis.
+ */
+static void
+setup_sessions_and_run ()
+{
+  esession = edb->get_session (edb->cls);
+  if (NULL == esession)
+  {
+    fprintf (stderr,
+             "Failed to initialize exchange session.\n");
+    global_ret = 1;
+    return;
+  }
+  asession = adb->get_session (adb->cls);
+  if (NULL == asession)
+  {
+    fprintf (stderr,
+             "Failed to initialize auditor session.\n");
+    global_ret = 1;
+    return;
+  }
+
+  transact (&analyze_reserves_in,
+            NULL);
+  transact (&analyze_reserves_out,
+            NULL);
+}
+
+
+/**
+ * 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)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Launching auditor\n");
+  cfg = c;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "taler",
+                                             "CURRENCY",
+                                             &currency))
+  {
+    GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+                               "taler",
+                               "CURRENCY");
+    global_ret = 1;
+    return;
+  }
+  if (NULL ==
+      (edb = TALER_EXCHANGEDB_plugin_load (cfg)))
+  {
+    fprintf (stderr,
+             "Failed to initialize exchange database plugin.\n");
+    global_ret = 1;
+    return;
+  }
+  if (NULL ==
+      (adb = TALER_AUDITORDB_plugin_load (cfg)))
+  {
+    fprintf (stderr,
+             "Failed to initialize auditor database plugin.\n");
+    global_ret = 1;
+    TALER_EXCHANGEDB_plugin_unload (edb);
+    return;
+  }
+  if (restart)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Full audit restart requested, dropping old audit data.\n");
+    GNUNET_break (GNUNET_OK ==
+                  adb->drop_tables (adb->cls));
+    TALER_AUDITORDB_plugin_unload (adb);
+    if (NULL ==
+        (adb = TALER_AUDITORDB_plugin_load (cfg)))
+    {
+      fprintf (stderr,
+               "Failed to initialize auditor database plugin after drop.\n");
+      global_ret = 1;
+      TALER_EXCHANGEDB_plugin_unload (edb);
+      return;
+    }
+    GNUNET_break (GNUNET_OK ==
+                  adb->create_tables (adb->cls));
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting audit\n");
+  setup_sessions_and_run ();
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Audit complete\n");
+  TALER_AUDITORDB_plugin_unload (adb);
+  TALER_EXCHANGEDB_plugin_unload (edb);
+}
+
+
+/**
+ * The main function of the database initialization tool.
+ * Used to initialize the Taler Exchange's database.
+ *
+ * @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_mandatory
+    (GNUNET_GETOPT_option_base32_auto ('m',
+                                       "exchange-key",
+                                       "KEY",
+                                       "public key of the exchange (Crockford 
base32 encoded)",
+                                       &master_pub)),
+    GNUNET_GETOPT_option_flag ('r',
+                               "restart",
+                               "restart audit from the beginning (required on 
first run)",
+                               &restart),
+    GNUNET_GETOPT_OPTION_END
+  };
+
+  /* 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 ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_log_setup ("taler-wire-auditor",
+                                   "MESSAGE",
+                                   NULL));
+  if (GNUNET_OK !=
+      GNUNET_PROGRAM_run (argc,
+                         argv,
+                          "taler-wire-auditor",
+                         "Audit exchange database for consistency with the 
bank's wire transfers",
+                         options,
+                         &run,
+                         NULL))
+    return 1;
+  return global_ret;
+}
+
+
+/* end of taler-wire-auditor.c */

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]