gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: make stasis plugin sane (transa


From: gnunet
Subject: [taler-anastasis] branch master updated: make stasis plugin sane (transaction retries, status codes, eliminate enum confusion, remove redundant DB queries
Date: Sun, 07 Feb 2021 16:44:40 +0100

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 26016a1  make stasis plugin sane (transaction retries, status codes, 
eliminate enum confusion, remove redundant DB queries
26016a1 is described below

commit 26016a1c20105c9dc985e468304692d4b68f6f13
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Feb 7 16:44:37 2021 +0100

    make stasis plugin sane (transaction retries, status codes, eliminate enum 
confusion, remove redundant DB queries
---
 src/include/anastasis_database_lib.h    |   54 --
 src/include/anastasis_database_plugin.h |  574 ++++++++------
 src/stasis/plugin_anastasis_postgres.c  | 1313 ++++++++++++-------------------
 src/stasis/test_anastasis_db.c          |  106 ++-
 4 files changed, 908 insertions(+), 1139 deletions(-)

diff --git a/src/include/anastasis_database_lib.h 
b/src/include/anastasis_database_lib.h
index f7bfc8d..4b33ea8 100644
--- a/src/include/anastasis_database_lib.h
+++ b/src/include/anastasis_database_lib.h
@@ -43,60 +43,6 @@ ANASTASIS_DB_plugin_load (const struct 
GNUNET_CONFIGURATION_Handle *cfg);
 void
 ANASTASIS_DB_plugin_unload (struct ANASTASIS_DatabasePlugin *plugin);
 
-/**
- * Status code returned from functions running database commands.
- * Can be combined with a function that returns the number
- * of results, so all non-negative values indicate success.
- */
-enum ANASTASIS_DB_QueryStatus
-{
-  /**
-   * Already valid code stored under this public key, please use the valid code
-   */
-  ANASTASIS_DB_STATUS_VALID_CODE_STORED = -6,
-
-  /**
-   * Provided Challenge code didn't match the server generated code
-   */
-  ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISSMATCH = -5,
-
-  /**
-   * Update failed because the old recovery data hash does not match what we 
previously had in the DB.
-   */
-  ANASTASIS_DB_STATUS_OLD_RECOVERY_UPLOAD_MISSMATCH = -4,
-
-  /**
-   * Account is unpaid / does not exist.
-   */
-  ANASTASIS_DB_STATUS_PAYMENT_REQUIRED = -3,
-
-  /**
-   * A hard error occurred, retrying will not help.
-   */
-  ANASTASIS_DB_STATUS_HARD_ERROR = -2,
-
-  /**
-   * A soft error occurred, retrying the transaction may succeed.
-   * Includes DEADLOCKS and SERIALIZATION errors.
-   */
-  ANASTASIS_DB_STATUS_SOFT_ERROR = -1,
-
-  /**
-   * The transaction succeeded, but yielded zero results.
-   * May include the case where an INSERT failed with UNIQUE
-   * violation (i.e. row already exists) or where DELETE
-   * failed to remove anything (i.e. nothing matched).
-   */
-  ANASTASIS_DB_STATUS_NO_RESULTS = 0,
-
-  /**
-   * The transaction succeeded, and yielded one result.
-   */
-  ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT = 1
-
-                                           /* Larger values may be returned 
for SELECT statements
-                                               that returned more than one 
result. */
-};
 
 #endif  /* ANASTASIS_DB_LIB_H */
 
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index 0ff68f3..419a7de 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -22,6 +22,103 @@
 #define ANASTASIS_DATABASE_PLUGIN_H
 
 #include "anastasis_service.h"
+#include <gnunet/gnunet_db_lib.h>
+
+
+/**
+ * Return values for checking code validity.
+ */
+enum ANASTASIS_DB_CodeStatus
+{
+  /**
+   * Provided authentication code does not match database content.
+   */
+  ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH = -3,
+
+  /**
+   * Encountered hard error talking to DB.
+   */
+  ANASTASIS_DB_CODE_STATUS_HARD_ERROR = -2,
+
+  /**
+   * Encountered serialization error talking to DB.
+   */
+  ANASTASIS_DB_CODE_STATUS_SOFT_ERROR = -1,
+
+  /**
+   * We have no challenge in the database.
+   */
+  ANASTASIS_DB_CODE_STATUS_NO_RESULTS = 0,
+
+  /**
+   * The provided challenge matches what we have in the database.
+   */
+  ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED = 1,
+};
+
+
+/**
+ * Return values for checking account validity.
+ */
+enum ANASTASIS_DB_AccountStatus
+{
+  /**
+   * Account is unknown, user should pay to establish it.
+   */
+  ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED = -3,
+
+  /**
+   * Encountered hard error talking to DB.
+   */
+  ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR = -2,
+
+  /**
+   * Account is valid, but we have no policy stored yet.
+   */
+  ANASTASIS_DB_ACCOUNT_STATUS_NO_RESULTS = 0,
+
+  /**
+   * Account is valid, and we have a policy stored.
+   */
+  ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED = 1,
+};
+
+
+/**
+ * Return values for storing data in database with payment.
+ */
+enum ANASTASIS_DB_StoreStatus
+{
+  /**
+   * The client has stored too many policies, should pay to store more.
+   */
+  ANASTASIS_DB_STORE_STATUS_STORE_LIMIT_EXCEEDED = -4,
+
+  /**
+   * The client needs to pay to store policies.
+   */
+  ANASTASIS_DB_STORE_STATUS_PAYMENT_REQUIRED = -3,
+
+  /**
+   * Encountered hard error talking to DB.
+   */
+  ANASTASIS_DB_STORE_STATUS_HARD_ERROR = -2,
+
+  /**
+   * Despite retrying, we encountered serialization errors.
+   */
+  ANASTASIS_DB_STORE_STATUS_SOFT_ERROR = -1,
+
+  /**
+   * Database did not need an update (document exists).
+   */
+  ANASTASIS_DB_STORE_STATUS_NO_RESULTS = 0,
+
+  /**
+   * We successfully stored the document.
+   */
+  ANASTASIS_DB_STORE_STATUS_SUCCESS = 1,
+};
 
 
 /**
@@ -51,15 +148,17 @@ struct ANASTASIS_DB_Truth
  *
  * @param cls closure
  * @param timestamp for how long have we been waiting
- * @param order_id order id in the backend
+ * @param payment_secret payment secret / order id in the backend
  * @param amount how much is the order for
  */
 typedef void
 (*ANASTASIS_DB_PaymentPendingIterator)(void *cls,
                                        struct GNUNET_TIME_Absolute timestamp,
-                                       const char *payment_identifier,
+                                       struct ANASTASIS_PaymentSecretP *
+                                       payment_secret,
                                        const struct TALER_Amount *amount);
 
+
 /**
  * Handle to interact with the database.
  *
@@ -105,7 +204,7 @@ struct ANASTASIS_DatabasePlugin
    *            this value should be garbage collected
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum GNUNET_DB_QueryStatus
   (*gc)(void *cls,
         struct GNUNET_TIME_Absolute expire,
         struct GNUNET_TIME_Absolute expire_pending_payments);
@@ -155,207 +254,212 @@ struct ANASTASIS_DatabasePlugin
    * @param cls the `struct PostgresClosure` with the plugin-specific state
    * @return transaction status code
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum GNUNET_DB_QueryStatus
   (*commit)(void *cls);
 
 
   /**
-  * Upload encrypted recovery document.
-  *
-  * @param cls closure
-  * @param anastasis_pub public key of the user's account
-  * @param account_sig signature affirming storage request
-  * @param data_hash hash of @a data
-  * @param data contains encrypted_recovery_document
-  * @param data_size size of data blob
-  * @param payment_secret identifier for the payment, used to later charge on 
uploads
-  * @param version[OUT] 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, ...
-  */
-  enum ANASTASIS_DB_QueryStatus
-  (*store_recovery_document)(void *cls,
-                             const struct
-                             ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
-                             const struct
-                             ANASTASIS_AccountSignatureP *account_sig,
-                             const struct
-                             GNUNET_HashCode *data_hash,
-                             const void *data,
-                             size_t data_size,
-                             const struct
-                             ANASTASIS_PaymentSecretP *payment_secret,
-                             uint32_t *version);
-
-  /**
- * Fetch recovery document for user according given version.
- *
- * @param cls closure
- * @param anastasis_pub public key of the user's account
- * @param version the version number of the policy the user requests
- * @param account_sig[OUT] signature
- * @param recovery_data_hash[OUT] hash of the current recovery data
- * @param data_size[OUT] size of data blob
- * @param data[OUT] blob which contains the recovery document
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*get_recovery_document)(void *cls,
-                           const struct
-                           ANASTASIS_CRYPTO_AccountPublicKeyP *
-                           anastasis_pub,
-                           uint32_t version,
-                           struct
-                           ANASTASIS_AccountSignatureP *account_sig,
-                           struct
-                           GNUNET_HashCode *recovery_data_hash,
-                           size_t *data_size,
-                           void **data);
-
-  /**
- * Fetch latest recovery document for user.
- *
- * @param cls closure
- * @param anastasis_pub public key of the user's account
- * @param account_sig signature
- * @param recovery_data_hash hash of the current recovery data
- * @param data_size size of data blob
- * @param data blob which contains the recovery document
- * @param version[OUT] set to the version number of the policy being returned
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*get_latest_recovery_document)(void *cls,
-                                  const struct
-                                  ANASTASIS_CRYPTO_AccountPublicKeyP *
-                                  anastasis_pub,
-                                  struct
-                                  ANASTASIS_AccountSignatureP *account_sig,
-                                  struct
-                                  GNUNET_HashCode *recovery_data_hash,
-                                  size_t *data_size,
-                                  void **data,
-                                  uint32_t *version);
-
-  /**
- * Upload Truth, which contains the Truth and the KeyShare.
- *
- * @param cls closure
- * @param truth_public_key the identifier for the Truth
- * @param key_share_data contains information of an EncryptedKeyShare
- * @param method name of method
- * @param nonce nonce used to compute encryption key for encrypted_truth
- * @param aes_gcm_tag authentication tag of encrypted_truth
- * @param encrypted_truth contains the encrypted Truth which includes the 
ground truth i.e. H(challenge answer), phonenumber, SMS
- * @param encrypted_truth_size the size of the Truth
- * @param truth_expiration time till the according data will be stored
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*store_truth)(void *cls,
-                 const struct
-                 ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-                 const struct
-                 ANASTASIS_CRYPTO_EncryptedKeyShareP *key_share_data,
-                 const char *mime_type,
-                 const void *encrypted_truth,
-                 size_t encrypted_truth_size,
-                 const char *method,
-                 struct
-                 GNUNET_TIME_Relative truth_expiration);
-
-
-  /**
-  * @param cls closure
-  * @param truth_public_key the identifier for the Truth
-  * @param truth contains the encrypted truth
-  * @param truth_size size of the encrypted truth
-  * @param truth_mime mime type of truth
-  * @return transaction status
-  */
-  enum ANASTASIS_DB_QueryStatus
-  (*get_escrow_challenge)(void *cls,
-                          const struct
-                          ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-                          void **truth,
-                          size_t *truth_size,
-                          char **truth_mime,
-                          char **method);
-
-  /**
-  * @param cls closure
-  * @param truth_public_key the identifier for the Truth
-  * @param key_share contains the encrypted Keyshare
-  * @param key_share_size size of the Keyshare
-  * @return transaction status
-  */
-  enum ANASTASIS_DB_QueryStatus
-  (*get_key_share)(void *cls,
-                   const struct
-                   ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-                   void **key_share,
-                   size_t *key_share_size);
-
-  /**
-  * @param cls closure
-  * @param anastasis_pub account identifier
-  * @param recovery_data_hash[OUT] set to hash of @a recovery document
-  * @return transaction status
-  */
-  enum ANASTASIS_DB_QueryStatus
-  (*lookup_account)(void *cls,
-                    const struct
-                    ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
-                    struct GNUNET_HashCode *recovery_data_hash);
+   * Store encrypted recovery document.
+   *
+   * @param cls closure
+   * @param anastasis_pub public key of the user's account
+   * @param account_sig signature affirming storage request
+   * @param data_hash hash of @a data
+   * @param data contains encrypted_recovery_document
+   * @param 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, ...
+   */
+  enum ANASTASIS_DB_StoreStatus
+  (*store_recovery_document)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+    const struct ANASTASIS_AccountSignatureP *account_sig,
+    const struct GNUNET_HashCode *data_hash,
+    const void *data,
+    size_t data_size,
+    const struct ANASTASIS_PaymentSecretP *payment_secret,
+    uint32_t *version);
+
 
   /**
- * Lookup pending payments by account.
- *
- * @param cls closure
- * @param anastasis_pub account to look for pending payment under
- * @param it iterator to call on all pending payments
- * @param it_cls closure for @a it
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*lookup_pending_payments_by_account)(void *cls,
-                                        const struct
-                                        ANASTASIS_CRYPTO_AccountPublicKeyP *
-                                        anastasis_pub,
-                                        ANASTASIS_DB_PaymentPendingIterator it,
-                                        void *it_cls);
+   * Fetch recovery document for user according given version.
+   *
+   * @param cls closure
+   * @param anastasis_pub public key of the user's account
+   * @param version the version number of the policy the user requests
+   * @param[out] account_sig signature
+   * @param[out] recovery_data_hash hash of the current recovery data
+   * @param[out] data_size size of data blob
+   * @param[out] data blob which contains the recovery document
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_recovery_document)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+    uint32_t version,
+    struct ANASTASIS_AccountSignatureP *account_sig,
+    struct GNUNET_HashCode *recovery_data_hash,
+    size_t *data_size,
+    void **data);
 
-/**
- * Check payment identifier. Used to check if a payment identifier given by
- * the user is valid (existing and paid).
- *
- * @param cls closure
- * @param payment_secret payment secret which the user must provide with every 
upload
- * @param paid bool value to show if payment is paid
- * @param valid_counter bool value to show if post_counter is > 0
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*check_payment_identifier)(void *cls,
-                              const struct
-                              ANASTASIS_PaymentSecretP *payment_secret,
-                              bool *paid,
-                              bool *valid_counter);
-/**
- * Check payment identifier. Used to check if a payment identifier given by
- * the user is valid (existing and paid).
- *
- * @param cls closure
- * @param payment_secret payment secret which the user must provide with every 
upload
- * @param paid[OUT] bool value to show if payment is paid
- * @param valid_counter[OUT] bool value to show if post_counter is > 0
- * @return transaction status
- */
-  enum ANASTASIS_DB_QueryStatus
-  (*check_challenge_payment)(void *cls,
-                             const struct
-                             ANASTASIS_PaymentSecretP *payment_secret,
-                             bool *paid);
+
+  /**
+   * Fetch latest recovery document for user.
+   *
+   * @param cls closure
+   * @param anastasis_pub public key of the user's account
+   * @param account_sig signature
+   * @param recovery_data_hash hash of the current recovery data
+   * @param[out] data_size set to size of @a data blob
+   * @param[out] data set to blob which contains the recovery document
+   * @param[out] version set to the version number of the policy being returned
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_latest_recovery_document)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+    struct ANASTASIS_AccountSignatureP *account_sig,
+    struct GNUNET_HashCode *recovery_data_hash,
+    size_t *data_size,
+    void **data,
+    uint32_t *version);
+
+
+  /**
+   * Upload Truth, which contains the Truth and the KeyShare.
+   *
+   * @param cls closure
+   * @param truth_public_key the identifier for the Truth
+   * @param key_share_data contains information of an EncryptedKeyShare
+   * @param method name of method
+   * @param nonce nonce used to compute encryption key for encrypted_truth
+   * @param aes_gcm_tag authentication tag of encrypted_truth
+   * @param encrypted_truth contains the encrypted Truth which includes the 
ground truth i.e. H(challenge answer), phonenumber, SMS
+   * @param encrypted_truth_size the size of the Truth
+   * @param truth_expiration time till the according data will be stored
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*store_truth)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    const struct ANASTASIS_CRYPTO_EncryptedKeyShareP *key_share_data,
+    const char *mime_type,
+    const void *encrypted_truth,
+    size_t encrypted_truth_size,
+    const char *method,
+    struct GNUNET_TIME_Relative truth_expiration);
+
+
+  /**
+   * Get the encrypted truth to validate the challenge response
+   *
+   * @param cls closure
+   * @param truth_public_key the identifier for the Truth
+   * @param[out] truth contains the encrypted truth
+   * @param[out] truth_size size of the encrypted truth
+   * @param[out] truth_mime mime type of truth
+   * @param[out] method type of the challenge
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_escrow_challenge)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    void **truth,
+    size_t *truth_size,
+    char **truth_mime,
+    char **method);
+
+
+  /**
+   * Lookup (encrypted) key share by @a truth_public_key.
+   *
+   * @param cls closure
+   * @param truth_public_key the identifier for the Truth
+   * @param[out] key_share contains the encrypted Keyshare
+   * @param[out] key_share_size size of the Keyshare
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_key_share)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    void **key_share,
+    size_t *key_share_size);
+
+
+  /**
+   * Check if an account exists, and if so, return the
+   * current @a recovery_document_hash.
+   *
+   * @param cls closure
+   * @param anastasis_pub account identifier
+   * @param[out] recovery_data_hash set to hash of @a recovery document
+   * @return transaction status
+   */
+  enum ANASTASIS_DB_AccountStatus
+  (*lookup_account)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+    struct GNUNET_HashCode *recovery_data_hash);
+
+
+  /**
+   * Lookup pending payments by account.
+   *
+   * @param cls closure
+   * @param anastasis_pub account to look for pending payment under
+   * @param it iterator to call on all pending payments
+   * @param it_cls closure for @a it
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*lookup_pending_payments_by_account)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
+    ANASTASIS_DB_PaymentPendingIterator it,
+    void *it_cls);
+
+
+  /**
+   * Check payment identifier. Used to check if a payment identifier given by
+   * the user is valid (existing and paid).
+   *
+   * @param cls closure
+   * @param payment_secret payment secret which the user must provide with 
every upload
+   * @param[out] paid bool value to show if payment is paid
+   * @param[out] valid_counter bool value to show if post_counter is > 0
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*check_payment_identifier)(
+    void *cls,
+    const struct ANASTASIS_PaymentSecretP *payment_secret,
+    bool *paid,
+    bool *valid_counter);
+
+
+  /**
+   * Check payment identifier. Used to check if a payment identifier given by
+   * the user is valid (existing and paid).
+   *
+   * @param cls closure
+   * @param payment_secret payment secret which the user must provide with 
every upload
+   * @param[out] paid bool value to show if payment is paid
+   * @param[out] valid_counter bool value to show if post_counter is > 0
+   * @return transaction status
+   */
+  enum GNUNET_DB_QueryStatus
+  (*check_challenge_payment)(
+    void *cls,
+    const struct ANASTASIS_PaymentSecretP *payment_secret,
+    bool *paid);
 
   /**
    * Increment account lifetime.
@@ -366,7 +470,7 @@ struct ANASTASIS_DatabasePlugin
    * @param lifetime for how long is the account now paid (increment)
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum GNUNET_DB_QueryStatus
   (*increment_lifetime)(
     void *cls,
     const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -386,7 +490,7 @@ struct ANASTASIS_DatabasePlugin
    * @param amount how much we asked for
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum GNUNET_DB_QueryStatus
   (*record_recdoc_payment)(
     void *cls,
     const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -405,7 +509,7 @@ struct ANASTASIS_DatabasePlugin
    * @param hashed_code code which the user provided and wants to verify
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum ANASTASIS_DB_CodeStatus
   (*verify_challenge_code)(void *cls,
                            const struct
                            ANASTASIS_CRYPTO_TruthPublicKeyP *truth_pub,
@@ -421,16 +525,18 @@ struct ANASTASIS_DatabasePlugin
    * @param code code which will be safed to check later
    * @param expiration_time for how long is the code available
    * @param retry_counter amount of retries allowed
-   * @return transaction status
+   * @return transaction status,
+   *        #GNUNET_DB_STATUS_SUCCESS_NO_RESULTS if conflicting challenge 
exists in DB,
+   *        #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if this @a code is now in the 
DB
    */
+  enum GNUNET_DB_QueryStatus
+  (*store_challenge_code)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    uint64_t code,
+    struct GNUNET_TIME_Relative expiration_time,
+    unsigned int retry_counter);
 
-  enum ANASTASIS_DB_QueryStatus
-  (*store_challenge_code)(void *cls,
-                          const struct
-                          ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-                          uint64_t code,
-                          struct GNUNET_TIME_Relative expiration_time,
-                          unsigned int retry_counter);
 
   /**
    * Store payment for challenge.
@@ -441,29 +547,29 @@ struct ANASTASIS_DatabasePlugin
    * @param amount how much we asked for
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
-  (*record_challenge_payment)(void *cls,
-                              const struct
-                              ANASTASIS_CRYPTO_TruthPublicKeyP 
*truth_public_key,
-                              const struct
-                              ANASTASIS_PaymentSecretP *payment_secret,
-                              const struct TALER_Amount *amount);
+  enum GNUNET_DB_QueryStatus
+  (*record_challenge_payment)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    const struct ANASTASIS_PaymentSecretP *payment_secret,
+    const struct TALER_Amount *amount);
+
 
   /**
    * Lookup for a pending payment for a certain challenge
    *
    * @param cls closure
    * @param truth_public_key identification of the challenge
-   * @param cp returns a challenge payment struct
+   * @param[out] payment_secret set to the challenge payment secret
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
-  (*lookup_challenge_payment)(void *cls,
-                              const struct
-                              ANASTASIS_CRYPTO_TruthPublicKeyP
-                              *truth_public_key,
-                              ANASTASIS_DB_PaymentPendingIterator it,
-                              void *it_cls);
+  enum GNUNET_DB_QueryStatus
+  (*lookup_challenge_payment)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    struct ANASTASIS_PaymentSecretP *payment_secret);
+
+
   /**
    * Update payment status of challenge
    *
@@ -472,18 +578,22 @@ struct ANASTASIS_DatabasePlugin
    * @param payment_identifier proof of payment, must be unique and match 
pending payment
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
-  (*update_challenge_payment)(void *cls,
-                              const struct
-                              ANASTASIS_CRYPTO_TruthPublicKeyP 
*truth_public_key,
-                              const struct
-                              ANASTASIS_PaymentSecretP *payment_identifier);
+  enum GNUNET_DB_QueryStatus
+  (*update_challenge_payment)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+    const struct ANASTASIS_PaymentSecretP *payment_identifier);
+
+
   /**
-   * FIXME maybe implemented in the postgres_gc but want it separate first
-   * Function called to remove all expired codes in the database
+   * Function called to remove all expired codes from the database.
+   * FIXME: maybe implement as part of @e gc() in the future.
+   *
    * @return transaction status
    */
-  enum ANASTASIS_DB_QueryStatus
+  enum GNUNET_DB_QueryStatus
   (*challenge_gc)(void *cls);
+
+
 };
 #endif
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index e1f1928..aad7829 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -200,12 +200,11 @@ rollback (void *cls)
  * @param cls the `struct PostgresClosure` with the plugin-specific state
  * @return transaction status code
  */
-
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 commit_transaction (void *cls)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam no_params[] = {
     GNUNET_PQ_query_param_end
   };
@@ -231,7 +230,7 @@ commit_transaction (void *cls)
  *            this value should be garbage collected
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_gc (void *cls,
              struct GNUNET_TIME_Absolute expire_backups,
              struct GNUNET_TIME_Absolute expire_pending_payments)
@@ -245,7 +244,7 @@ postgres_gc (void *cls,
     GNUNET_PQ_query_param_absolute_time (&expire_pending_payments),
     GNUNET_PQ_query_param_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
 
   check_connection (pg);
   postgres_preflight (pg);
@@ -269,7 +268,7 @@ postgres_gc (void *cls,
  * @param creation_date timestamp
  * @return transaction status, NULL if codes are different
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum ANASTASIS_DB_CodeStatus
 check_valid_code (
   struct PostgresClosure *pg,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -287,7 +286,7 @@ check_valid_code (
                                   &server_code),
     GNUNET_PQ_result_spec_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
 
   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                  "challengecode_select",
@@ -296,12 +295,11 @@ check_valid_code (
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_SOFT_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
+    return ANASTASIS_DB_CODE_STATUS_NO_RESULTS;
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     {
       struct GNUNET_HashCode shashed_code;
@@ -312,13 +310,13 @@ check_valid_code (
           GNUNET_memcmp (&shashed_code,
                          hashed_code))
       {
-        return ANASTASIS_DB_STATUS_VALID_CODE_STORED;
+        return ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED;
       }
-      return ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISSMATCH;
+      return ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH;
     }
   default:
     GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   }
 }
 
@@ -366,6 +364,7 @@ payment_by_account_cb (void *cls,
                        unsigned int num_results)
 {
   struct PaymentIteratorContext *pic = cls;
+
   for (unsigned int i = 0; i < num_results; i++)
   {
     struct GNUNET_TIME_Absolute creation_date;
@@ -391,14 +390,10 @@ payment_by_account_cb (void *cls,
       pic->qs = GNUNET_DB_STATUS_HARD_ERROR;
       return;
     }
-    char *order_id;
-    order_id = GNUNET_STRINGS_data_to_string_alloc (&payment_identifier,
-                                                    sizeof (struct
-                                                            
ANASTASIS_PaymentSecretP));
     pic->qs = i + 1;
     pic->it (pic->it_cls,
              creation_date,
-             order_id,
+             &payment_identifier,
              &amount);
     GNUNET_PQ_cleanup_result (rs);
   }
@@ -413,7 +408,7 @@ payment_by_account_cb (void *cls,
  * @param it iterator to call on all pending payments
  * @param it_cls closure for @a it
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_lookup_pending_payments_by_account (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -447,20 +442,20 @@ postgres_lookup_pending_payments_by_account (
 
 
 /**
-  * Upload encrypted recovery document.
-  *
-  * @param cls closure
-  * @param anastasis_pub public key of the user's account
-  * @param account_sig signature affirming storage request
-  * @param data_hash hash of @a data
-  * @param data contains encrypted_recovery_document
-  * @param data_size size of data blob
-  * @param payment_secret identifier for the payment, used to later charge on 
uploads
-  * @param version[OUT] 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_QueryStatus
+ * Store encrypted recovery document.
+ *
+ * @param cls closure
+ * @param anastasis_pub public key of the user's account
+ * @param account_sig signature affirming storage request
+ * @param data_hash hash of @a data
+ * @param data contains encrypted_recovery_document
+ * @param 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 *anastasis_pub,
@@ -473,235 +468,209 @@ postgres_store_recovery_document (
 {
   struct PostgresClosure *pg = cls;
   enum GNUNET_DB_QueryStatus qs;
-  uint32_t postcounter;
-  struct GNUNET_HashCode dh;
 
   check_connection (pg);
   postgres_preflight (pg);
-  /* get the version for the recoverydocument */
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint32 ("version", version),
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"latest_recovery_version_select",
-                                                   params,
-                                                   rs);
-  }
-  switch (qs)
-  {
-  case ANASTASIS_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_NO_RESULTS:
-    *version = 1;
-    break;
-  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
-    (*version)++;
-    break;
-  default:
-    rollback (pg);
-    return qs;
-  }
-
-  /* First, check if account exists */
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "user_select",
-                                                   params,
-                                                   rs);
-  }
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    /* handle interesting case below */
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-
-  // lookup if the user has enough uploads left and decrement
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_auto_from_type (payment_secret),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_uint32 ("post_counter",
-                                    &postcounter),
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "postcounter_select",
-                                                   params,
-                                                   rs);
-  }
-
-  switch (qs)
-  {
-  case ANASTASIS_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_NO_RESULTS:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    rollback (pg);
-    return qs;
-  }
-
-  if (0 == postcounter)
+  for (unsigned int retry = 0; retry<MAX_RETRIES; retry++)
   {
-    rollback (pg);
-    return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; // FIXME: WAS: 
TALER_EC_DB_STATUS_NOT_SUFFICIENT_POSTS;
-  }
-  /* Decrement the postcounter by one */
-  postcounter--;
-
-  /* Update the postcounter in the Database */
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_uint32 (&postcounter),
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_auto_from_type (payment_secret),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "postcounter_update",
-                                             params);
-  }
-  switch (qs)
-  {
-  case ANASTASIS_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_NO_RESULTS:
-    GNUNET_break (0);
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    rollback (pg);
-    return qs;
-  }
+    if (GNUNET_OK !=
+        begin_transaction (pg,
+                           "store_recovery_document"))
+    {
+      GNUNET_break (0);
+      return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+    }
+    /* get the current version and hash of the latest recovery document
+       for this account */
+    {
+      struct GNUNET_HashCode dh;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_uint32 ("version",
+                                      version),
+        GNUNET_PQ_result_spec_auto_from_type ("recovery_data_hash",
+                                              &dh),
+        GNUNET_PQ_result_spec_end
+      };
 
-  /* check if existing recovery_data conflicts */
-  if (*version > 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "At %s:%d Public key used to query db is: %s\n",
-                __FILE__,
-                __LINE__,
-                TALER_B2S (anastasis_pub));
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     
"latest_recovery_version_select",
+                                                     params,
+                                                     rs);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        rollback (pg);
+        return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        goto retry;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        *version = 1;
+        break;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        /* had an existing recovery_data, is it identical? */
+        if (0 == GNUNET_memcmp (&dh,
+                                recovery_data_hash))
+        {
+          /* Yes. Previous identical recovery data exists */
+          rollback (pg);
+          return ANASTASIS_DB_STORE_STATUS_NO_RESULTS;
+        }
+        (*version)++;
+        break;
+      default:
+        rollback (pg);
+        return qs;
+      }
+    }
 
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("recovery_data_hash",
-                                            &dh),
-      GNUNET_PQ_result_spec_end
-    };
+    /* First, check if account exists */
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_end
+      };
 
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   
"recoverydocument_select_hash",
-                                                   params,
-                                                   rs);
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "user_select",
+                                                     params,
+                                                     rs);
+    }
     switch (qs)
     {
     case GNUNET_DB_STATUS_HARD_ERROR:
-      return ANASTASIS_DB_STATUS_HARD_ERROR;
+      rollback (pg);
+      return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
     case GNUNET_DB_STATUS_SOFT_ERROR:
-      GNUNET_break (0);
-      return ANASTASIS_DB_STATUS_SOFT_ERROR;
+      goto retry;
     case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-      /* original error must have been a hard error, oddly enough */
-      // return ANASTASIS_DB_STATUS_HARD_ERROR;
-      break;
+      rollback (pg);
+      return ANASTASIS_DB_STORE_STATUS_PAYMENT_REQUIRED;
     case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
       /* handle interesting case below */
       break;
-    default:
-      GNUNET_break (0);
-      return ANASTASIS_DB_STATUS_HARD_ERROR;
     }
-    /* had an existing recovery_data, is it identical? */
-    if (0 == GNUNET_memcmp (&dh,
-                            recovery_data_hash))
-      /* previous conflicting recovery_data exists */
-      return ANASTASIS_DB_STATUS_OLD_RECOVERY_UPLOAD_MISSMATCH;
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_uint32 (version),
-      GNUNET_PQ_query_param_auto_from_type (account_sig),
-      GNUNET_PQ_query_param_auto_from_type (recovery_data_hash),
-      GNUNET_PQ_query_param_fixed_size (recovery_data,
-                                        recovery_data_size),
-      GNUNET_PQ_query_param_end
-    };
 
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "recovery_document_insert",
-                                             params);
-  }
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    /* handle interesting case below */
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    {
+      uint32_t postcounter;
+
+      /* lookup if the user has enough uploads left and decrement */
+      {
+        struct GNUNET_PQ_QueryParam params[] = {
+          GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+          GNUNET_PQ_query_param_auto_from_type (payment_secret),
+          GNUNET_PQ_query_param_end
+        };
+        struct GNUNET_PQ_ResultSpec rs[] = {
+          GNUNET_PQ_result_spec_uint32 ("post_counter",
+                                        &postcounter),
+          GNUNET_PQ_result_spec_end
+        };
+
+        qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                       "postcounter_select",
+                                                       params,
+                                                       rs);
+        switch (qs)
+        {
+        case GNUNET_DB_STATUS_HARD_ERROR:
+          rollback (pg);
+          return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+        case GNUNET_DB_STATUS_SOFT_ERROR:
+          goto retry;
+        case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+          rollback (pg);
+          return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+        case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+          break;
+        }
+      }
+
+      if (0 == postcounter)
+      {
+        rollback (pg);
+        return ANASTASIS_DB_STORE_STATUS_STORE_LIMIT_EXCEEDED;
+      }
+      /* Decrement the postcounter by one */
+      postcounter--;
+
+      /* Update the postcounter in the Database */
+      {
+        struct GNUNET_PQ_QueryParam params[] = {
+          GNUNET_PQ_query_param_uint32 (&postcounter),
+          GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+          GNUNET_PQ_query_param_auto_from_type (payment_secret),
+          GNUNET_PQ_query_param_end
+        };
+
+        qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                 "postcounter_update",
+                                                 params);
+        switch (qs)
+        {
+        case GNUNET_DB_STATUS_HARD_ERROR:
+          rollback (pg);
+          return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+        case GNUNET_DB_STATUS_SOFT_ERROR:
+          goto retry;
+        case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+          GNUNET_break (0);
+          rollback (pg);
+          return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+        case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+          break;
+        default:
+          rollback (pg);
+          return qs;
+        }
+      }
+    }
+
+    /* finally, actually insert the recovery document */
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+        GNUNET_PQ_query_param_uint32 (version),
+        GNUNET_PQ_query_param_auto_from_type (account_sig),
+        GNUNET_PQ_query_param_auto_from_type (recovery_data_hash),
+        GNUNET_PQ_query_param_fixed_size (recovery_data,
+                                          recovery_data_size),
+        GNUNET_PQ_query_param_end
+      };
+
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "recovery_document_insert",
+                                               params);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        rollback (pg);
+        return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        goto retry;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        GNUNET_break (0);
+        rollback (pg);
+        return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        qs = commit_transaction (pg);
+        if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+          goto retry;
+        if (qs < 0)
+          return ANASTASIS_DB_STORE_STATUS_HARD_ERROR;
+        return ANASTASIS_DB_STORE_STATUS_SUCCESS;
+      }
+    }
+retry:
+    rollback (pg);
   }
-  return qs;
+  return ANASTASIS_DB_STORE_STATUS_SOFT_ERROR;
 }
 
 
@@ -714,7 +683,7 @@ postgres_store_recovery_document (
  * @param lifetime for how long is the account now paid (increment)
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_increment_lifetime (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -723,137 +692,120 @@ postgres_increment_lifetime (
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_TIME_Absolute expiration;
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
 
   check_connection (pg);
-  if (GNUNET_OK !=
-      begin_transaction (pg,
-                         "increment lifetime"))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-
+  for (unsigned int retries = 0; retries<MAX_RETRIES; retries++)
   {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (payment_identifier),
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
-    check_connection (pg);
-    postgres_preflight (pg);
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "recdoc_payment_done",
-                                             params);
-    if (0 >= qs)
+    if (GNUNET_OK !=
+        begin_transaction (pg,
+                           "increment lifetime"))
     {
-      /* payment made before, or unknown, or error => no further action! */
-      rollback (pg);
-      return qs;
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
     }
-  }
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
-                                            &expiration),
-      GNUNET_PQ_result_spec_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "user_select",
-                                                   params,
-                                                   rs);
-  }
 
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     {
-      // user does not exist, create new one
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "At %s:%d Public key to be saved to user db is: %s\n",
-                  __FILE__,
-                  __LINE__,
-                  TALER_B2S (anastasis_pub));
-
       struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (payment_identifier),
         GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
-        GNUNET_PQ_query_param_absolute_time (&expiration),
         GNUNET_PQ_query_param_end
       };
-
-      expiration = GNUNET_TIME_relative_to_absolute (lifetime);
+      check_connection (pg);
+      postgres_preflight (pg);
       qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "user_insert",
+                                               "recdoc_payment_done",
                                                params);
+      if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+        goto retry;
+      if (0 >= qs)
+      {
+        /* payment made before, or unknown, or error => no further action! */
+        rollback (pg);
+        return qs;
+      }
     }
-    break;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+
     {
-      // user exists, update expiration_date
       struct GNUNET_PQ_QueryParam params[] = {
-        GNUNET_PQ_query_param_absolute_time (&expiration),
         GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
         GNUNET_PQ_query_param_end
       };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_auto_from_type ("expiration_date",
+                                              &expiration),
+        GNUNET_PQ_result_spec_end
+      };
 
-      expiration = GNUNET_TIME_absolute_add (expiration,
-                                             lifetime);
-      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                               "user_update",
-                                               params);
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     "user_select",
+                                                     params,
+                                                     rs);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        goto retry;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        {
+          /* user does not exist, create new one */
+          struct GNUNET_PQ_QueryParam params[] = {
+            GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+            GNUNET_PQ_query_param_absolute_time (&expiration),
+            GNUNET_PQ_query_param_end
+          };
+
+          expiration = GNUNET_TIME_relative_to_absolute (lifetime);
+          qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                   "user_insert",
+                                                   params);
+        }
+        break;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        {
+          /* user exists, update expiration_date */
+          struct GNUNET_PQ_QueryParam params[] = {
+            GNUNET_PQ_query_param_absolute_time (&expiration),
+            GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
+            GNUNET_PQ_query_param_end
+          };
+
+          expiration = GNUNET_TIME_absolute_add (expiration,
+                                                 lifetime);
+          qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                                   "user_update",
+                                                   params);
+        }
+        break;
+      }
     }
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0);
+
+    switch (qs)
+    {
+    case GNUNET_DB_STATUS_HARD_ERROR:
+      rollback (pg);
+      return qs;
+    case GNUNET_DB_STATUS_SOFT_ERROR:
+      goto retry;
+    case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+      GNUNET_break (0);
+      rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+      break;
+    }
+    qs = commit_transaction (pg);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+      goto retry;
+    if (qs < 0)
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+retry:
     rollback (pg);
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  qs = commit_transaction (pg);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
   }
+  return GNUNET_DB_STATUS_SOFT_ERROR;
 }
 
 
@@ -869,7 +821,7 @@ postgres_increment_lifetime (
  * @param amount how much we asked for
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_record_recdoc_payment (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -878,7 +830,6 @@ postgres_record_recdoc_payment (
   const struct TALER_Amount *amount)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
   struct GNUNET_TIME_Absolute expiration;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -889,12 +840,13 @@ postgres_record_recdoc_payment (
     GNUNET_PQ_query_param_absolute_time (&now),
     GNUNET_PQ_query_param_end
   };
+  enum GNUNET_DB_QueryStatus qs;
 
   check_connection (pg);
   postgres_preflight (pg);
 
-  // because of constraint at user_id, first we have to verify
-  // if user exists, otherwise we have to create one
+  /* because of constraint at user_id, first we have to verify
+     if user exists, and if not, create one */
   {
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
@@ -914,14 +866,13 @@ postgres_record_recdoc_payment (
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return qs;
   case GNUNET_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+    GNUNET_break (0);
+    return GNUNET_DB_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     {
-      // create new user
+      /* create new user */
       struct GNUNET_PQ_QueryParam params[] = {
         GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
         GNUNET_PQ_query_param_absolute_time (&now),
@@ -930,55 +881,31 @@ postgres_record_recdoc_payment (
       qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                                "user_insert",
                                                params);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        GNUNET_break (0);
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        GNUNET_break (0);
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        /* successful, continue below */
+        break;
+      }
     }
+    /* continue below */
     break;
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    // handle case below
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0);
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+    /* handle case below */
     break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
   }
 
-  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                           "recdoc_payment_insert",
-                                           params);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                             "recdoc_payment_insert",
+                                             params);
 }
 
 
@@ -991,7 +918,7 @@ postgres_record_recdoc_payment (
  * @param amount how much we asked for
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_record_challenge_payment (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -999,75 +926,19 @@ postgres_record_challenge_payment (
   const struct TALER_Amount *amount)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
-  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
-  check_connection (pg);
-
-/*
-  {
-    // because of constraint at truth_id, first we have to verify
-    // if the challenge exists
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_public_key),
-      GNUNET_PQ_query_param_end
-    };
-    struct GNUNET_PQ_ResultSpec rs[] = {
-      GNUNET_PQ_result_spec_end
-    };
-    qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "truth_select",
-                                                   params,
-                                                   rs);
-    if (qs != 1)
-    {
-      return qs;
-    }
-  }
-*/
-  if (GNUNET_OK != begin_transaction (pg,
-                                      "challenge_payment_insert"))
-  {
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_public_key),
-      TALER_PQ_query_param_amount (amount),
-      GNUNET_PQ_query_param_auto_from_type (payment_secret),
-      GNUNET_PQ_query_param_absolute_time (&now),
-      GNUNET_PQ_query_param_end
-    };
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (truth_public_key),
+    TALER_PQ_query_param_amount (amount),
+    GNUNET_PQ_query_param_auto_from_type (payment_secret),
+    GNUNET_PQ_query_param_absolute_time (&now),
+    GNUNET_PQ_query_param_end
+  };
 
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+  check_connection (pg);
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "challenge_payment_insert",
                                              params);
-  }
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-
-  qs = commit_transaction (pg);
-  if (qs < 0)
-  {
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-
-  return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -1077,11 +948,11 @@ postgres_record_challenge_payment (
  *
  * @param cls closure
  * @param payment_secret payment secret which the user must provide with every 
upload
- * @param paid[OUT] bool value to show if payment is paid
- * @param valid_counter[OUT] bool value to show if post_counter is > 0
+ * @param[out] paid bool value to show if payment is paid
+ * @param[out] valid_counter bool value to show if post_counter is > 0
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_check_challenge_payment (
   void *cls,
   const struct ANASTASIS_PaymentSecretP *payment_secret,
@@ -1097,30 +968,12 @@ postgres_check_challenge_payment (
                                           paid),
     GNUNET_PQ_result_spec_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
 
   check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "challenge_payment_select",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  return qs;
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "challenge_payment_select",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -1130,11 +983,11 @@ postgres_check_challenge_payment (
  *
  * @param cls closure
  * @param payment_secret payment secret which the user must provide with every 
upload
- * @param paid[OUT] bool value to show if payment is paid
- * @param valid_counter[OUT] bool value to show if post_counter is > 0
+ * @param[out] paid bool value to show if payment is paid
+ * @param[out] valid_counter bool value to show if post_counter is > 0
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_check_payment_identifier (
   void *cls,
   const struct ANASTASIS_PaymentSecretP *payment_secret,
@@ -1142,9 +995,7 @@ postgres_check_payment_identifier (
   bool *valid_counter)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
   uint32_t counter;
-
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (payment_secret),
     GNUNET_PQ_query_param_end
@@ -1156,20 +1007,21 @@ postgres_check_payment_identifier (
                                   &counter),
     GNUNET_PQ_result_spec_end
   };
+  enum GNUNET_DB_QueryStatus qs;
+
   check_connection (pg);
   qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
                                                  "recdoc_payment_select",
                                                  params,
                                                  rs);
 
-  if (qs == ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT)
+  if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
     if (counter > 0)
       *valid_counter = true;
     else
       *valid_counter = false;
   }
-
   return qs;
 }
 
@@ -1189,7 +1041,7 @@ postgres_check_payment_identifier (
  * @param truth_expiration time till the according data will be stored
  * @return transaction status
  */
-static enum ANASTASIS_DB_QueryStatus
+static enum GNUNET_DB_QueryStatus
 postgres_store_truth (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -1201,68 +1053,26 @@ postgres_store_truth (
   struct GNUNET_TIME_Relative truth_expiration)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute expiration = GNUNET_TIME_absolute_get ();
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (truth_public_key),
+    GNUNET_PQ_query_param_auto_from_type (key_share_data),
+    GNUNET_PQ_query_param_string (method),
+    GNUNET_PQ_query_param_fixed_size (encrypted_truth,
+                                      encrypted_truth_size),
+    GNUNET_PQ_query_param_string (mime_type),
+    TALER_PQ_query_param_absolute_time (&expiration),
+    GNUNET_PQ_query_param_end
+  };
+
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d Truth public key used to query db is: %s\n",
-              __FILE__,
-              __LINE__,
-              TALER_B2S (truth_public_key));
   GNUNET_TIME_round_abs (&expiration);
   expiration = GNUNET_TIME_absolute_add (expiration,
                                          truth_expiration);
-
   check_connection (pg);
-  if (GNUNET_OK != begin_transaction (pg,
-                                      "store_truth"))
-  {
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_public_key),
-      GNUNET_PQ_query_param_auto_from_type (key_share_data),
-      GNUNET_PQ_query_param_string (method),
-      GNUNET_PQ_query_param_fixed_size (encrypted_truth,
-                                        encrypted_truth_size),
-      GNUNET_PQ_query_param_string (mime_type),
-      TALER_PQ_query_param_absolute_time (&expiration),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "truth_insert",
                                              params);
-  }
-  switch (qs)
-  {
-  case ANASTASIS_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_NO_RESULTS:
-    GNUNET_break (0);
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    rollback (pg);
-    return qs;
-  }
-
-  qs = commit_transaction (pg);
-  if (qs < 0)
-  {
-    return qs;
-  }
-
-  return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -1271,12 +1081,13 @@ postgres_store_truth (
  *
  * @param cls closure
  * @param truth_public_key the identifier for the Truth
- * @param truth contains the encrypted truth
- * @param truth_size size of encrypted truth
- * @param truth_mime mime type of truth
+ * @param[out] truth contains the encrypted truth
+ * @param[out] truth_size size of the encrypted truth
+ * @param[out] truth_mime mime type of truth
+ * @param[out] method type of the challenge
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_get_escrow_challenge (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -1310,13 +1121,15 @@ postgres_get_escrow_challenge (
 
 
 /**
+ * Lookup (encrypted) key share by @a truth_public_key.
+ *
  * @param cls closure
  * @param truth_public_key the identifier for the Truth
- * @param key_share contains the encrypted Keyshare
- * @param key_share_size size of the Keyshare
+ * @param[out] key_share contains the encrypted Keyshare
+ * @param[out] key_share_size size of the Keyshare
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_get_key_share (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -1334,38 +1147,23 @@ postgres_get_key_share (
                                          key_share_size),
     GNUNET_PQ_result_spec_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
 
   check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "key_share_select",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "key_share_select",
+                                                   params,
+                                                   rs);
 }
 
 
 /**
+ *
  * @param cls closure
  * @param anastasis_pub account identifier
- * @param recovery_data_hash[OUT] set to hash of @a recovery document
+ * @param[out] recovery_data_hash set to hash of @a recovery document
  * @return transaction status
-*/
-enum ANASTASIS_DB_QueryStatus
+ */
+enum ANASTASIS_DB_AccountStatus
 postgres_lookup_account (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -1376,7 +1174,7 @@ postgres_lookup_account (
     GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
     GNUNET_PQ_query_param_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
 
   check_connection (pg);
   postgres_preflight (pg);
@@ -1395,17 +1193,14 @@ postgres_lookup_account (
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SOFT_ERROR:
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+    GNUNET_break (0);
+    return ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     break; /* handle interesting case below */
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED;
   }
 
   /* check if account exists */
@@ -1422,19 +1217,19 @@ postgres_lookup_account (
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SOFT_ERROR:
     GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+    return ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
     /* indicates: no account */
-    return ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
+    return ANASTASIS_DB_ACCOUNT_STATUS_PAYMENT_REQUIRED;
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
     /* indicates: no backup */
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
+    return ANASTASIS_DB_ACCOUNT_STATUS_NO_RESULTS;
   default:
     GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_ACCOUNT_STATUS_HARD_ERROR;
   }
 }
 
@@ -1451,7 +1246,7 @@ postgres_lookup_account (
  * @param version[OUT] set to the version number of the policy being returned
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_get_latest_recovery_document (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -1462,7 +1257,6 @@ postgres_get_latest_recovery_document (
   uint32_t *version)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
     GNUNET_PQ_query_param_end
@@ -1482,25 +1276,10 @@ postgres_get_latest_recovery_document (
 
   check_connection (pg);
   postgres_preflight (pg);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 
"latest_recoverydocument_select",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"latest_recoverydocument_select",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -1516,7 +1295,7 @@ postgres_get_latest_recovery_document (
  * @param[out] data blob which contains the recovery document
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_get_recovery_document (
   void *cls,
   const struct ANASTASIS_CRYPTO_AccountPublicKeyP *anastasis_pub,
@@ -1542,28 +1321,12 @@ postgres_get_recovery_document (
                                          data_size),
     GNUNET_PQ_result_spec_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
 
   check_connection (pg);
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 "recoverydocument_select",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   "recoverydocument_select",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -1575,9 +1338,9 @@ postgres_get_recovery_document (
  * @param cls closure
  * @param truth_pub identification of the challenge which the code corresponds 
to
  * @param hashed_code code which the user provided and wants to verify
- * @return transaction status
+ * @return code validity status
  */
-enum ANASTASIS_DB_QueryStatus
+enum ANASTASIS_DB_CodeStatus
 postgres_verify_challenge_code (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_pub,
@@ -1588,57 +1351,63 @@ postgres_verify_challenge_code (
     GNUNET_PQ_query_param_auto_from_type (truth_pub),
     GNUNET_PQ_query_param_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute time_now = GNUNET_TIME_absolute_get ();
+  enum ANASTASIS_DB_CodeStatus cs;
 
   check_connection (pg);
   GNUNET_TIME_round_abs (&time_now);
   /* Check if there is already a valid code */
-  qs = check_valid_code (pg,
+  cs = check_valid_code (pg,
                          truth_pub,
                          hashed_code,
                          time_now);
-  if (qs != ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISSMATCH)
-    return qs;
+  if (cs != ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH)
+  {
+    if (ANASTASIS_DB_CODE_STATUS_SOFT_ERROR == cs)
+    {
+      GNUNET_break (0);
+      return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
+    }
+    return cs;
+  }
   qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                            "challengecode_update_retry",
                                            params);
   switch (qs)
   {
   case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SOFT_ERROR:
     GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    /*Should never happen */
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
+    GNUNET_break (0);
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    return ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISSMATCH;
+    return ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH;
   default:
     GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
+    return ANASTASIS_DB_CODE_STATUS_HARD_ERROR;
   }
 }
 
 
 /**
- * Lookup for a pending payment for a certain challenge
+ * Lookup pending payment for a certain challenge.
  *
  * @param cls closure
  * @param truth_public_key identification of the challenge
- * @param cp returns a challenge payment struct
+ * @param[out] payment_secret set to the challenge payment secret
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_lookup_challenge_payment (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
-  ANASTASIS_DB_PaymentPendingIterator it,
-  void *it_cls)
+  struct ANASTASIS_PaymentSecretP *payment_secret)
 {
   struct PostgresClosure *pg = cls;
-  struct ANASTASIS_PaymentSecretP payment_identifier;
   struct GNUNET_TIME_Absolute timestamp;
   struct TALER_Amount amount;
   struct GNUNET_PQ_QueryParam params[] = {
@@ -1649,46 +1418,17 @@ postgres_lookup_challenge_payment (
     GNUNET_PQ_result_spec_absolute_time ("creation_date",
                                          &timestamp),
     GNUNET_PQ_result_spec_auto_from_type ("payment_identifier",
-                                          &payment_identifier),
+                                          payment_secret),
     TALER_PQ_result_spec_amount ("amount",
                                  pg->currency,
                                  &amount),
     GNUNET_PQ_result_spec_end
   };
-  enum ANASTASIS_DB_QueryStatus qs;
-
-  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                 
"challenge_pending_payment_select",
-                                                 params,
-                                                 rs);
-  switch (qs)
-  {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    return ANASTASIS_DB_STATUS_NO_RESULTS;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
 
-  {
-    char *order_id;
-
-    order_id = GNUNET_STRINGS_data_to_string_alloc (
-      &payment_identifier,
-      sizeof (struct ANASTASIS_PaymentSecretP));
-    it (it_cls,
-        timestamp,
-        order_id, // FIXME: pass payment secretP, not ASCII version here!
-        &amount);
-    GNUNET_free (order_id);
-  }
-  return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
+  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                   
"challenge_pending_payment_select",
+                                                   params,
+                                                   rs);
 }
 
 
@@ -1700,52 +1440,23 @@ postgres_lookup_challenge_payment (
  * @param payment_identifier proof of payment, must be unique and match 
pending payment
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
-postgres_update_challenge_payment (void *cls,
-                                   const struct
-                                   ANASTASIS_CRYPTO_TruthPublicKeyP *
-                                   truth_public_key,
-                                   const struct
-                                   ANASTASIS_PaymentSecretP 
*payment_identifier)
+enum GNUNET_DB_QueryStatus
+postgres_update_challenge_payment (
+  void *cls,
+  const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
+  const struct ANASTASIS_PaymentSecretP *payment_identifier)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
+  struct GNUNET_PQ_QueryParam params[] = {
+    GNUNET_PQ_query_param_auto_from_type (payment_identifier),
+    GNUNET_PQ_query_param_auto_from_type (truth_public_key),
+    GNUNET_PQ_query_param_end
+  };
 
   check_connection (pg);
-  if (GNUNET_OK !=
-      begin_transaction (pg,
-                         "update_challenge_payment"))
-  {
-    GNUNET_break (0);
-    return GNUNET_DB_STATUS_HARD_ERROR;
-  }
-
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (payment_identifier),
-      GNUNET_PQ_query_param_auto_from_type (truth_public_key),
-      GNUNET_PQ_query_param_end
-    };
-
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+  return GNUNET_PQ_eval_prepared_non_select (pg->conn,
                                              "challenge_payment_done",
                                              params);
-    if (0 >= qs)
-    {
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "ROLLBACK %d", qs);
-      /* payment made before, or unknown, or error => no further action! */
-      rollback (pg);
-      return qs;
-    }
-    qs = commit_transaction (pg);
-    if (qs < 0)
-    {
-      return qs;
-    }
-  }
-  return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
 }
 
 
@@ -1761,7 +1472,7 @@ postgres_update_challenge_payment (void *cls,
  * @param retry_counter amount of retries allowed
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_store_challenge_code (
   void *cls,
   const struct ANASTASIS_CRYPTO_TruthPublicKeyP *truth_public_key,
@@ -1770,80 +1481,99 @@ postgres_store_challenge_code (
   unsigned int retry_counter)
 {
   struct PostgresClosure *pg = cls;
-  enum ANASTASIS_DB_QueryStatus qs;
+  enum GNUNET_DB_QueryStatus qs;
   struct GNUNET_TIME_Absolute creation_date = GNUNET_TIME_absolute_get ();
   struct GNUNET_TIME_Absolute expiration_date;
   struct GNUNET_HashCode hashed_code;
+  enum ANASTASIS_DB_CodeStatus cs;
 
   check_connection (pg);
   GNUNET_TIME_round_abs (&creation_date);
   expiration_date = GNUNET_TIME_absolute_add (creation_date,
                                               expiration_time);
 
-  /*Check if there is already a valid code */
+  /* Check if there is already a valid code */
   ANASTASIS_hash_answer (code,
                          &hashed_code);
-  qs = check_valid_code (pg,
-                         truth_public_key,
-                         &hashed_code,
-                         creation_date);
-  if (qs != ANASTASIS_DB_STATUS_NO_RESULTS)
-    return qs;
-  if (GNUNET_OK != begin_transaction (pg,
-                                      "store_challenge_code"))
-  {
-    GNUNET_break (0);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  }
-  {
-    struct GNUNET_PQ_QueryParam params[] = {
-      GNUNET_PQ_query_param_auto_from_type (truth_public_key),
-      GNUNET_PQ_query_param_uint64 (&code),
-      TALER_PQ_query_param_absolute_time (&creation_date),
-      TALER_PQ_query_param_absolute_time (&expiration_date),
-      GNUNET_PQ_query_param_uint32 (&retry_counter),
-      GNUNET_PQ_query_param_end
-    };
-    qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "challengecode_insert",
-                                             params);
-  }
-  switch (qs)
+  for (unsigned int retries = 0; retries<MAX_RETRIES; retries++)
   {
-  case GNUNET_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-  case GNUNET_DB_STATUS_SOFT_ERROR:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_SOFT_ERROR;
-  case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
-    break;
-  default:
-    rollback (pg);
-    return ANASTASIS_DB_STATUS_HARD_ERROR;
-    return qs;
-  }
+    if (GNUNET_OK !=
+        begin_transaction (pg,
+                           "store_challenge_code"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+    cs = check_valid_code (pg,
+                           truth_public_key,
+                           &hashed_code,
+                           creation_date);
+    switch (cs)
+    {
+    case ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH:
+      /* conflicting challenge is in DB, refuse to change! */
+      rollback (pg);
+      return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS;
+    case ANASTASIS_DB_CODE_STATUS_HARD_ERROR:
+      rollback (pg);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    case ANASTASIS_DB_CODE_STATUS_SOFT_ERROR:
+      goto retry;
+    case ANASTASIS_DB_CODE_STATUS_NO_RESULTS:
+      break; /* continue below */
+    case ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED:
+      /* same value already stored, claim success */
+      rollback (pg);
+      return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+    }
 
-  qs = commit_transaction (pg);
-  if (qs < 0)
-  {
-    return qs;
-  }
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (truth_public_key),
+        GNUNET_PQ_query_param_uint64 (&code),
+        TALER_PQ_query_param_absolute_time (&creation_date),
+        TALER_PQ_query_param_absolute_time (&expiration_date),
+        GNUNET_PQ_query_param_uint32 (&retry_counter),
+        GNUNET_PQ_query_param_end
+      };
 
-  return ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT;
+      qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                               "challengecode_insert",
+                                               params);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        rollback (pg);
+        return GNUNET_DB_STATUS_HARD_ERROR;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        goto retry;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        rollback (pg);
+        return GNUNET_DB_STATUS_SOFT_ERROR;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        break;
+      }
+    }
+    qs = commit_transaction (pg);
+    if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+      goto retry;
+    if (qs < 0)
+      return qs;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+retry:
+    rollback (pg);
+  }
+  return GNUNET_DB_STATUS_SOFT_ERROR;
 }
 
 
 /**
- * FIXME maybe implemented in the postgres_gc but want it separate first
- * Function called to remove all expired codes in the database
+ * Function called to remove all expired codes from the database.
+ * FIXME maybe implemented as part of postgres_gc() in the future.
  *
  * @return transaction status
  */
-enum ANASTASIS_DB_QueryStatus
+enum GNUNET_DB_QueryStatus
 postgres_challenge_gc (void *cls)
 {
   struct PostgresClosure *pg = cls;
@@ -2057,6 +1787,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
     GNUNET_PQ_make_prepare ("latest_recovery_version_select",
                             "SELECT"
                             " version"
+                            ",recovery_data_hash"
                             " FROM anastasis_recoverydocument"
                             " WHERE user_id=$1"
                             " ORDER BY version DESC"
diff --git a/src/stasis/test_anastasis_db.c b/src/stasis/test_anastasis_db.c
index 8fe663d..056a7ac 100644
--- a/src/stasis/test_anastasis_db.c
+++ b/src/stasis/test_anastasis_db.c
@@ -1,6 +1,6 @@
 /*
   This file is part of Anastasis
-  Copyright (C) 2020 Taler Systems SA
+  Copyright (C) 2020, 2021 Taler Systems SA
 
   Anastasis is free software; you can redistribute it and/or modify it under 
the
   terms of the GNU Lesser General Public License as published by the Free 
Software
@@ -19,13 +19,8 @@
  * @author Marcello Stanisci
  * @author Christian Grothoff
  */
-
 #include "platform.h"
-#include <gnunet/gnunet_util_lib.h>
-#include <taler/taler_util.h>
-#include "anastasis_database_plugin.h"
 #include "anastasis_database_lib.h"
-#include "anastasis_error_codes.h"
 #include "anastasis_util_lib.h"
 #include <gnunet/gnunet_signatures.h>
 
@@ -62,26 +57,6 @@ run (void *cls)
 {
   struct GNUNET_CONFIGURATION_Handle *cfg = cls;
   struct TALER_Amount amount;
-
-  if (NULL == (plugin = ANASTASIS_DB_plugin_load (cfg)))
-  {
-    result = 77;
-    return;
-  }
-  if (GNUNET_OK != plugin->drop_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)))
-  {
-    result = 77;
-    return;
-  }
-
   struct ANASTASIS_PaymentSecretP paymentSecretP;
   struct ANASTASIS_CRYPTO_AccountPublicKeyP accountPubP;
   struct ANASTASIS_AccountSignatureP accountSig;
@@ -110,12 +85,30 @@ run (void *cls)
   const char *recovery_data = "RECOVERY_DATA";
   uint64_t challenge_code = 1234;
   struct GNUNET_HashCode c_hash;
-
   struct ANASTASIS_UploadSignaturePS usp = {
     .purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_TEST),
     .purpose.size = htonl (sizeof (usp))
   };
 
+  if (NULL == (plugin = ANASTASIS_DB_plugin_load (cfg)))
+  {
+    result = 77;
+    return;
+  }
+  if (GNUNET_OK != plugin->drop_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)))
+  {
+    result = 77;
+    return;
+  }
+
   challenge_expiration = GNUNET_TIME_UNIT_HOURS;
   GNUNET_CRYPTO_hash (recovery_data,
                       strlen (recovery_data),
@@ -139,7 +132,7 @@ run (void *cls)
                                          &amount));
 
   memset (&key_share, 1, sizeof (key_share));
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_truth (plugin->cls,
                                &truth_public_key,
                                &key_share,
@@ -149,7 +142,7 @@ run (void *cls)
                                method,
                                rel_time));
 
-  FAILIF (ANASTASIS_DB_STATUS_NO_RESULTS !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->check_payment_identifier (plugin->cls,
                                             &paymentSecretP,
                                             &paid,
@@ -157,50 +150,41 @@ run (void *cls)
 
   memset (&accountPubP, 2, sizeof (accountPubP));
   memset (&accountSig, 3, sizeof (accountSig));
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->record_recdoc_payment (plugin->cls,
                                          &accountPubP,
                                          post_counter,
                                          &paymentSecretP,
                                          &amount));
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->increment_lifetime (plugin->cls,
                                       &accountPubP,
                                       &paymentSecretP,
                                       rel_time));
-
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->check_payment_identifier (plugin->cls,
                                             &paymentSecretP,
                                             &paid,
                                             &valid_counter));
-
-  FAILIF (ANASTASIS_DB_STATUS_NO_RESULTS !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
           plugin->check_challenge_payment (plugin->cls,
                                            &paymentSecretP,
                                            &paid));
 
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->record_challenge_payment (plugin->cls,
                                             &truth_public_key,
                                             &paymentSecretP,
                                             &amount));
-
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->update_challenge_payment (plugin->cls,
                                             &truth_public_key,
                                             &paymentSecretP));
-
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->check_challenge_payment (plugin->cls,
                                            &paymentSecretP,
                                            &paid));
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (ANASTASIS_DB_STORE_STATUS_SUCCESS !=
           plugin->store_recovery_document (plugin->cls,
                                            &accountPubP,
                                            &accountSig,
@@ -209,13 +193,11 @@ run (void *cls)
                                            strlen (recovery_data),
                                            &paymentSecretP,
                                            &docVersion));
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (ANASTASIS_DB_ACCOUNT_STATUS_VALID_HASH_RETURNED !=
           plugin->lookup_account (plugin->cls,
                                   &accountPubP,
                                   &r));
-
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_key_share (plugin->cls,
                                  &truth_public_key,
                                  &res_key_share,
@@ -225,7 +207,7 @@ run (void *cls)
                        sizeof (key_share)));
   GNUNET_free (res_key_share);
 
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_recovery_document (plugin->cls,
                                          &accountPubP,
                                          recversion,
@@ -238,7 +220,7 @@ run (void *cls)
                        strlen (recovery_data)));
   GNUNET_free (res_recovery_data);
 
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->get_latest_recovery_document (plugin->cls,
                                                 &accountPubP,
                                                 &res_account_sig,
@@ -251,7 +233,7 @@ run (void *cls)
                        strlen (recovery_data)));
   GNUNET_free (res_recovery_data);
 
-  FAILIF (ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_challenge_code (plugin->cls,
                                         &truth_public_key,
                                         challenge_code,
@@ -259,7 +241,7 @@ run (void *cls)
                                         3));
 
 
-  FAILIF (ANASTASIS_DB_STATUS_VALID_CODE_STORED !=
+  FAILIF (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
           plugin->store_challenge_code (plugin->cls,
                                         &truth_public_key,
                                         challenge_code,
@@ -267,14 +249,14 @@ run (void *cls)
                                         3));
   ANASTASIS_hash_answer (123,
                          &c_hash);
-  FAILIF (ANASTASIS_DB_STATUS_CHALLENGE_CODE_MISSMATCH !=
+  FAILIF (ANASTASIS_DB_CODE_STATUS_CHALLENGE_CODE_MISMATCH !=
           plugin->verify_challenge_code (plugin->cls,
                                          &truth_public_key,
                                          &c_hash));
 
   ANASTASIS_hash_answer (challenge_code,
                          &c_hash);
-  FAILIF (ANASTASIS_DB_STATUS_VALID_CODE_STORED !=
+  FAILIF (ANASTASIS_DB_CODE_STATUS_VALID_CODE_STORED !=
           plugin->verify_challenge_code (plugin->cls,
                                          &truth_public_key,
                                          &c_hash));
@@ -315,12 +297,12 @@ main (int argc,
   GNUNET_OS_init (ANASTASIS_project_data_default ());
   GNUNET_log_setup (argv[0], "DEBUG", NULL);
   plugin_name++;
-  (void) GNUNET_asprintf (&testname,
-                          "%s",
-                          plugin_name);
-  (void) GNUNET_asprintf (&config_filename,
-                          "test_anastasis_db_%s.conf",
-                          testname);
+  GNUNET_asprintf (&testname,
+                   "%s",
+                   plugin_name);
+  GNUNET_asprintf (&config_filename,
+                   "test_anastasis_db_%s.conf",
+                   testname);
   cfg = GNUNET_CONFIGURATION_create ();
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_load (cfg,

-- 
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]