gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: separate DB creation from plugi


From: gnunet
Subject: [taler-anastasis] branch master updated: separate DB creation from plugin loading; fix misc. Debian package issues
Date: Wed, 01 Sep 2021 00:59:37 +0200

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

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new c3a1a4e  separate DB creation from plugin loading; fix misc. Debian 
package issues
c3a1a4e is described below

commit c3a1a4ecbea0c8df729b7a29da5d31c1f9dab9c9
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Sep 1 00:59:34 2021 +0200

    separate DB creation from plugin loading; fix misc. Debian package issues
---
 debian/anastasis-httpd.postinst                    |    6 +
 debian/db/install/pgsql                            |    2 +-
 debian/etc/anastasis/anastasis.conf                |   21 +
 debian/rules                                       |    2 +-
 doc/sphinx/manpages/anastasis.conf.5.rst           |    3 +
 .../anastasis-helper-authorization-iban.c          |   10 +
 src/backend/anastasis-httpd.c                      |    8 +
 src/include/anastasis_database_plugin.h            |   22 +-
 src/stasis/anastasis-dbinit.c                      |    8 +-
 src/stasis/plugin_anastasis_postgres.c             | 1408 ++++++++++----------
 src/stasis/test_anastasis_db.c                     |   10 +-
 11 files changed, 805 insertions(+), 695 deletions(-)

diff --git a/debian/anastasis-httpd.postinst b/debian/anastasis-httpd.postinst
index fe89acb..994b06b 100644
--- a/debian/anastasis-httpd.postinst
+++ b/debian/anastasis-httpd.postinst
@@ -20,6 +20,12 @@ configure)
     adduser --quiet --system --ingroup ${_GROUPNAME} --no-create-home --home 
${TALER_HOME} ${_USERNAME}
   fi
 
+  if ! dpkg-statoverride --list 
/etc/anastasis/secrets/anastasis-db.secret.conf >/dev/null 2>&1; then
+    dpkg-statoverride --add --update \
+      anastasis-httpd root 460 \
+      /etc/anastasis/secrets/anastasis-db.secret.conf
+  fi
+
   # Setup postgres database (needs dbconfig-pgsql package)
   if [ -f /usr/share/dbconfig-common/dpkg/postinst.pgsql ]; then
     . /usr/share/dbconfig-common/dpkg/postinst.pgsql
diff --git a/debian/db/install/pgsql b/debian/db/install/pgsql
index dab5d1e..f695fed 100755
--- a/debian/db/install/pgsql
+++ b/debian/db/install/pgsql
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 
 set -eu
 
diff --git a/debian/etc/anastasis/anastasis.conf 
b/debian/etc/anastasis/anastasis.conf
index e662a43..4d0deda 100644
--- a/debian/etc/anastasis/anastasis.conf
+++ b/debian/etc/anastasis/anastasis.conf
@@ -1,5 +1,26 @@
 [anastasis]
 DATABASE = postgres
+SERVE = unix
+
+# You must set each of the following options
+# before starting anastasis-httpd!
+#
+# Storage fee for policies (per year)
+#ANNUAL_FEE = KUDOS:0
+#
+# Storage fee for truth
+#TRUTH_UPLOAD_FEE = KUDOS:0
+
+# Name of your business
+#BUSINESS_NAME = ""
+
+# Random server salt. Use output of 'uuidgen'
+#SERVER_SALT = ""
+
+# How high is the per key share insurance offered
+# by your business?
+#INSURANCE = KUDOS:0
+
 
 [taler]
 # Currency accepted by anastasis via GNU Taler payments.
diff --git a/debian/rules b/debian/rules
index e3c7db5..cfd43c7 100755
--- a/debian/rules
+++ b/debian/rules
@@ -34,7 +34,7 @@ override_dh_install:
        dh_install
 # Done manually for debhelper-compat<13
        dh_installtmpfiles
-# Remove files already present in libtalerexchange from main taler-exchange 
package
+# Remove files already present in libanastasis-dev/cli from 
anastasis-httpd/libanastasis packages
        cd debian/libanastasis-dev; find . -type f,l -exec rm -f 
../anastasis-httpd/{} \;
        cd debian/anastasis-cli; find . -type f -exec rm -f 
../anastasis-httpd/{} \;
        cd debian/libanastasis-dev; find . -type f,l -exec rm -f 
../libanastasis/{} \;
diff --git a/doc/sphinx/manpages/anastasis.conf.5.rst 
b/doc/sphinx/manpages/anastasis.conf.5.rst
index 1f6b49e..000d8f0 100644
--- a/doc/sphinx/manpages/anastasis.conf.5.rst
+++ b/doc/sphinx/manpages/anastasis.conf.5.rst
@@ -67,6 +67,9 @@ ANNUAL_FEE
 TRUTH_UPLOAD_FEE
   Annual fee to be paid for truth uploads, i.e. "EUR:1.5".
 
+INSURANCE
+  Amount up to which key shares are warranted, i.e. "EUR:1000000".
+
 DB
   Database backend to use, only ``postgres`` is supported right now.
 
diff --git a/src/authorization/anastasis-helper-authorization-iban.c 
b/src/authorization/anastasis-helper-authorization-iban.c
index 04dfa03..c6e5335 100644
--- a/src/authorization/anastasis-helper-authorization-iban.c
+++ b/src/authorization/anastasis-helper-authorization-iban.c
@@ -389,6 +389,16 @@ run (void *cls,
     global_ret = EXIT_NOTCONFIGURED;
     return;
   }
+  if (GNUNET_OK !=
+      db_plugin->connect (db_plugin->cls))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Database not set up. Did you run anastasis-dbinit?\n");
+    global_ret = EXIT_NOTCONFIGURED;
+    ANASTASIS_DB_plugin_unload (db_plugin);
+    db_plugin = NULL;
+    return;
+  }
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "authorization-iban",
diff --git a/src/backend/anastasis-httpd.c b/src/backend/anastasis-httpd.c
index fdf17ff..9f5c87b 100644
--- a/src/backend/anastasis-httpd.c
+++ b/src/backend/anastasis-httpd.c
@@ -888,6 +888,14 @@ run (void *cls,
     GNUNET_SCHEDULER_shutdown ();
     return;
   }
+  if (GNUNET_OK !=
+      db->connect (db->cls))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Database not setup. Did you run anastasis-dbinit?\n");
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
 
   fh = TALER_MHD_bind (config,
                        "anastasis",
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index 565ad69..bc4b0e6 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -187,8 +187,26 @@ struct ANASTASIS_DatabasePlugin
    * @param cls closure
    * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
    */
-  int
-  (*drop_tables) (void *cls);
+  enum GNUNET_GenericReturnValue
+  (*drop_tables)(void *cls);
+
+  /**
+   * Connect to the database.
+   *
+   * @param cls closure
+   * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+   */
+  enum GNUNET_GenericReturnValue
+  (*connect)(void *cls);
+
+  /**
+   * Initialize merchant tables
+   *
+   * @param cls closure
+   * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+   */
+  enum GNUNET_GenericReturnValue
+  (*create_tables)(void *cls);
 
   /**
    * Function called to perform "garbage collection" on the
diff --git a/src/stasis/anastasis-dbinit.c b/src/stasis/anastasis-dbinit.c
index 038fb7c..17b3c56 100644
--- a/src/stasis/anastasis-dbinit.c
+++ b/src/stasis/anastasis-dbinit.c
@@ -54,7 +54,7 @@ run (void *cls,
   {
     fprintf (stderr,
              "Failed to initialize database plugin.\n");
-    global_ret = 1;
+    global_ret = EXIT_FAILURE;
     return;
   }
   if (reset_db)
@@ -63,6 +63,12 @@ run (void *cls,
     ANASTASIS_DB_plugin_unload (plugin);
     plugin = ANASTASIS_DB_plugin_load (cfg);
   }
+  if (GNUNET_OK !=
+      plugin->create_tables (plugin->cls))
+  {
+    global_ret = EXIT_FAILURE;
+    return;
+  }
   ANASTASIS_DB_plugin_unload (plugin);
 }
 
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index 8ee16ad..b78dbdb 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -81,7 +81,7 @@ struct PostgresClosure
  * @param cls closure our `struct Plugin`
  * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
-static int
+static enum GNUNET_GenericReturnValue
 postgres_drop_tables (void *cls)
 {
   struct PostgresClosure *pg = cls;
@@ -100,266 +100,676 @@ postgres_drop_tables (void *cls)
 
 
 /**
- * Check that the database connection is still up.
- *
- * @param cls a `struct PostgresClosure` with connection to check
- */
-static void
-check_connection (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-
-  GNUNET_PQ_reconnect_if_down (pg->conn);
-}
-
-
-/**
- * Do a pre-flight check that we are not in an uncommitted transaction.
- * If we are, try to commit the previous transaction and output a warning.
- * Does not return anything, as we will continue regardless of the outcome.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- */
-static void
-postgres_preflight (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute ("COMMIT"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-
-  if (NULL == pg->transaction_name)
-    return; /* all good */
-  if (GNUNET_OK ==
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "BUG: Preflight check committed transaction `%s'!\n",
-                pg->transaction_name);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "BUG: Preflight check failed to commit transaction `%s'!\n",
-                pg->transaction_name);
-  }
-  pg->transaction_name = NULL;
-}
-
-
-/**
- * Start a transaction.
+ * Initialize tables.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param name unique name identifying the transaction (for debugging),
- *             must point to a constant
- * @return #GNUNET_OK on success
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
-static int
-begin_transaction (void *cls,
-                   const char *name)
+static enum GNUNET_GenericReturnValue
+postgres_create_tables (void *cls)
 {
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
+  struct PostgresClosure *pc = cls;
+  struct GNUNET_PQ_Context *conn;
 
-  check_connection (pg);
-  postgres_preflight (pg);
-  pg->transaction_name = name;
-  if (GNUNET_OK !=
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    TALER_LOG_ERROR ("Failed to start transaction\n");
-    GNUNET_break (0);
+  conn = GNUNET_PQ_connect_with_cfg (pc->cfg,
+                                     "stasis-postgres",
+                                     "stasis-",
+                                     NULL,
+                                     NULL);
+  if (NULL == conn)
     return GNUNET_SYSERR;
-  }
+  GNUNET_PQ_disconnect (conn);
   return GNUNET_OK;
 }
 
 
 /**
-* Roll back the current transaction of a database connection.
-*
-* @param cls the `struct PostgresClosure` with the plugin-specific state
-* @return #GNUNET_OK on success
-*/
-static void
-rollback (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_ExecuteStatement es[] = {
-    GNUNET_PQ_make_execute ("ROLLBACK"),
-    GNUNET_PQ_EXECUTE_STATEMENT_END
-  };
-
-  if (GNUNET_OK !=
-      GNUNET_PQ_exec_statements (pg->conn,
-                                 es))
-  {
-    TALER_LOG_ERROR ("Failed to rollback transaction\n");
-    GNUNET_break (0);
-  }
-  pg->transaction_name = NULL;
-}
-
-
-/**
- * Commit the current transaction of a database connection.
- *
- * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @return transaction status code
- */
-static enum GNUNET_DB_QueryStatus
-commit_transaction (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_PQ_QueryParam no_params[] = {
-    GNUNET_PQ_query_param_end
-  };
-
-  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                           "do_commit",
-                                           no_params);
-  pg->transaction_name = NULL;
-  return qs;
-}
-
-
-/**
- * Register callback to be invoked on events of type @a es.
- *
- * @param cls database context to use
- * @param es specification of the event to listen for
- * @param timeout how long to wait for the event
- * @param cb function to call when the event happens, possibly
- *         multiple times (until cancel is invoked)
- * @param cb_cls closure for @a cb
- * @return handle useful to cancel the listener
- */
-static struct GNUNET_DB_EventHandler *
-postgres_event_listen (void *cls,
-                       const struct GNUNET_DB_EventHeaderP *es,
-                       struct GNUNET_TIME_Relative timeout,
-                       GNUNET_DB_EventCallback cb,
-                       void *cb_cls)
-{
-  struct PostgresClosure *pg = cls;
-
-  return GNUNET_PQ_event_listen (pg->conn,
-                                 es,
-                                 timeout,
-                                 cb,
-                                 cb_cls);
-}
-
-
-/**
- * Stop notifications.
- *
- * @param eh handle to unregister.
- */
-static void
-postgres_event_listen_cancel (struct GNUNET_DB_EventHandler *eh)
-{
-  GNUNET_PQ_event_listen_cancel (eh);
-}
-
-
-/**
- * Notify all that listen on @a es of an event.
- *
- * @param cls database context to use
- * @param es specification of the event to generate
- * @param extra additional event data provided
- * @param extra_size number of bytes in @a extra
- */
-static void
-postgres_event_notify (void *cls,
-                       const struct GNUNET_DB_EventHeaderP *es,
-                       const void *extra,
-                       size_t extra_size)
-{
-  struct PostgresClosure *pg = cls;
-
-  return GNUNET_PQ_event_notify (pg->conn,
-                                 es,
-                                 extra,
-                                 extra_size);
-}
-
-
-/**
- * Function called to perform "garbage collection" on the
- * database, expiring records we no longer require.  Deletes
- * all user records that are not paid up (and by cascade deletes
- * the associated recovery documents). Also deletes expired
- * truth and financial records older than @a fin_expire.
- *
- * @param cls closure
- * @param expire_backups backups older than the given time stamp should be 
garbage collected
- * @param expire_pending_payments payments still pending from since before
- *            this value should be garbage collected
- * @return transaction status
- */
-static enum GNUNET_DB_QueryStatus
-postgres_gc (void *cls,
-             struct GNUNET_TIME_Absolute expire_backups,
-             struct GNUNET_TIME_Absolute expire_pending_payments)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&expire_backups),
-    GNUNET_PQ_query_param_end
-  };
-  struct GNUNET_PQ_QueryParam params2[] = {
-    GNUNET_PQ_query_param_absolute_time (&expire_pending_payments),
-    GNUNET_PQ_query_param_end
-  };
-  enum GNUNET_DB_QueryStatus qs;
-
-  check_connection (pg);
-  postgres_preflight (pg);
-  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                           "gc_accounts",
-                                           params);
-  if (qs < 0)
-    return qs;
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "gc_recdoc_pending_payments",
-                                             params2);
-}
-
-
-/**
- * Store encrypted recovery document.
+ * Establish connection to the database.
  *
- * @param cls closure
- * @param account_pub public key of the user's account
- * @param account_sig signature affirming storage request
- * @param recovery_data_hash hash of @a data
- * @param recovery_data contains encrypted_recovery_document
- * @param recovery_data_size size of data blob
- * @param payment_secret identifier for the payment, used to later charge on 
uploads
- * @param[out] version set to the version assigned to the document by the 
database
- * @return transaction status, 0 if upload could not be finished because @a 
payment_secret
- *         did not have enough upload left; HARD error if @a payment_secret is 
unknown, ...
+ * @param cls plugin context
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
-static enum ANASTASIS_DB_StoreStatus
-postgres_store_recovery_document (
-  void *cls,
-  const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub,
-  const struct ANASTASIS_AccountSignatureP *account_sig,
-  const struct GNUNET_HashCode *recovery_data_hash,
-  const void *recovery_data,
-  size_t recovery_data_size,
-  const struct ANASTASIS_PaymentSecretP *payment_secret,
-  uint32_t *version)
+static enum GNUNET_GenericReturnValue
+postgres_connect (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_PreparedStatement ps[] = {
+    GNUNET_PQ_make_prepare ("user_insert",
+                            "INSERT INTO anastasis_user "
+                            "(user_id"
+                            ",expiration_date"
+                            ") VALUES "
+                            "($1, $2);",
+                            2),
+    GNUNET_PQ_make_prepare ("do_commit",
+                            "COMMIT",
+                            0),
+    GNUNET_PQ_make_prepare ("user_select",
+                            "SELECT"
+                            " expiration_date "
+                            "FROM anastasis_user"
+                            " WHERE user_id=$1"
+                            " FOR UPDATE;",
+                            1),
+    GNUNET_PQ_make_prepare ("user_update",
+                            "UPDATE anastasis_user"
+                            " SET "
+                            " expiration_date=$1"
+                            " WHERE user_id=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("recdoc_payment_insert",
+                            "INSERT INTO anastasis_recdoc_payment "
+                            "(user_id"
+                            ",post_counter"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",payment_identifier"
+                            ",creation_date"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5, $6);",
+                            6),
+    GNUNET_PQ_make_prepare ("challenge_payment_insert",
+                            "INSERT INTO anastasis_challenge_payment "
+                            "(truth_uuid"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",payment_identifier"
+                            ",creation_date"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5);",
+                            5),
+    GNUNET_PQ_make_prepare ("truth_payment_insert",
+                            "INSERT INTO anastasis_truth_payment "
+                            "(truth_uuid"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",expiration"
+                            ") VALUES "
+                            "($1, $2, $3, $4);",
+                            4),
+    GNUNET_PQ_make_prepare ("recdoc_payment_done",
+                            "UPDATE anastasis_recdoc_payment "
+                            "SET"
+                            " paid=TRUE "
+                            "WHERE"
+                            "  payment_identifier=$1"
+                            " AND"
+                            "  user_id=$2"
+                            " AND"
+                            "  paid=FALSE;",
+                            2),
+    GNUNET_PQ_make_prepare ("challenge_refund_update",
+                            "UPDATE anastasis_challenge_payment "
+                            "SET"
+                            " refunded=TRUE "
+                            "WHERE"
+                            "  payment_identifier=$1"
+                            " AND"
+                            "  paid=TRUE"
+                            " AND"
+                            "  truth_uuid=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("challenge_payment_done",
+                            "UPDATE anastasis_challenge_payment "
+                            "SET"
+                            " paid=TRUE "
+                            "WHERE"
+                            "  payment_identifier=$1"
+                            " AND"
+                            "  refunded=FALSE"
+                            " AND"
+                            "  truth_uuid=$2"
+                            " AND"
+                            "  paid=FALSE;",
+                            2),
+    GNUNET_PQ_make_prepare ("recdoc_payment_select",
+                            "SELECT"
+                            " creation_date"
+                            ",post_counter"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",paid"
+                            " FROM anastasis_recdoc_payment"
+                            " WHERE payment_identifier=$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("truth_payment_select",
+                            "SELECT"
+                            " expiration"
+                            " FROM anastasis_truth_payment"
+                            " WHERE truth_uuid=$1"
+                            "   AND expiration>$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("challenge_payment_select",
+                            "SELECT"
+                            " creation_date"
+                            ",amount_val"
+                            ",amount_frac"
+                            ",paid"
+                            " FROM anastasis_challenge_payment"
+                            " WHERE payment_identifier=$1"
+                            "   AND truth_uuid=$2"
+                            "   AND refunded=FALSE"
+                            "   AND counter>0;",
+                            1),
+    GNUNET_PQ_make_prepare ("challenge_pending_payment_select",
+                            "SELECT"
+                            " creation_date"
+                            ",payment_identifier"
+                            ",amount_val"
+                            ",amount_frac"
+                            " FROM anastasis_challenge_payment"
+                            " WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  refunded=FALSE"
+                            " AND"
+                            "  truth_uuid=$1"
+                            " AND"
+                            "  creation_date > $2;",
+                            1),
+    GNUNET_PQ_make_prepare ("recdoc_payments_select",
+                            "SELECT"
+                            " user_id"
+                            ",payment_identifier"
+                            ",amount_val"
+                            ",amount_frac"
+                            " FROM anastasis_recdoc_payment"
+                            " WHERE paid=FALSE;",
+                            0),
+    GNUNET_PQ_make_prepare ("gc_accounts",
+                            "DELETE FROM anastasis_user "
+                            "WHERE"
+                            " expiration_date < $1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_recdoc_pending_payments",
+                            "DELETE FROM anastasis_recdoc_payment "
+                            "WHERE"
+                            "  paid=FALSE"
+                            " AND"
+                            "  creation_date < $1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_challenge_pending_payments",
+                            "DELETE FROM anastasis_challenge_payment "
+                            "WHERE"
+                            "  (paid=FALSE"
+                            "   OR"
+                            "   refunded=TRUE)"
+                            " AND"
+                            "  creation_date < $1;",
+                            1),
+    GNUNET_PQ_make_prepare ("truth_insert",
+                            "INSERT INTO anastasis_truth "
+                            "(truth_uuid"
+                            ",key_share_data"
+                            ",method_name"
+                            ",encrypted_truth"
+                            ",truth_mime"
+                            ",expiration"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5, $6);",
+                            6),
+
+    GNUNET_PQ_make_prepare ("test_auth_iban_payment",
+                            "SELECT"
+                            " credit_val"
+                            ",credit_frac"
+                            ",wire_subject"
+                            " FROM anastasis_auth_iban_in"
+                            " WHERE debit_account_details=$1"
+                            "  AND execution_date>=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("store_auth_iban_payment_details",
+                            "INSERT INTO anastasis_auth_iban_in "
+                            "(wire_reference"
+                            ",wire_subject"
+                            ",credit_val"
+                            ",credit_frac"
+                            ",debit_account_details"
+                            ",credit_account_details"
+                            ",execution_date"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5, $6, $7);",
+                            7),
+
+
+    GNUNET_PQ_make_prepare ("recovery_document_insert",
+                            "INSERT INTO anastasis_recoverydocument "
+                            "(user_id"
+                            ",version"
+                            ",account_sig"
+                            ",recovery_data_hash"
+                            ",recovery_data"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5);",
+                            5),
+    GNUNET_PQ_make_prepare ("truth_select",
+                            "SELECT "
+                            " method_name"
+                            ",encrypted_truth"
+                            ",truth_mime"
+                            " FROM anastasis_truth"
+                            " WHERE truth_uuid =$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("latest_recoverydocument_select",
+                            "SELECT "
+                            " version"
+                            ",account_sig"
+                            ",recovery_data_hash"
+                            ",recovery_data"
+                            " FROM anastasis_recoverydocument"
+                            " WHERE user_id =$1 "
+                            " ORDER BY version DESC"
+                            " LIMIT 1;",
+                            1),
+    GNUNET_PQ_make_prepare ("latest_recovery_version_select",
+                            "SELECT"
+                            " version"
+                            ",recovery_data_hash"
+                            ",expiration_date"
+                            " FROM anastasis_recoverydocument"
+                            " JOIN anastasis_user USING (user_id)"
+                            " WHERE user_id=$1"
+                            " ORDER BY version DESC"
+                            " LIMIT 1;",
+                            1),
+    GNUNET_PQ_make_prepare ("recoverydocument_select",
+                            "SELECT "
+                            " account_sig"
+                            ",recovery_data_hash"
+                            ",recovery_data"
+                            " FROM anastasis_recoverydocument"
+                            " WHERE user_id=$1"
+                            " AND version=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("postcounter_select",
+                            "SELECT"
+                            " post_counter"
+                            " FROM anastasis_recdoc_payment"
+                            " WHERE user_id=$1"
+                            "  AND payment_identifier=$2;",
+                            2),
+    GNUNET_PQ_make_prepare ("postcounter_update",
+                            "UPDATE "
+                            "anastasis_recdoc_payment "
+                            "SET "
+                            "post_counter=$1 "
+                            "WHERE user_id =$2 "
+                            "AND payment_identifier=$3;",
+                            3),
+    GNUNET_PQ_make_prepare ("key_share_select",
+                            "SELECT "
+                            "key_share_data "
+                            "FROM "
+                            "anastasis_truth "
+                            "WHERE truth_uuid =$1;",
+                            1),
+    GNUNET_PQ_make_prepare ("challengecode_insert",
+                            "INSERT INTO anastasis_challengecode "
+                            "(truth_uuid"
+                            ",code"
+                            ",creation_date"
+                            ",expiration_date"
+                            ",retry_counter"
+                            ") VALUES "
+                            "($1, $2, $3, $4, $5);",
+                            5),
+    GNUNET_PQ_make_prepare ("challengecode_select",
+                            "SELECT "
+                            " code"
+                            ",satisfied"
+                            " FROM anastasis_challengecode"
+                            " WHERE truth_uuid=$1"
+                            "   AND expiration_date > $2"
+                            "   AND retry_counter != 0;",
+                            2),
+    GNUNET_PQ_make_prepare ("challengecode_set_satisfied",
+                            "UPDATE anastasis_challengecode"
+                            " SET satisfied=TRUE"
+                            " WHERE truth_uuid=$1"
+                            "   AND code=$2"
+                            "   AND creation_date IN"
+                            " (SELECT creation_date"
+                            "    FROM anastasis_challengecode"
+                            "   WHERE truth_uuid=$1"
+                            "     AND code=$2"
+                            "    ORDER BY creation_date DESC"
+                            "     LIMIT 1);",
+                            2),
+    GNUNET_PQ_make_prepare ("challengecode_test_satisfied",
+                            "SELECT 1 FROM anastasis_challengecode"
+                            " WHERE truth_uuid=$1"
+                            "   AND satisfied=TRUE"
+                            "   AND code=$2"
+                            "   AND creation_date >= $3"
+                            " LIMIT 1;",
+                            3),
+    GNUNET_PQ_make_prepare ("challengecode_select_meta",
+                            "SELECT "
+                            " code"
+                            ",retry_counter"
+                            ",retransmission_date"
+                            " FROM anastasis_challengecode"
+                            " WHERE truth_uuid=$1"
+                            "   AND expiration_date > $2"
+                            "   AND creation_date > $3"
+                            " ORDER BY creation_date DESC"
+                            " LIMIT 1;",
+                            2),
+    GNUNET_PQ_make_prepare ("challengecode_update_retry",
+                            "UPDATE anastasis_challengecode"
+                            " SET retry_counter=retry_counter - 1"
+                            " WHERE truth_uuid=$1"
+                            "   AND code=$2"
+                            "   AND retry_counter != 0;",
+                            1),
+    GNUNET_PQ_make_prepare ("challengepayment_dec_counter",
+                            "UPDATE anastasis_challenge_payment"
+                            " SET counter=counter - 1"
+                            " WHERE truth_uuid=$1"
+                            "   AND payment_identifier=$2"
+                            "   AND counter > 0;",
+                            2),
+    GNUNET_PQ_make_prepare ("challengecode_mark_sent",
+                            "UPDATE anastasis_challengecode"
+                            " SET retransmission_date=$3"
+                            " WHERE truth_uuid=$1"
+                            "   AND code=$2"
+                            "   AND creation_date IN"
+                            " (SELECT creation_date"
+                            "    FROM anastasis_challengecode"
+                            "   WHERE truth_uuid=$1"
+                            "     AND code=$2"
+                            "    ORDER BY creation_date DESC"
+                            "     LIMIT 1);",
+                            3),
+    GNUNET_PQ_make_prepare ("get_last_auth_iban_payment",
+                            "SELECT "
+                            " wire_reference"
+                            " FROM anastasis_auth_iban_in"
+                            " WHERE credit_account_details=$1"
+                            " ORDER BY wire_reference DESC"
+                            " LIMIT 1;",
+                            1),
+    GNUNET_PQ_make_prepare ("gc_challengecodes",
+                            "DELETE FROM anastasis_challengecode "
+                            "WHERE "
+                            "expiration_date < $1;",
+                            1),
+    GNUNET_PQ_PREPARED_STATEMENT_END
+  };
+
+  pg->conn = GNUNET_PQ_connect_with_cfg (pg->cfg,
+                                         "stasis-postgres",
+                                         NULL,
+                                         NULL,
+                                         ps);
+  if (NULL == pg->conn)
+    return GNUNET_SYSERR;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Check that the database connection is still up.
+ *
+ * @param cls a `struct PostgresClosure` with connection to check
+ */
+static void
+check_connection (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+
+  GNUNET_PQ_reconnect_if_down (pg->conn);
+}
+
+
+/**
+ * Do a pre-flight check that we are not in an uncommitted transaction.
+ * If we are, try to commit the previous transaction and output a warning.
+ * Does not return anything, as we will continue regardless of the outcome.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ */
+static void
+postgres_preflight (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("COMMIT"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  if (NULL == pg->transaction_name)
+    return; /* all good */
+  if (GNUNET_OK ==
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "BUG: Preflight check committed transaction `%s'!\n",
+                pg->transaction_name);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "BUG: Preflight check failed to commit transaction `%s'!\n",
+                pg->transaction_name);
+  }
+  pg->transaction_name = NULL;
+}
+
+
+/**
+ * Start a transaction.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @param name unique name identifying the transaction (for debugging),
+ *             must point to a constant
+ * @return #GNUNET_OK on success
+ */
+static int
+begin_transaction (void *cls,
+                   const char *name)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("START TRANSACTION ISOLATION LEVEL SERIALIZABLE"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  check_connection (pg);
+  postgres_preflight (pg);
+  pg->transaction_name = name;
+  if (GNUNET_OK !=
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    TALER_LOG_ERROR ("Failed to start transaction\n");
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+* Roll back the current transaction of a database connection.
+*
+* @param cls the `struct PostgresClosure` with the plugin-specific state
+* @return #GNUNET_OK on success
+*/
+static void
+rollback (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_ExecuteStatement es[] = {
+    GNUNET_PQ_make_execute ("ROLLBACK"),
+    GNUNET_PQ_EXECUTE_STATEMENT_END
+  };
+
+  if (GNUNET_OK !=
+      GNUNET_PQ_exec_statements (pg->conn,
+                                 es))
+  {
+    TALER_LOG_ERROR ("Failed to rollback transaction\n");
+    GNUNET_break (0);
+  }
+  pg->transaction_name = NULL;
+}
+
+
+/**
+ * Commit the current transaction of a database connection.
+ *
+ * @param cls the `struct PostgresClosure` with the plugin-specific state
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+commit_transaction (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam no_params[] = {
+    GNUNET_PQ_query_param_end
+  };
+
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "do_commit",
+                                           no_params);
+  pg->transaction_name = NULL;
+  return qs;
+}
+
+
+/**
+ * Register callback to be invoked on events of type @a es.
+ *
+ * @param cls database context to use
+ * @param es specification of the event to listen for
+ * @param timeout how long to wait for the event
+ * @param cb function to call when the event happens, possibly
+ *         multiple times (until cancel is invoked)
+ * @param cb_cls closure for @a cb
+ * @return handle useful to cancel the listener
+ */
+static struct GNUNET_DB_EventHandler *
+postgres_event_listen (void *cls,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       struct GNUNET_TIME_Relative timeout,
+                       GNUNET_DB_EventCallback cb,
+                       void *cb_cls)
+{
+  struct PostgresClosure *pg = cls;
+
+  return GNUNET_PQ_event_listen (pg->conn,
+                                 es,
+                                 timeout,
+                                 cb,
+                                 cb_cls);
+}
+
+
+/**
+ * Stop notifications.
+ *
+ * @param eh handle to unregister.
+ */
+static void
+postgres_event_listen_cancel (struct GNUNET_DB_EventHandler *eh)
+{
+  GNUNET_PQ_event_listen_cancel (eh);
+}
+
+
+/**
+ * Notify all that listen on @a es of an event.
+ *
+ * @param cls database context to use
+ * @param es specification of the event to generate
+ * @param extra additional event data provided
+ * @param extra_size number of bytes in @a extra
+ */
+static void
+postgres_event_notify (void *cls,
+                       const struct GNUNET_DB_EventHeaderP *es,
+                       const void *extra,
+                       size_t extra_size)
+{
+  struct PostgresClosure *pg = cls;
+
+  return GNUNET_PQ_event_notify (pg->conn,
+                                 es,
+                                 extra,
+                                 extra_size);
+}
+
+
+/**
+ * Function called to perform "garbage collection" on the
+ * database, expiring records we no longer require.  Deletes
+ * all user records that are not paid up (and by cascade deletes
+ * the associated recovery documents). Also deletes expired
+ * truth and financial records older than @a fin_expire.
+ *
+ * @param cls closure
+ * @param expire_backups backups older than the given time stamp should be 
garbage collected
+ * @param expire_pending_payments payments still pending from since before
+ *            this value should be garbage collected
+ * @return transaction status
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_gc (void *cls,
+             struct GNUNET_TIME_Absolute expire_backups,
+             struct GNUNET_TIME_Absolute expire_pending_payments)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&expire_backups),
+    GNUNET_PQ_query_param_end
+  };
+  struct GNUNET_PQ_QueryParam params2[] = {
+    GNUNET_PQ_query_param_absolute_time (&expire_pending_payments),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
+
+  check_connection (pg);
+  postgres_preflight (pg);
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "gc_accounts",
+                                           params);
+  if (qs < 0)
+    return qs;
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "gc_recdoc_pending_payments",
+                                             params2);
+}
+
+
+/**
+ * Store encrypted recovery document.
+ *
+ * @param cls closure
+ * @param account_pub public key of the user's account
+ * @param account_sig signature affirming storage request
+ * @param recovery_data_hash hash of @a data
+ * @param recovery_data contains encrypted_recovery_document
+ * @param recovery_data_size size of data blob
+ * @param payment_secret identifier for the payment, used to later charge on 
uploads
+ * @param[out] version set to the version assigned to the document by the 
database
+ * @return transaction status, 0 if upload could not be finished because @a 
payment_secret
+ *         did not have enough upload left; HARD error if @a payment_secret is 
unknown, ...
+ */
+static enum ANASTASIS_DB_StoreStatus
+postgres_store_recovery_document (
+  void *cls,
+  const struct ANASTASIS_CRYPTO_AccountPublicKeyP *account_pub,
+  const struct ANASTASIS_AccountSignatureP *account_sig,
+  const struct GNUNET_HashCode *recovery_data_hash,
+  const void *recovery_data,
+  size_t recovery_data_size,
+  const struct ANASTASIS_PaymentSecretP *payment_secret,
+  uint32_t *version)
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus qs;
@@ -2214,450 +2624,76 @@ postgres_mark_challenge_sent (
   check_connection (pg);
   {
     struct GNUNET_TIME_Absolute now;
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_uuid),
-      GNUNET_PQ_query_param_uint64 (&code),
-      TALER_PQ_query_param_absolute_time (&now),
-      GNUNET_PQ_query_param_end
-    };
-
-    now = GNUNET_TIME_absolute_get ();
-    GNUNET_TIME_round_abs (&now);
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "challengecode_mark_sent",
-                                             params);
-    if (qs <= 0)
-      return qs;
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_uuid),
-      GNUNET_PQ_query_param_auto_from_type (payment_secret),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "challengepayment_dec_counter",
-                                             params);
-    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
-      return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* probably was free */
-    return qs;
-  }
-}
-
-
-/**
- * Function called to remove all expired codes from the database.
- *
- * @return transaction status
- */
-enum GNUNET_DB_QueryStatus
-postgres_challenge_gc (void *cls)
-{
-  struct PostgresClosure *pg = cls;
-  struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get ();
-  struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_absolute_time (&time_now),
-    GNUNET_PQ_query_param_end
-  };
-
-  check_connection (pg);
-  postgres_preflight (pg);
-  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "gc_challengecodes",
-                                             params);
-}
-
-
-/**
- * Initialize Postgres database subsystem.
- *
- * @param cls a configuration instance
- * @return NULL on error, otherwise a `struct TALER_ANASTASISDB_Plugin`
- */
-void *
-libanastasis_plugin_db_postgres_init (void *cls)
-{
-  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct PostgresClosure *pg;
-  struct ANASTASIS_DatabasePlugin *plugin;
-  struct GNUNET_PQ_PreparedStatement ps[] = {
-    GNUNET_PQ_make_prepare ("user_insert",
-                            "INSERT INTO anastasis_user "
-                            "(user_id"
-                            ",expiration_date"
-                            ") VALUES "
-                            "($1, $2);",
-                            2),
-    GNUNET_PQ_make_prepare ("do_commit",
-                            "COMMIT",
-                            0),
-    GNUNET_PQ_make_prepare ("user_select",
-                            "SELECT"
-                            " expiration_date "
-                            "FROM anastasis_user"
-                            " WHERE user_id=$1"
-                            " FOR UPDATE;",
-                            1),
-    GNUNET_PQ_make_prepare ("user_update",
-                            "UPDATE anastasis_user"
-                            " SET "
-                            " expiration_date=$1"
-                            " WHERE user_id=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("recdoc_payment_insert",
-                            "INSERT INTO anastasis_recdoc_payment "
-                            "(user_id"
-                            ",post_counter"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",payment_identifier"
-                            ",creation_date"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
-    GNUNET_PQ_make_prepare ("challenge_payment_insert",
-                            "INSERT INTO anastasis_challenge_payment "
-                            "(truth_uuid"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",payment_identifier"
-                            ",creation_date"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5);",
-                            5),
-    GNUNET_PQ_make_prepare ("truth_payment_insert",
-                            "INSERT INTO anastasis_truth_payment "
-                            "(truth_uuid"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",expiration"
-                            ") VALUES "
-                            "($1, $2, $3, $4);",
-                            4),
-    GNUNET_PQ_make_prepare ("recdoc_payment_done",
-                            "UPDATE anastasis_recdoc_payment "
-                            "SET"
-                            " paid=TRUE "
-                            "WHERE"
-                            "  payment_identifier=$1"
-                            " AND"
-                            "  user_id=$2"
-                            " AND"
-                            "  paid=FALSE;",
-                            2),
-    GNUNET_PQ_make_prepare ("challenge_refund_update",
-                            "UPDATE anastasis_challenge_payment "
-                            "SET"
-                            " refunded=TRUE "
-                            "WHERE"
-                            "  payment_identifier=$1"
-                            " AND"
-                            "  paid=TRUE"
-                            " AND"
-                            "  truth_uuid=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("challenge_payment_done",
-                            "UPDATE anastasis_challenge_payment "
-                            "SET"
-                            " paid=TRUE "
-                            "WHERE"
-                            "  payment_identifier=$1"
-                            " AND"
-                            "  refunded=FALSE"
-                            " AND"
-                            "  truth_uuid=$2"
-                            " AND"
-                            "  paid=FALSE;",
-                            2),
-    GNUNET_PQ_make_prepare ("recdoc_payment_select",
-                            "SELECT"
-                            " creation_date"
-                            ",post_counter"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",paid"
-                            " FROM anastasis_recdoc_payment"
-                            " WHERE payment_identifier=$1;",
-                            1),
-    GNUNET_PQ_make_prepare ("truth_payment_select",
-                            "SELECT"
-                            " expiration"
-                            " FROM anastasis_truth_payment"
-                            " WHERE truth_uuid=$1"
-                            "   AND expiration>$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("challenge_payment_select",
-                            "SELECT"
-                            " creation_date"
-                            ",amount_val"
-                            ",amount_frac"
-                            ",paid"
-                            " FROM anastasis_challenge_payment"
-                            " WHERE payment_identifier=$1"
-                            "   AND truth_uuid=$2"
-                            "   AND refunded=FALSE"
-                            "   AND counter>0;",
-                            1),
-    GNUNET_PQ_make_prepare ("challenge_pending_payment_select",
-                            "SELECT"
-                            " creation_date"
-                            ",payment_identifier"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM anastasis_challenge_payment"
-                            " WHERE"
-                            "  paid=FALSE"
-                            " AND"
-                            "  refunded=FALSE"
-                            " AND"
-                            "  truth_uuid=$1"
-                            " AND"
-                            "  creation_date > $2;",
-                            1),
-    GNUNET_PQ_make_prepare ("recdoc_payments_select",
-                            "SELECT"
-                            " user_id"
-                            ",payment_identifier"
-                            ",amount_val"
-                            ",amount_frac"
-                            " FROM anastasis_recdoc_payment"
-                            " WHERE paid=FALSE;",
-                            0),
-    GNUNET_PQ_make_prepare ("gc_accounts",
-                            "DELETE FROM anastasis_user "
-                            "WHERE"
-                            " expiration_date < $1;",
-                            1),
-    GNUNET_PQ_make_prepare ("gc_recdoc_pending_payments",
-                            "DELETE FROM anastasis_recdoc_payment "
-                            "WHERE"
-                            "  paid=FALSE"
-                            " AND"
-                            "  creation_date < $1;",
-                            1),
-    GNUNET_PQ_make_prepare ("gc_challenge_pending_payments",
-                            "DELETE FROM anastasis_challenge_payment "
-                            "WHERE"
-                            "  (paid=FALSE"
-                            "   OR"
-                            "   refunded=TRUE)"
-                            " AND"
-                            "  creation_date < $1;",
-                            1),
-    GNUNET_PQ_make_prepare ("truth_insert",
-                            "INSERT INTO anastasis_truth "
-                            "(truth_uuid"
-                            ",key_share_data"
-                            ",method_name"
-                            ",encrypted_truth"
-                            ",truth_mime"
-                            ",expiration"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6);",
-                            6),
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (truth_uuid),
+      GNUNET_PQ_query_param_uint64 (&code),
+      TALER_PQ_query_param_absolute_time (&now),
+      GNUNET_PQ_query_param_end
+    };
 
-    GNUNET_PQ_make_prepare ("test_auth_iban_payment",
-                            "SELECT"
-                            " credit_val"
-                            ",credit_frac"
-                            ",wire_subject"
-                            " FROM anastasis_auth_iban_in"
-                            " WHERE debit_account_details=$1"
-                            "  AND execution_date>=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("store_auth_iban_payment_details",
-                            "INSERT INTO anastasis_auth_iban_in "
-                            "(wire_reference"
-                            ",wire_subject"
-                            ",credit_val"
-                            ",credit_frac"
-                            ",debit_account_details"
-                            ",credit_account_details"
-                            ",execution_date"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5, $6, $7);",
-                            7),
+    now = GNUNET_TIME_absolute_get ();
+    GNUNET_TIME_round_abs (&now);
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "challengecode_mark_sent",
+                                             params);
+    if (qs <= 0)
+      return qs;
+  }
+  {
+    struct GNUNET_PQ_QueryParam params[] = {
+      GNUNET_PQ_query_param_auto_from_type (truth_uuid),
+      GNUNET_PQ_query_param_auto_from_type (payment_secret),
+      GNUNET_PQ_query_param_end
+    };
 
+    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "challengepayment_dec_counter",
+                                             params);
+    if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
+      return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* probably was free */
+    return qs;
+  }
+}
 
-    GNUNET_PQ_make_prepare ("recovery_document_insert",
-                            "INSERT INTO anastasis_recoverydocument "
-                            "(user_id"
-                            ",version"
-                            ",account_sig"
-                            ",recovery_data_hash"
-                            ",recovery_data"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5);",
-                            5),
-    GNUNET_PQ_make_prepare ("truth_select",
-                            "SELECT "
-                            " method_name"
-                            ",encrypted_truth"
-                            ",truth_mime"
-                            " FROM anastasis_truth"
-                            " WHERE truth_uuid =$1;",
-                            1),
-    GNUNET_PQ_make_prepare ("latest_recoverydocument_select",
-                            "SELECT "
-                            " version"
-                            ",account_sig"
-                            ",recovery_data_hash"
-                            ",recovery_data"
-                            " FROM anastasis_recoverydocument"
-                            " WHERE user_id =$1 "
-                            " ORDER BY version DESC"
-                            " LIMIT 1;",
-                            1),
-    GNUNET_PQ_make_prepare ("latest_recovery_version_select",
-                            "SELECT"
-                            " version"
-                            ",recovery_data_hash"
-                            ",expiration_date"
-                            " FROM anastasis_recoverydocument"
-                            " JOIN anastasis_user USING (user_id)"
-                            " WHERE user_id=$1"
-                            " ORDER BY version DESC"
-                            " LIMIT 1;",
-                            1),
-    GNUNET_PQ_make_prepare ("recoverydocument_select",
-                            "SELECT "
-                            " account_sig"
-                            ",recovery_data_hash"
-                            ",recovery_data"
-                            " FROM anastasis_recoverydocument"
-                            " WHERE user_id=$1"
-                            " AND version=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("postcounter_select",
-                            "SELECT"
-                            " post_counter"
-                            " FROM anastasis_recdoc_payment"
-                            " WHERE user_id=$1"
-                            "  AND payment_identifier=$2;",
-                            2),
-    GNUNET_PQ_make_prepare ("postcounter_update",
-                            "UPDATE "
-                            "anastasis_recdoc_payment "
-                            "SET "
-                            "post_counter=$1 "
-                            "WHERE user_id =$2 "
-                            "AND payment_identifier=$3;",
-                            3),
-    GNUNET_PQ_make_prepare ("key_share_select",
-                            "SELECT "
-                            "key_share_data "
-                            "FROM "
-                            "anastasis_truth "
-                            "WHERE truth_uuid =$1;",
-                            1),
-    GNUNET_PQ_make_prepare ("challengecode_insert",
-                            "INSERT INTO anastasis_challengecode "
-                            "(truth_uuid"
-                            ",code"
-                            ",creation_date"
-                            ",expiration_date"
-                            ",retry_counter"
-                            ") VALUES "
-                            "($1, $2, $3, $4, $5);",
-                            5),
-    GNUNET_PQ_make_prepare ("challengecode_select",
-                            "SELECT "
-                            " code"
-                            ",satisfied"
-                            " FROM anastasis_challengecode"
-                            " WHERE truth_uuid=$1"
-                            "   AND expiration_date > $2"
-                            "   AND retry_counter != 0;",
-                            2),
-    GNUNET_PQ_make_prepare ("challengecode_set_satisfied",
-                            "UPDATE anastasis_challengecode"
-                            " SET satisfied=TRUE"
-                            " WHERE truth_uuid=$1"
-                            "   AND code=$2"
-                            "   AND creation_date IN"
-                            " (SELECT creation_date"
-                            "    FROM anastasis_challengecode"
-                            "   WHERE truth_uuid=$1"
-                            "     AND code=$2"
-                            "    ORDER BY creation_date DESC"
-                            "     LIMIT 1);",
-                            2),
-    GNUNET_PQ_make_prepare ("challengecode_test_satisfied",
-                            "SELECT 1 FROM anastasis_challengecode"
-                            " WHERE truth_uuid=$1"
-                            "   AND satisfied=TRUE"
-                            "   AND code=$2"
-                            "   AND creation_date >= $3"
-                            " LIMIT 1;",
-                            3),
-    GNUNET_PQ_make_prepare ("challengecode_select_meta",
-                            "SELECT "
-                            " code"
-                            ",retry_counter"
-                            ",retransmission_date"
-                            " FROM anastasis_challengecode"
-                            " WHERE truth_uuid=$1"
-                            "   AND expiration_date > $2"
-                            "   AND creation_date > $3"
-                            " ORDER BY creation_date DESC"
-                            " LIMIT 1;",
-                            2),
-    GNUNET_PQ_make_prepare ("challengecode_update_retry",
-                            "UPDATE anastasis_challengecode"
-                            " SET retry_counter=retry_counter - 1"
-                            " WHERE truth_uuid=$1"
-                            "   AND code=$2"
-                            "   AND retry_counter != 0;",
-                            1),
-    GNUNET_PQ_make_prepare ("challengepayment_dec_counter",
-                            "UPDATE anastasis_challenge_payment"
-                            " SET counter=counter - 1"
-                            " WHERE truth_uuid=$1"
-                            "   AND payment_identifier=$2"
-                            "   AND counter > 0;",
-                            2),
-    GNUNET_PQ_make_prepare ("challengecode_mark_sent",
-                            "UPDATE anastasis_challengecode"
-                            " SET retransmission_date=$3"
-                            " WHERE truth_uuid=$1"
-                            "   AND code=$2"
-                            "   AND creation_date IN"
-                            " (SELECT creation_date"
-                            "    FROM anastasis_challengecode"
-                            "   WHERE truth_uuid=$1"
-                            "     AND code=$2"
-                            "    ORDER BY creation_date DESC"
-                            "     LIMIT 1);",
-                            3),
-    GNUNET_PQ_make_prepare ("get_last_auth_iban_payment",
-                            "SELECT "
-                            " wire_reference"
-                            " FROM anastasis_auth_iban_in"
-                            " WHERE credit_account_details=$1"
-                            " ORDER BY wire_reference DESC"
-                            " LIMIT 1;",
-                            1),
-    GNUNET_PQ_make_prepare ("gc_challengecodes",
-                            "DELETE FROM anastasis_challengecode "
-                            "WHERE "
-                            "expiration_date < $1;",
-                            1),
-    GNUNET_PQ_PREPARED_STATEMENT_END
+
+/**
+ * Function called to remove all expired codes from the database.
+ *
+ * @return transaction status
+ */
+enum GNUNET_DB_QueryStatus
+postgres_challenge_gc (void *cls)
+{
+  struct PostgresClosure *pg = cls;
+  struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_absolute_time (&time_now),
+    GNUNET_PQ_query_param_end
   };
 
+  check_connection (pg);
+  postgres_preflight (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "gc_challengecodes",
+                                             params);
+}
+
+
+/**
+ * Initialize Postgres database subsystem.
+ *
+ * @param cls a configuration instance
+ * @return NULL on error, otherwise a `struct TALER_ANASTASISDB_Plugin`
+ */
+void *
+libanastasis_plugin_db_postgres_init (void *cls)
+{
+  struct GNUNET_CONFIGURATION_Handle *cfg = cls;
+  struct PostgresClosure *pg;
+  struct ANASTASIS_DatabasePlugin *plugin;
+
   pg = GNUNET_new (struct PostgresClosure);
   pg->cfg = cfg;
-  pg->conn = GNUNET_PQ_connect_with_cfg (cfg,
-                                         "stasis-postgres",
-                                         "stasis-",
-                                         NULL,
-                                         ps);
-  if (NULL == pg->conn)
-  {
-    GNUNET_free (pg);
-    return NULL;
-  }
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
                                              "taler",
@@ -2673,6 +2709,8 @@ libanastasis_plugin_db_postgres_init (void *cls)
   }
   plugin = GNUNET_new (struct ANASTASIS_DatabasePlugin);
   plugin->cls = pg;
+  plugin->connect = &postgres_connect;
+  plugin->create_tables = &postgres_create_tables;
   plugin->drop_tables = &postgres_drop_tables;
   plugin->gc = &postgres_gc;
   plugin->preflight = &postgres_preflight;
diff --git a/src/stasis/test_anastasis_db.c b/src/stasis/test_anastasis_db.c
index 204307a..1ec9770 100644
--- a/src/stasis/test_anastasis_db.c
+++ b/src/stasis/test_anastasis_db.c
@@ -92,15 +92,15 @@ run (void *cls)
     result = 77;
     return;
   }
-  if (GNUNET_OK != plugin->drop_tables (plugin->cls))
+  (void) plugin->drop_tables (plugin->cls);
+  if (GNUNET_OK !=
+      plugin->create_tables (plugin->cls))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Dropping tables failed\n");
     result = 77;
     return;
   }
-  ANASTASIS_DB_plugin_unload (plugin);
-  if (NULL == (plugin = ANASTASIS_DB_plugin_load (cfg)))
+  if (GNUNET_OK !=
+      plugin->connect (plugin->cls))
   {
     result = 77;
     return;

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

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