gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: Added Policy GET handling


From: gnunet
Subject: [taler-anastasis] branch master updated: Added Policy GET handling
Date: Wed, 18 Dec 2019 09:46:34 +0100

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

dennis-neufeld pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new 32e0b8c  Added Policy GET handling
32e0b8c is described below

commit 32e0b8c74425310ec3944c03fbaaf7d080d9e8c7
Author: Dennis Neufeld <address@hidden>
AuthorDate: Wed Dec 18 08:46:27 2019 +0000

    Added Policy GET handling
---
 src/backend/anastasis-httpd.c               |   8 +-
 src/backend/anastasis-httpd_policy.c        |   4 +-
 src/backend/anastasis-httpd_policy.h        |   4 +-
 src/backend/anastasis-httpd_policy_upload.c |  26 ++-
 src/backend/anastasis-httpd_truth.c         |   4 +-
 src/backend/anastasis-httpd_truth.h         |   4 +-
 src/include/anastasis_database_plugin.h     |  17 +-
 src/include/anastasis_service.h             |  38 ++++-
 src/include/anastasis_testing_lib.h         | 145 ++++++++++++++--
 src/lib/Makefile.am                         |   5 +-
 src/lib/anastasis_api_policy_lookup.c       | 246 ++++++++++++++++++++--------
 src/lib/anastasis_api_policy_store.c        |   2 +-
 src/lib/test_anastasis_api.c                |   6 +-
 src/lib/testing_api_cmd_policy_lookup.c     | 238 ++++++++++++++++++++++++++-
 src/lib/testing_api_cmd_policy_store.c      | 180 +++++++++++++++++---
 src/lib/testing_api_trait_account_priv.c    |  73 +++++++++
 src/lib/testing_api_trait_account_pub.c     |  73 +++++++++
 src/lib/testing_api_trait_hash.c            |  73 +++++++++
 src/stasis/plugin_anastasis_postgres.c      |  44 ++---
 19 files changed, 1020 insertions(+), 170 deletions(-)

diff --git a/src/backend/anastasis-httpd.c b/src/backend/anastasis-httpd.c
index 92ee61f..0db9ed9 100644
--- a/src/backend/anastasis-httpd.c
+++ b/src/backend/anastasis-httpd.c
@@ -277,13 +277,13 @@ url_handler (void *cls,
     // return handle_policy (...);
     if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
     {
-      return AH_handler_policy_GET (connection,
+      return AH_handler_policy_get (connection,
                                     url,
                                     con_cls);
     }
     if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
     {
-      return AH_handler_policy_POST (connection,
+      return AH_handler_policy_post (connection,
                                      con_cls,
                                      url,
                                      upload_data,
@@ -297,13 +297,13 @@ url_handler (void *cls,
     // return handle_truth (...);
     if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
     {
-      return AH_handler_truth_GET (connection,
+      return AH_handler_truth_get (connection,
                                    url,
                                    con_cls);
     }
     if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
     {
-      return AH_handler_truth_POST (connection,
+      return AH_handler_truth_post (connection,
                                     con_cls,
                                     url,
                                     upload_data,
diff --git a/src/backend/anastasis-httpd_policy.c 
b/src/backend/anastasis-httpd_policy.c
index 1f5448f..49da521 100644
--- a/src/backend/anastasis-httpd_policy.c
+++ b/src/backend/anastasis-httpd_policy.c
@@ -49,7 +49,7 @@
  * @return MHD result code
  */
 int
-AH_return_backup (struct MHD_Connection *connection,
+AH_return_policy (struct MHD_Connection *connection,
                   const struct ANASTASIS_AccountPubP *account,
                   unsigned int default_http_status)
 {
@@ -159,7 +159,7 @@ AH_return_backup (struct MHD_Connection *connection,
  * @return MHD result code
  */
 int
-AH_handler_policy_GET (struct MHD_Connection *connection,
+AH_handler_policy_get (struct MHD_Connection *connection,
                        const char *url,
                        void **con_cls)
 {
diff --git a/src/backend/anastasis-httpd_policy.h 
b/src/backend/anastasis-httpd_policy.h
index 0b88fb4..06401fc 100644
--- a/src/backend/anastasis-httpd_policy.h
+++ b/src/backend/anastasis-httpd_policy.h
@@ -31,7 +31,7 @@
  * @return MHD result code
  */
 int
-AH_handler_policy_GET (struct MHD_Connection *connection,
+AH_handler_policy_get (struct MHD_Connection *connection,
                        const char *url,
                        void **con_cls);
 
@@ -44,7 +44,7 @@ AH_handler_policy_GET (struct MHD_Connection *connection,
  * @return MHD result code
  */
 int
-AH_handler_policy_POST (struct MHD_Connection *connection,
+AH_handler_policy_post (struct MHD_Connection *connection,
                         void **con_cls,
                         const char *url,
                         const char *upload_data,
diff --git a/src/backend/anastasis-httpd_policy_upload.c 
b/src/backend/anastasis-httpd_policy_upload.c
index d6f2236..ce121f5 100644
--- a/src/backend/anastasis-httpd_policy_upload.c
+++ b/src/backend/anastasis-httpd_policy_upload.c
@@ -419,7 +419,6 @@ await_payment (struct PolicyUploadContext *puc,
   AH_trigger_curl ();
 }
 
-
 /**
  * Helper function used to ask our backend to begin
  * processing a payment for the user's account.
@@ -439,9 +438,12 @@ begin_payment (struct PolicyUploadContext *puc,
   enum ANASTASIS_DB_QueryStatus qs;
 
   qs = db->lookup_pending_payment_by_account (db->cls,
-                                              &puc->account);
+                                              &puc->account,
+                                              puc);
   if (qs < 0)
   {
+    /*FIXME: In our case we don't safe the order_id to db,
+     so there is no exsisting order in db*/
     struct MHD_Response *resp;
     int ret;
 
@@ -454,7 +456,7 @@ begin_payment (struct PolicyUploadContext *puc,
     return ret;
   }
 
-  if (qs == ANASTASIS_EC_DB_STATUS_UNKNOWN_USER)
+  if (qs == ANASTASIS_DB_STATUS_NO_RESULTS)
   {
     qs = db->increment_lifetime (db->cls,
                                  &puc->account,
@@ -462,13 +464,6 @@ begin_payment (struct PolicyUploadContext *puc,
                                  GNUNET_TIME_UNIT_ZERO);
   }
 
-  if (NULL != puc->existing_order_id)
-  {
-    await_payment (puc,
-                   GNUNET_TIME_UNIT_ZERO /* no long polling */,
-                   puc->existing_order_id);
-    return MHD_YES;
-  }
   GNUNET_CONTAINER_DLL_insert (puc_head,
                                puc_tail,
                                puc);
@@ -522,6 +517,7 @@ handle_database_error (struct PolicyUploadContext *puc,
       order_id = MHD_lookup_connection_value (puc->con,
                                               MHD_GET_ARGUMENT_KIND,
                                               "paying");
+
       if (NULL == order_id)
       {
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -566,7 +562,7 @@ handle_database_error (struct PolicyUploadContext *puc,
  * @return MHD result code
  */
 int
-AH_handler_policy_POST (struct MHD_Connection *connection,
+AH_handler_policy_post (struct MHD_Connection *connection,
                         void **con_cls,
                         const char *url,
                         const char *recovery_data,
@@ -744,13 +740,13 @@ AH_handler_policy_POST (struct MHD_Connection *connection,
       if (qs < 0)
         return handle_database_error (puc,
                                       qs);
-      if (ANASTASIS_DB_STATUS_NO_RESULTS == qs)
+      if (qs == ANASTASIS_DB_STATUS_NO_RESULTS)
       {
         memset (&hc, 0, sizeof (hc));
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                     "User not known. Payment required to create new 
account\n");
-        return begin_payment (puc,
-                              GNUNET_YES);
+        return handle_database_error (puc,
+                                      ANASTASIS_DB_STATUS_PAYMENT_REQUIRED);
       }
       if (0 == GNUNET_memcmp (&hc,
                               &puc->new_policy_upload_hash))
@@ -776,7 +772,7 @@ AH_handler_policy_POST (struct MHD_Connection *connection,
                               &puc->old_policy_upload_hash))
       {
         /* Refuse upload: if-none-match failed! */
-        return AH_return_backup (connection,
+        return AH_return_policy (connection,
                                  &accountPubP,
                                  MHD_HTTP_CONFLICT);
       }
diff --git a/src/backend/anastasis-httpd_truth.c 
b/src/backend/anastasis-httpd_truth.c
index 77d515b..87b903e 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -33,7 +33,7 @@
  * @return MHD result code
  */
 int
-AH_handler_truth_GET (struct MHD_Connection *connection,
+AH_handler_truth_get (struct MHD_Connection *connection,
                       const char *url,
                       void **con_cls)
 {
@@ -51,7 +51,7 @@ AH_handler_truth_GET (struct MHD_Connection *connection,
  * @return MHD result code
  */
 int
-AH_handler_truth_POST (struct MHD_Connection *connection,
+AH_handler_truth_post (struct MHD_Connection *connection,
                        void **con_cls,
                        const char *url,
                        const char *upload_data,
diff --git a/src/backend/anastasis-httpd_truth.h 
b/src/backend/anastasis-httpd_truth.h
index 6529826..57774c5 100644
--- a/src/backend/anastasis-httpd_truth.h
+++ b/src/backend/anastasis-httpd_truth.h
@@ -31,7 +31,7 @@
  * @return MHD result code
  */
 int
-AH_handler_truth_GET (struct MHD_Connection *connection,
+AH_handler_truth_get (struct MHD_Connection *connection,
                       const char *url,
                       void **con_cls);
 
@@ -44,7 +44,7 @@ AH_handler_truth_GET (struct MHD_Connection *connection,
  * @return MHD result code
  */
 int
-AH_handler_truth_POST (struct MHD_Connection *connection,
+AH_handler_truth_post (struct MHD_Connection *connection,
                        void **con_cls,
                        const char *url,
                        const char *upload_data,
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index 9f794b6..3dcb4cc 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -29,6 +29,20 @@
 #include <uuid/uuid.h>
 
 
+/**
+ * Function called on all pending payments for an account.
+ *
+ * @param cls closure
+ * @param timestamp for how long have we been waiting
+ * @param order_id 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 *order_id,
+                                       const struct TALER_Amount *amount);
+
 /**
  * Handle to interact with the database.
  *
@@ -270,7 +284,8 @@ struct ANASTASIS_DatabasePlugin
   enum ANASTASIS_DB_QueryStatus
   (*lookup_pending_payment_by_account)(void *cls,
                                        const struct
-                                       ANASTASIS_AccountPubP *account_pub);
+                                       ANASTASIS_AccountPubP *account_pub,
+                                       void *it_cls);
 
 /**
  * Increment account lifetime.
diff --git a/src/include/anastasis_service.h b/src/include/anastasis_service.h
index 429f385..9796903 100644
--- a/src/include/anastasis_service.h
+++ b/src/include/anastasis_service.h
@@ -131,7 +131,7 @@ enum ANASTASIS_UploadStatus
    * reconcile and try again with (using the provided
    * recovered backup as the previous backup).
    */
-  ANASTASIS_US_CONFLICTING_BACKUP = 2,
+  ANASTASIS_US_CONFLICTING_POLICY = 2,
 
   /**
    * HTTP interaction failed, see HTTP status.
@@ -151,6 +151,39 @@ enum ANASTASIS_UploadStatus
 };
 
 
+/**
+ * Detailed results from the successful download.
+ */
+struct ANASTASIS_DownloadDetails
+{
+  /**
+   * Signature (already verified).
+   */
+  struct ANASTASIS_AccountSignatureP sig;
+
+  /**
+   * Hash of the previous version.
+   */
+  struct GNUNET_HashCode prev_policy_hash;
+
+  /**
+   * Hash over @e policy and @e policy_size.
+   */
+  struct GNUNET_HashCode curr_policy_hash;
+
+  /**
+   * The backup we downloaded.
+   */
+  const void *policy;
+
+  /**
+   * Number of bytes in @e backup.
+   */
+  size_t policy_size;
+
+};
+
+
 /**
  * Result of an upload.
  */
@@ -240,8 +273,7 @@ struct ANASTASIS_PolicyLookupOperation;
 typedef void
 (*ANASTASIS_PolicyLookupCallback) (void *cls,
                                    unsigned int http_status,
-                                   enum ANASTASIS_ErrorCode ec,
-                                   const json_t *obj);
+                                   const struct ANASTASIS_DownloadDetails *dd);
 
 /**
  * Does a GET /policy.
diff --git a/src/include/anastasis_testing_lib.h 
b/src/include/anastasis_testing_lib.h
index 0df5612..d113a2c 100644
--- a/src/include/anastasis_testing_lib.h
+++ b/src/include/anastasis_testing_lib.h
@@ -29,6 +29,7 @@
 
 #include "anastasis_service.h"
 #include <gnunet/gnunet_json_lib.h>
+#include <taler/taler_testing_lib.h>
 #include <microhttpd.h>
 
 /* ********************* Helper functions ********************* */
@@ -41,6 +42,96 @@
  */
 #define ANASTASIS_TESTING_TRAIT_HASH_CURRENT 0
 
+/**
+ * Index used in #SYNC_TESTING_get_trait_hash() for the previous hash.
+ */
+#define ANASTASIS_TESTING_TRAIT_HASH_PREVIOUS 1
+
+/**
+ * Obtain a hash from @a cmd.
+ *
+ * @param cmd command to extract the number from.
+ * @param index the number's index number, 
#ANASTASIS_TESTING_TRAIT_HASH_CURRENT or
+ *          #SYNC_TESTING_TRAIT_HASH_PREVIOUS
+ * @param h[out] set to the hash coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_hash (const struct TALER_TESTING_Command *cmd,
+                                  unsigned int index,
+                                  const struct GNUNET_HashCode **h);
+
+
+/**
+ * Offer a hash.
+ *
+ * @param index the number's index number.
+ * @param h the hash to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_hash (unsigned int index,
+                                   const struct GNUNET_HashCode *h);
+
+
+/**
+ * Obtain an account public key from @a cmd.
+ *
+ * @param cmd command to extract the public key from.
+ * @param index usually 0
+ * @param pub[out] set to the account public key used in @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_account_pub (const struct
+                                         TALER_TESTING_Command *cmd,
+                                         unsigned int index,
+                                         const struct
+                                         ANASTASIS_AccountPubP **pub);
+
+
+/**
+ * Offer an account public key.
+ *
+ * @param index usually zero
+ * @param h the account_pub to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_account_pub (unsigned int index,
+                                          const struct
+                                          ANASTASIS_AccountPubP *h);
+
+
+/**
+ * Obtain an account private key from @a cmd.
+ *
+ * @param cmd command to extract the number from.
+ * @param index must be 0
+ * @param priv[out] set to the account private key used in @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_account_priv (const struct
+                                          TALER_TESTING_Command *cmd,
+                                          unsigned int index,
+                                          const struct
+                                          ANASTASIS_AccountPrivP **priv);
+
+
+/**
+ * Offer an account private key.
+ *
+ * @param index usually zero
+ * @param priv the account_priv to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_account_priv (unsigned int index,
+                                           const struct
+                                           ANASTASIS_AccountPrivP *priv);
+
+
 /**
  * Prepare the merchant execution.  Create tables and check if
  * the port is available.
@@ -99,6 +190,35 @@ TALER_TESTING_prepare_anastasis (const char 
*config_filename);
 
 /* ************** Specific interpreter commands ************ */
 
+
+/**
+ * Types of options for performing the upload. Used as a bitmask.
+ */
+enum ANASTASIS_TESTING_PolicyStoreOption
+{
+  /**
+   * Do everything by the book.
+   */
+  ANASTASIS_TESTING_PSO_NONE = 0,
+
+  /**
+   * Use random hash for previous upload instead of correct
+   * previous hash.
+   */
+  ANASTASIS_TESTING_PSO_PREV_HASH_WRONG = 1,
+
+  /**
+   * Request payment.
+   */
+  ANASTASIS_TESTING_PSO_REQUEST_PAYMENT = 2,
+
+  /**
+   * Reference payment order ID from linked previous upload.
+   */
+  ANASTASIS_TESTING_PSO_REFERENCE_ORDER_ID = 4
+
+};
+
 /**
  * Make the "policy store" command.
  *
@@ -116,29 +236,28 @@ TALER_TESTING_prepare_anastasis (const char 
*config_filename);
 struct TALER_TESTING_Command
 ANASTASIS_TESTING_cmd_policy_store (const char *label,
                                     const char *anastasis_url,
+                                    const char *prev_upload,
                                     unsigned int http_status,
+                                    enum
+                                    ANASTASIS_TESTING_PolicyStoreOption pso,
                                     const struct
                                     ANASTASIS_PaymentSecretP *payment_id,
                                     const void *policy_data,
                                     size_t policy_data_size);
 /**
- * Make a "policy lookup" command.
+ * Make the "policy lookup" command.
  *
- * @param label command label.
- * @param anastasis_url base URL of the anastasis backend
- *        serving the policy lookup request.
- * @param http_status expected HTTP response code.
- * @param policy_reference reference to a "policy store" CMD.
- * @param order_id order id to lookup, can be NULL.
- *
- * @return the command.
+ * @param label command label
+ * @param ANASTASIS_url base URL of the ANASTASIS serving
+ *        the policy store request.
+ * @param http_status expected HTTP status.
+ * @param upload_ref reference to upload command
+ * @return the command
  */
 struct TALER_TESTING_Command
 ANASTASIS_TESTING_cmd_policy_lookup (const char *label,
-                                     const char *anastasis_url,
+                                     const char *ANASTASIS_url,
                                      unsigned int http_status,
-                                     const char *proposal_reference,
-                                     const struct
-                                     ANASTASIS_AccountPubP pub);
+                                     const char *upload_ref);
 
 #endif
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
index c75d948..d156841 100644
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -52,7 +52,10 @@ libanastasistesting_la_LDFLAGS = \
 libanastasistesting_la_SOURCES = \
   testing_api_cmd_policy_store.c \
   testing_api_cmd_policy_lookup.c \
-  testing_api_helpers.c 
+  testing_api_helpers.c \
+  testing_api_trait_account_pub.c \
+  testing_api_trait_account_priv.c \
+  testing_api_trait_hash.c
 libanastasistesting_la_LIBADD = \
   libanastasisrest.la \
   -ltalerexchange \
diff --git a/src/lib/anastasis_api_policy_lookup.c 
b/src/lib/anastasis_api_policy_lookup.c
index 449f5b3..2f980b2 100644
--- a/src/lib/anastasis_api_policy_lookup.c
+++ b/src/lib/anastasis_api_policy_lookup.c
@@ -33,6 +33,7 @@
 #include <taler/taler_json_lib.h>
 #include <taler/taler_curl_lib.h>
 #include <taler/taler_util.h>
+#include <taler/taler_signatures.h>
 #include "anastasis_service.h"
 
 
@@ -66,6 +67,25 @@ struct ANASTASIS_PolicyLookupOperation
    * Reference to the execution context.
    */
   struct GNUNET_CURL_Context *ctx;
+
+  /**
+   * Public key of the account we are downloading from.
+   */
+  struct ANASTASIS_AccountPubP account_pub;
+
+  /**
+   * Signature returned in the "Sync-Signature"
+   * header, or all zeros for none.
+   */
+  struct ANASTASIS_AccountSignatureP account_sig;
+
+  /**
+   * FIXME: reasonable?
+   * Hash code returned by the server in the
+   * "Anastasis-Previous" header, or all zeros for
+   * none.
+   */
+  struct GNUNET_HashCode anastasis_previous;
 };
 
 
@@ -94,12 +114,10 @@ ANASTASIS_policy_lookup_cancel (struct
 static void
 handle_policy_lookup_finished (void *cls,
                                long response_code,
-                               const void *response)
+                               const void *data,
+                               size_t data_size)
 {
   struct ANASTASIS_PolicyLookupOperation *plo = cls;
-  char *error;
-  enum ANASTASIS_ErrorCode code;
-  const json_t *json = response;
 
   plo->job = NULL;
   switch (response_code)
@@ -108,41 +126,145 @@ handle_policy_lookup_finished (void *cls,
     /* Hard error */
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Backend didn't even return from GET /policy\n");
-    return;
+    break;
 
   case MHD_HTTP_OK:
+    {
+      struct ANASTASIS_DownloadDetails dd;
+      struct ANASTASIS_UploadSignaturePS usp;
+
+      usp.purpose.purpose = htonl (TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD);
+      usp.purpose.size = htonl (sizeof (usp));
+      usp.old_recovery_data_hash = plo->anastasis_previous;
+      GNUNET_CRYPTO_hash (data,
+                          data_size,
+                          &usp.new_recovery_data_hash);
+      if (GNUNET_OK !=
+          GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD,
+                                      &usp.purpose,
+                                      &plo->account_sig.eddsa_sig,
+                                      &plo->account_pub.pub))
+      {
+        GNUNET_break_op (0);
+        response_code = 0;
+        break;
+      }
+      /* Success, call callback with all details! */
+      memset (&dd, 0, sizeof (dd));
+      dd.sig = plo->account_sig;
+      dd.prev_policy_hash = plo->anastasis_previous;
+      dd.curr_policy_hash = usp.new_recovery_data_hash;
+      dd.policy = data;
+      dd.policy_size = data_size;
+      plo->cb (plo->cb_cls,
+               response_code,
+               &dd);
+      plo->cb = NULL;
+      ANASTASIS_policy_lookup_cancel (plo);
+      return;
+    }
+  case MHD_HTTP_BAD_REQUEST:
+    /* This should never happen, either us or the anastasis server is buggy
+       (or API version conflict); just pass JSON reply to the application */
+    break;
   case MHD_HTTP_NOT_FOUND:
-    plo->cb (plo->cb_cls,
-             response_code,
-             ANASTASIS_EC_NONE,
-             json);
+    /* Nothing really to verify */
+    break;
+  case MHD_HTTP_INTERNAL_SERVER_ERROR:
+    /* Server had an internal issue; we should retry, but this API
+       leaves this to the application */
     break;
   default:
-    /**
-     * The backend gave response, but it's error, log it.
-     * NOTE that json must be a ANASTASIS-specific error object (FIXME,
-     * need a link to error objects at docs)
-     */
-    if (-1 == json_unpack ((json_t *) json,
-                           "{s:s, s:I, s:s}",
-                           "error", &error,
-                           "code", &code))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Failed GET /policy, error: %s, code: %d\n",
-                  error,
-                  code);
-      break;
-    }
+    /* unexpected response code */
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed /policy lookup, backend did not give"
-                " a valid error object, HTTP code was %lu\n",
-                response_code);
+                "Unexpected response code %u\n",
+                (unsigned int) response_code);
+    GNUNET_break (0);
+    response_code = 0;
+    break;
+  }
+  if (NULL != plo->cb)
+  {
+    plo->cb (plo->cb_cls,
+             response_code,
+             NULL);
+    plo->cb = NULL;
   }
-
   ANASTASIS_policy_lookup_cancel (plo);
 }
 
+/**
+ * Handle HTTP header received by curl.
+ *
+ * @param buffer one line of HTTP header data
+ * @param size size of an item
+ * @param nitems number of items passed
+ * @param userdata our `struct ANASTASIS_PolicyLookupOperation *`
+ * @return `size * nitems`
+ */
+static size_t
+handle_header (char *buffer,
+               size_t size,
+               size_t nitems,
+               void *userdata)
+{
+  struct ANASTASIS_PolicyLookupOperation *plo = userdata;
+  size_t total = size * nitems;
+  char *ndup;
+  const char *hdr_type;
+  char *hdr_val;
+
+  ndup = GNUNET_strndup (buffer,
+                         total);
+  hdr_type = strtok (ndup,
+                     ":");
+  if (NULL == hdr_type)
+  {
+    GNUNET_free (ndup);
+    return total;
+  }
+  hdr_val = strtok (NULL,
+                    "\n\r");
+  if (NULL == hdr_val)
+  {
+    GNUNET_free (ndup);
+    return total;
+  }
+  if (' ' == *hdr_val)
+    hdr_val++;
+  if (0 == strcasecmp (hdr_type,
+                       "Anastasis-Policy-Signature"))
+  {
+    if (GNUNET_OK !=
+        GNUNET_STRINGS_string_to_data (hdr_val,
+                                       strlen (hdr_val),
+                                       &plo->account_sig,
+                                       sizeof (struct
+                                               ANASTASIS_AccountSignatureP)))
+    {
+      GNUNET_break_op (0);
+      GNUNET_free (ndup);
+      return 0;
+    }
+  }
+  /* FIXME: reasonable?*/
+  if (0 == strcasecmp (hdr_type,
+                       "Anastasis-Previous"))
+  {
+    if (GNUNET_OK !=
+        GNUNET_STRINGS_string_to_data (hdr_val,
+                                       strlen (hdr_val),
+                                       &plo->anastasis_previous,
+                                       sizeof (struct GNUNET_HashCode)))
+    {
+      GNUNET_break_op (0);
+      GNUNET_free (ndup);
+      return 0;
+    }
+  }
+  GNUNET_free (ndup);
+  return total;
+}
 
 /**
  * Does a GET /policy.
@@ -180,25 +302,20 @@ ANASTASIS_policy_lookup (struct GNUNET_CURL_Context *ctx,
                              NULL);
   GNUNET_free (path);
   eh = curl_easy_init ();
-  if (CURLE_OK != curl_easy_setopt (eh,
-                                    CURLOPT_URL,
-                                    plo->url))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
-                                               eh,
-                                               GNUNET_NO,
-                                               handle_policy_lookup_finished,
-                                               plo)))
-  {
-    GNUNET_break (0);
-    return NULL;
-
-  }
-
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_HEADERFUNCTION,
+                                   &handle_header));
+  GNUNET_assert ((CURLE_OK != curl_easy_setopt (eh,
+                                                CURLOPT_URL,
+                                                plo)));
+  plo->cb = cb;
+  plo->cb_cls = cb_cls;
+  plo->job = GNUNET_CURL_job_add_raw (ctx,
+                                      eh,
+                                      GNUNET_NO,
+                                      &handle_policy_lookup_finished,
+                                      plo);
   return plo;
 }
 
@@ -244,24 +361,19 @@ ANASTASIS_policy_lookup_version (struct 
GNUNET_CURL_Context *ctx,
                              NULL);
   GNUNET_free (path);
   eh = curl_easy_init ();
-  if (CURLE_OK != curl_easy_setopt (eh,
-                                    CURLOPT_URL,
-                                    plo->url))
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  if (NULL == (plo->job = GNUNET_CURL_job_add (ctx,
-                                               eh,
-                                               GNUNET_NO,
-                                               handle_policy_lookup_finished,
-                                               plo)))
-  {
-    GNUNET_break (0);
-    return NULL;
-
-  }
-
+  GNUNET_assert (CURLE_OK ==
+                 curl_easy_setopt (eh,
+                                   CURLOPT_HEADERFUNCTION,
+                                   &handle_header));
+  GNUNET_assert ((CURLE_OK != curl_easy_setopt (eh,
+                                                CURLOPT_URL,
+                                                plo)));
+  plo->cb = cb;
+  plo->cb_cls = cb_cls;
+  plo->job = GNUNET_CURL_job_add_raw (ctx,
+                                      eh,
+                                      GNUNET_NO,
+                                      &handle_policy_lookup_finished,
+                                      plo);
   return plo;
 }
diff --git a/src/lib/anastasis_api_policy_store.c 
b/src/lib/anastasis_api_policy_store.c
index beb6d3f..e9371a0 100644
--- a/src/lib/anastasis_api_policy_store.c
+++ b/src/lib/anastasis_api_policy_store.c
@@ -150,7 +150,7 @@ handle_policy_store_finished (void *cls,
                                      data_size);
     break;
   case MHD_HTTP_CONFLICT:
-    ud.us = ANASTASIS_US_CONFLICTING_BACKUP;
+    ud.us = ANASTASIS_US_CONFLICTING_POLICY;
     GNUNET_CRYPTO_hash (data,
                         data_size,
                         &ud.details.recovered_backup.existing_backup_hash);
diff --git a/src/lib/test_anastasis_api.c b/src/lib/test_anastasis_api.c
index fbb6e67..590d6a9 100644
--- a/src/lib/test_anastasis_api.c
+++ b/src/lib/test_anastasis_api.c
@@ -278,7 +278,9 @@ run (void *cls,
 
     ANASTASIS_TESTING_cmd_policy_store ("policy-store-1",
                                         anastasis_url,
+                                        NULL,
                                         MHD_HTTP_OK,
+                                        ANASTASIS_TESTING_PSO_NONE,
                                         &paymentSecret,
                                         "Test-1",
                                         strlen ("Test-1")),
@@ -287,7 +289,7 @@ run (void *cls,
     TALER_TESTING_cmd_proposal_lookup ("fetch-proposal",
                                        merchant_url,
                                        MHD_HTTP_OK,
-                                       "backup-upload-1",
+                                       "policy-store-1",
                                        NULL),
     /* make the payment */
     TALER_TESTING_cmd_pay ("pay-account",
@@ -301,7 +303,9 @@ run (void *cls,
 
     ANASTASIS_TESTING_cmd_policy_store ("policy-store-2",
                                         anastasis_url,
+                                        "backup-upload-1",
                                         MHD_HTTP_OK,
+                                        ANASTASIS_TESTING_PSO_NONE,
                                         &paymentSecret,
                                         "Test-2",
                                         strlen ("Test-2")),
diff --git a/src/lib/testing_api_cmd_policy_lookup.c 
b/src/lib/testing_api_cmd_policy_lookup.c
index 8cb45a3..0b5d07b 100644
--- a/src/lib/testing_api_cmd_policy_lookup.c
+++ b/src/lib/testing_api_cmd_policy_lookup.c
@@ -44,7 +44,17 @@ struct PolicyLookupState
   /**
    * Eddsa Publickey.
    */
-  const struct ANASTASIS_AccountPubP anastasis_pub;
+  struct ANASTASIS_AccountPubP anastasis_pub;
+
+  /**
+   * Hash of the upload (all zeros if there was no upload).
+   */
+  const struct GNUNET_HashCode *upload_hash;
+
+  /**
+   * Hash of the previous upload (all zeros if there was no previous upload).
+   */
+  const struct GNUNET_HashCode *prev_upload_hash;
 
   /**
    * URL of the anastasis backend.
@@ -56,8 +66,234 @@ struct PolicyLookupState
    */
   unsigned int http_status;
 
+  /**
+   * Reference to upload command we expect to lookup.
+   */
+  const char *upload_reference;
+
   /**
    * The  /policy GET operation handle.
    */
   struct ANASTASIS_PolicyLookupOperation *plo;
+
+  /**
+   * The /policy GET operation handle.
+   */
+  struct ANASTASIS_PolicyLookupOperation *lookup;
 };
+
+/**
+ * Function called with the results of a #ANASTASIS_lookup().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param ud details about the lookup operation
+ */
+static void
+policy_lookup_cb (void *cls,
+                  unsigned int http_status,
+                  const struct ANASTASIS_DownloadDetails *dd)
+{
+  struct PolicyLookupState *pls = cls;
+
+  pls->lookup = NULL;
+  if (http_status != pls->http_status)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unexpected response code %u to command %s in %s:%u\n",
+                http_status,
+                pls->is->commands[pls->is->ip].label,
+                __FILE__,
+                __LINE__);
+    TALER_TESTING_interpreter_fail (pls->is);
+    return;
+  }
+  if (NULL != pls->upload_reference)
+  {
+    if ( (MHD_HTTP_OK == http_status) &&
+         (0 != GNUNET_memcmp (&dd->curr_policy_hash,
+                              pls->upload_hash)) )
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+    if ( (MHD_HTTP_OK == http_status) &&
+         (0 != GNUNET_memcmp (&dd->prev_policy_hash,
+                              pls->prev_upload_hash)) )
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+  }
+  TALER_TESTING_interpreter_next (pls->is);
+}
+
+
+/**
+ * Run a "policy lookup" CMD.
+ *
+ * @param cls closure.
+ * @param cmd command currently being run.
+ * @param is interpreter state.
+ */
+static void
+policy_lookup_run (void *cls,
+                   const struct TALER_TESTING_Command *cmd,
+                   struct TALER_TESTING_Interpreter *is)
+{
+  struct PolicyLookupState *pls = cls;
+
+  pls->is = is;
+  if (NULL != pls->upload_reference)
+  {
+    const struct TALER_TESTING_Command *upload_cmd;
+    const struct ANASTASIS_AccountPubP *anastasis_pub;
+
+    upload_cmd = TALER_TESTING_interpreter_lookup_command
+                   (is,
+                   pls->upload_reference);
+    if (NULL == upload_cmd)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        ANASTASIS_TESTING_get_trait_hash (upload_cmd,
+                                          ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+                                          &pls->upload_hash))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        ANASTASIS_TESTING_get_trait_hash (upload_cmd,
+                                          
ANASTASIS_TESTING_TRAIT_HASH_PREVIOUS,
+                                          &pls->prev_upload_hash))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+    if (GNUNET_OK !=
+        ANASTASIS_TESTING_get_trait_account_pub (upload_cmd,
+                                                 0,
+                                                 &anastasis_pub))
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pls->is);
+      return;
+    }
+    pls->anastasis_pub = *anastasis_pub;
+  }
+  pls->lookup = ANASTASIS_policy_lookup (is->ctx,
+                                         pls->anastasis_url,
+                                         &pls->anastasis_pub,
+                                         &policy_lookup_cb,
+                                         pls);
+  if (NULL == pls->lookup)
+  {
+    GNUNET_break (0);
+    TALER_TESTING_interpreter_fail (pls->is);
+    return;
+  }
+}
+
+
+/**
+ * Free the state of a "policy lookup" CMD, and possibly
+ * cancel it if it did not complete.
+ *
+ * @param cls closure.
+ * @param cmd command being freed.
+ */
+static void
+policy_lookup_cleanup (void *cls,
+                       const struct TALER_TESTING_Command *cmd)
+{
+  struct PolicyLookupState *pls = cls;
+
+  if (NULL != pls->lookup)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Command '%s' did not complete (policy lookup)\n",
+                cmd->label);
+    ANASTASIS_policy_lookup_cancel (pls->lookup);
+    pls->lookup = NULL;
+  }
+  GNUNET_free (pls);
+}
+
+
+/**
+ * Make the "policy lookup" command.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the ANASTASIS serving
+ *        the policy store request.
+ * @param http_status expected HTTP status.
+ * @param upload_ref reference to upload command
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_policy_lookup (const char *label,
+                                     const char *anastasis_url,
+                                     unsigned int http_status,
+                                     const char *upload_ref)
+{
+  struct PolicyLookupState *pls;
+
+  GNUNET_assert (NULL != upload_ref);
+  pls = GNUNET_new (struct PolicyLookupState);
+  pls->http_status = http_status;
+  pls->anastasis_url = anastasis_url;
+  pls->upload_reference = upload_ref;
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = pls,
+      .label = label,
+      .run = &policy_lookup_run,
+      .cleanup = &policy_lookup_cleanup
+    };
+
+    return cmd;
+  }
+}
+
+
+/**
+ * Make the "policy lookup" command for a non-existent upload.
+ *
+ * @param label command label
+ * @param anastasis_url base URL of the ANASTASIS serving
+ *        the policy store request.
+ * @return the command
+ */
+struct TALER_TESTING_Command
+ANASTASIS_TESTING_cmd_policy_nx (const char *label,
+                                 const char *anastasis_url)
+{
+  struct PolicyLookupState *pls;
+  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+
+  pls = GNUNET_new (struct PolicyLookupState);
+  pls->http_status = MHD_HTTP_NOT_FOUND;
+  pls->anastasis_url = anastasis_url;
+  priv = GNUNET_CRYPTO_eddsa_key_create ();
+  GNUNET_CRYPTO_eddsa_key_get_public (priv,
+                                      &pls->anastasis_pub.pub);
+  GNUNET_free (priv);
+  {
+    struct TALER_TESTING_Command cmd = {
+      .cls = pls,
+      .label = label,
+      .run = &policy_lookup_run,
+      .cleanup = &policy_lookup_cleanup
+    };
+
+    return cmd;
+  }
+}
diff --git a/src/lib/testing_api_cmd_policy_store.c 
b/src/lib/testing_api_cmd_policy_store.c
index c9bd859..e2d752b 100644
--- a/src/lib/testing_api_cmd_policy_store.c
+++ b/src/lib/testing_api_cmd_policy_store.c
@@ -96,38 +96,33 @@ struct PolicyStoreState
    * Payment identifier.
    */
   const struct ANASTASIS_PaymentSecretP *payment_id;
-};
-
 
-/**
- * State for a "policy lookup" CMD.
- */
-struct PolicyLookupState
-{
   /**
-   * The interpreter state.
+   * Previous upload, or NULL for none. Used to calculate what THIS
+   * upload is based on.
    */
-  struct TALER_TESTING_Interpreter *is;
+  const char *prev_upload;
 
   /**
-   * Eddsa Publickey.
+   * Last upload, or NULL for none, usually same as @e prev_upload.
+   * Used to check the response on #MHD_HTTP_CONFLICT.
    */
-  const struct ANASTASIS_AccountPubP anastasis_pub;
+  const char *last_upload;
 
   /**
-   * URL of the anastasis backend.
+   * Payment order ID we got back, if any. Otherwise NULL.
    */
-  const char *anastasis_url;
+  char *payment_order_id;
 
   /**
-   * Expected status code.
+   * Payment order ID we are to provide in the request, may be NULL.
    */
-  unsigned int http_status;
+  const char *payment_order_req;
 
   /**
-   * The  /policy GET operation handle.
+   * Options for how we are supposed to do the upload.
    */
-  struct ANASTASIS_PolicyLookupOperation *plo;
+  enum ANASTASIS_TESTING_PolicyStoreOption psopt;
 };
 
 /**
@@ -207,22 +202,36 @@ policy_store_cb (void *cls,
              So if you hit this, you might just want to modify
              the code here to handle this better! */return;
         }
-        char str[11];
-        snprintf (str, sizeof str, "%lu", (unsigned long) pss->payment_id->id);
+        pss->payment_order_id = GNUNET_strdup (&m[strlen ("/-/-/")]);
         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                    "Order ID from Sync service is `%s'\n",
-                    str);
+                    "Order ID from Anastasis service is `%s'\n",
+                    pss->payment_order_id);
         memset (&pss->curr_hash,
                 0,
                 sizeof (struct GNUNET_HashCode));
       }
       break;
-    case ANASTASIS_US_CONFLICTING_BACKUP:
+    case ANASTASIS_US_CONFLICTING_POLICY:
       {
-        /* FIXME: Conflicting Recovery Data handling */
-        GNUNET_break (0);
-        TALER_TESTING_interpreter_fail (pss->is);
-        return;
+        const struct TALER_TESTING_Command *ref;
+        const struct GNUNET_HashCode *h;
+
+        ref = TALER_TESTING_interpreter_lookup_command
+                (pss->is,
+                pss->last_upload);
+        GNUNET_assert (NULL != ref);
+        GNUNET_assert (GNUNET_OK ==
+                       ANASTASIS_TESTING_get_trait_hash (ref,
+                                                         
ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+                                                         &h));
+        if (0 != GNUNET_memcmp (h,
+                                &ud->details.recovered_backup.
+                                existing_backup_hash))
+        {
+          GNUNET_break (0);
+          TALER_TESTING_interpreter_fail (pss->is);
+          return;
+        }
       }
     case ANASTASIS_US_HTTP_ERROR:
       break;
@@ -254,6 +263,83 @@ policy_store_run (void *cls,
   struct PolicyStoreState *pss = cls;
 
   pss->is = is;
+  if (NULL != pss->prev_upload)
+  {
+    const struct TALER_TESTING_Command *ref;
+
+    ref = TALER_TESTING_interpreter_lookup_command
+            (is,
+            pss->prev_upload);
+    if (NULL == ref)
+    {
+      GNUNET_break (0);
+      TALER_TESTING_interpreter_fail (pss->is);
+      return;
+    }
+    {
+      const struct GNUNET_HashCode *h;
+
+      if (GNUNET_OK !=
+          ANASTASIS_TESTING_get_trait_hash (ref,
+                                            
ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+                                            &h))
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (pss->is);
+        return;
+      }
+      pss->prev_hash = *h;
+    }
+    {
+      const struct ANASTASIS_AccountPrivP *priv;
+
+      if (GNUNET_OK !=
+          ANASTASIS_TESTING_get_trait_account_priv (ref,
+                                                    0,
+                                                    &priv))
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (pss->is);
+        return;
+      }
+      pss->anastasis_priv = *priv;
+    }
+    {
+      const struct ANASTASIS_AccountPubP *pub;
+
+      if (GNUNET_OK !=
+          ANASTASIS_TESTING_get_trait_account_pub (ref,
+                                                   0,
+                                                   &pub))
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (pss->is);
+        return;
+      }
+      pss->anastasis_pub = *pub;
+    }
+    if (0 != (ANASTASIS_TESTING_PSO_REFERENCE_ORDER_ID & pss->psopt))
+    {
+      const char *order_id;
+
+      if (GNUNET_OK !=
+          TALER_TESTING_get_trait_order_id (ref,
+                                            0,
+                                            &order_id))
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (pss->is);
+        return;
+      }
+      pss->payment_order_req = order_id;
+      if (NULL == pss->payment_order_req)
+      {
+        GNUNET_break (0);
+        TALER_TESTING_interpreter_fail (pss->is);
+        return;
+      }
+    }
+  }
 
   {
     // Create an eddsa private key
@@ -323,6 +409,40 @@ policy_store_cleanup (void *cls,
   GNUNET_free (pss);
 }
 
+/**
+ * Offer internal data to other commands.
+ *
+ * @param cls closure
+ * @param ret[out] result (could be anything)
+ * @param trait name of the trait
+ * @param index index number of the object to extract.
+ * @return #GNUNET_OK on success
+ */
+static int
+policy_store_traits (void *cls,
+                     const void **ret,
+                     const char *trait,
+                     unsigned int index)
+{
+  struct PolicyStoreState *pss = cls;
+  struct TALER_TESTING_Trait traits[] = {
+    ANASTASIS_TESTING_make_trait_hash (ANASTASIS_TESTING_TRAIT_HASH_CURRENT,
+                                       &pss->curr_hash),
+    ANASTASIS_TESTING_make_trait_account_pub (0,
+                                              &pss->anastasis_pub),
+    ANASTASIS_TESTING_make_trait_account_priv (0,
+                                               &pss->anastasis_priv),
+    TALER_TESTING_make_trait_order_id (0,
+                                       pss->payment_order_id),
+    TALER_TESTING_trait_end ()
+  };
+
+  return TALER_TESTING_get_trait (traits,
+                                  ret,
+                                  trait,
+                                  index);
+}
+
 
 /**
  * Make the "policy store" command.
@@ -331,6 +451,7 @@ policy_store_cleanup (void *cls,
  * @param anastasis_url base URL of the anastasis serving
  *        the policy store request.
  * @param http_status expected HTTP status.
+ * @param pso policy store options
  * @param priv private account identifier
  * @param pub account identifier
  * @param payment_id payment identifier
@@ -341,7 +462,10 @@ policy_store_cleanup (void *cls,
 struct TALER_TESTING_Command
 ANASTASIS_TESTING_cmd_policy_store (const char *label,
                                     const char *anastasis_url,
+                                    const char *prev_upload,
                                     unsigned int http_status,
+                                    enum
+                                    ANASTASIS_TESTING_PolicyStoreOption pso,
                                     const struct
                                     ANASTASIS_PaymentSecretP *payment_id,
                                     const void *recovery_data,
@@ -354,13 +478,15 @@ ANASTASIS_TESTING_cmd_policy_store (const char *label,
   pss->recovery_data_size = recovery_data_size;
   pss->payment_id = payment_id;
   pss->http_status = http_status;
+  pss->psopt = pso;
   pss->anastasis_url = anastasis_url;
 
   struct TALER_TESTING_Command cmd = {
     .cls = pss,
     .label = label,
     .run = &policy_store_run,
-    .cleanup = &policy_store_cleanup
+    .cleanup = &policy_store_cleanup,
+    .traits = &policy_store_traits
   };
 
   return cmd;
diff --git a/src/lib/testing_api_trait_account_priv.c 
b/src/lib/testing_api_trait_account_priv.c
new file mode 100644
index 0000000..0f699a9
--- /dev/null
+++ b/src/lib/testing_api_trait_account_priv.c
@@ -0,0 +1,73 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2019 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Privlic License for more details.
+
+  You should have received a copy of the GNU General Privlic
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_trait_account_priv.c
+ * @brief traits to offer a account_priv
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "anastasis_service.h"
+#include "anastasis_testing_lib.h"
+
+#define ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV "anastasis-account_priv"
+
+
+/**
+ * Obtain an account private key from @a cmd.
+ *
+ * @param cmd command to extract the private key from.
+ * @param index the private key's index number.
+ * @param n[out] set to the private key coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_account_priv
+  (const struct TALER_TESTING_Command *cmd,
+  unsigned int index,
+  const struct ANASTASIS_AccountPrivP **priv)
+{
+  return cmd->traits (cmd->cls,
+                      (const void **) priv,
+                      ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV,
+                      index);
+}
+
+
+/**
+ * Offer an account private key.
+ *
+ * @param index usually zero
+ * @param priv the account_priv to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_account_priv
+  (unsigned int index,
+  const struct ANASTASIS_AccountPrivP *priv)
+{
+  struct TALER_TESTING_Trait ret = {
+    .index = index,
+    .trait_name = ANASTASIS_TESTING_TRAIT_ACCOUNT_PRIV,
+    .ptr = (const void *) priv
+  };
+  return ret;
+}
+
+
+/* end of testing_api_trait_account_priv.c */
diff --git a/src/lib/testing_api_trait_account_pub.c 
b/src/lib/testing_api_trait_account_pub.c
new file mode 100644
index 0000000..60d4b28
--- /dev/null
+++ b/src/lib/testing_api_trait_account_pub.c
@@ -0,0 +1,73 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2019 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_trait_account_pub.c
+ * @brief traits to offer a account_pub
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "anastasis_service.h"
+#include "anastasis_testing_lib.h"
+
+#define ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB "anastasis-account_pub"
+
+
+/**
+ * Obtain an account public key from @a cmd.
+ *
+ * @param cmd command to extract the public key from.
+ * @param index the public key's index number.
+ * @param n[out] set to the public key coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_account_pub
+  (const struct TALER_TESTING_Command *cmd,
+  unsigned int index,
+  const struct ANASTASIS_AccountPubP **pub)
+{
+  return cmd->traits (cmd->cls,
+                      (const void **) pub,
+                      ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB,
+                      index);
+}
+
+
+/**
+ * Offer an account public key.
+ *
+ * @param index usually zero
+ * @param h the account_pub to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_account_pub
+  (unsigned int index,
+  const struct ANASTASIS_AccountPubP *h)
+{
+  struct TALER_TESTING_Trait ret = {
+    .index = index,
+    .trait_name = ANASTASIS_TESTING_TRAIT_ACCOUNT_PUB,
+    .ptr = (const void *) h
+  };
+  return ret;
+}
+
+
+/* end of testing_api_trait_account_pub.c */
diff --git a/src/lib/testing_api_trait_hash.c b/src/lib/testing_api_trait_hash.c
new file mode 100644
index 0000000..faf5bb9
--- /dev/null
+++ b/src/lib/testing_api_trait_hash.c
@@ -0,0 +1,73 @@
+/*
+  This file is part of TALER
+  Copyright (C) 2019 Taler Systems SA
+
+  TALER is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published
+  by the Free Software Foundation; either version 3, or (at your
+  option) any later version.
+
+  TALER is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU General Public
+  License along with TALER; see the file COPYING.  If not, see
+  <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file lib/testing_api_trait_hash.c
+ * @brief traits to offer a hash
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "anastasis_service.h"
+#include "anastasis_testing_lib.h"
+
+#define ANASTASIS_TESTING_TRAIT_HASH "anastasis-hash"
+
+
+/**
+ * Obtain a hash from @a cmd.
+ *
+ * @param cmd command to extract the number from.
+ * @param index the number's index number.
+ * @param n[out] set to the number coming from @a cmd.
+ * @return #GNUNET_OK on success.
+ */
+int
+ANASTASIS_TESTING_get_trait_hash
+  (const struct TALER_TESTING_Command *cmd,
+  unsigned int index,
+  const struct GNUNET_HashCode **h)
+{
+  return cmd->traits (cmd->cls,
+                      (const void **) h,
+                      ANASTASIS_TESTING_TRAIT_HASH,
+                      index);
+}
+
+
+/**
+ * Offer a hash.
+ *
+ * @param index the number's index number.
+ * @param h the hash to offer.
+ * @return #GNUNET_OK on success.
+ */
+struct TALER_TESTING_Trait
+ANASTASIS_TESTING_make_trait_hash
+  (unsigned int index,
+  const struct GNUNET_HashCode *h)
+{
+  struct TALER_TESTING_Trait ret = {
+    .index = index,
+    .trait_name = ANASTASIS_TESTING_TRAIT_HASH,
+    .ptr = (const void *) h
+  };
+  return ret;
+}
+
+
+/* end of testing_api_trait_hash.c */
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index 3b8e5ba..12b96d7 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -220,11 +220,14 @@ commit_transaction (void *cls)
  *
  * @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
  */
 static enum ANASTASIS_DB_QueryStatus
 postgres_lookup_pending_payment_by_account (void *cls,
                                             const struct
-                                            ANASTASIS_AccountPubP 
*anastasis_pub)
+                                            ANASTASIS_AccountPubP 
*anastasis_pub,
+                                            void *it_cls)
 {
   struct GNUNET_TIME_Absolute paid_until;
   struct GNUNET_TIME_Relative time_remaining;
@@ -249,32 +252,13 @@ postgres_lookup_pending_payment_by_account (void *cls,
                                                    rs);
   }
 
-  switch (qs)
+  if (qs == ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT)
   {
-  case ANASTASIS_DB_STATUS_HARD_ERROR:
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_SOFT_ERROR:
-    // FIXME: or: retry internally?
-    rollback (pg);
-    return qs;
-  case ANASTASIS_DB_STATUS_NO_RESULTS:
-    return ANASTASIS_EC_DB_STATUS_UNKNOWN_USER;
-  case ANASTASIS_DB_STATUS_SUCCESS_ONE_RESULT:
     time_remaining = GNUNET_TIME_absolute_get_remaining (paid_until);
-    break;
-  default:
-    // FIXME: Some Action
-    rollback (pg);
-    return qs;
-  }
-
-  // rollback if user hasn't paid
-  if (time_remaining.rel_value_us == 0)
-  {
-    rollback (pg);
-    return ANASTASIS_EC_DB_STATUS_PAYMENT_EXPIRED;
+    if ( GNUNET_TIME_round_rel (&time_remaining) == 0)
+      return ANASTASIS_DB_STATUS_PAYMENT_REQUIRED;
   }
+  GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
   return qs;
 }
 
@@ -887,6 +871,7 @@ postgres_lookup_account (void *cls,
 {
   struct PostgresClosure *pg = cls;
   struct GNUNET_TIME_Absolute paid_until;
+  enum ANASTASIS_DB_QueryStatus qs;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (anastasis_pub),
     GNUNET_PQ_query_param_end
@@ -898,10 +883,13 @@ postgres_lookup_account (void *cls,
   };
 
   check_connection (pg);
-  return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
-                                                   "user_select",
-                                                   params,
-                                                   rs);
+  qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                 "user_select",
+                                                 params,
+                                                 rs);
+
+  GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != qs);
+  return qs;
 }
 
 

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



reply via email to

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