gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: -more work on iban logic


From: gnunet
Subject: [taler-anastasis] branch master updated: -more work on iban logic
Date: Mon, 23 Aug 2021 18:22:08 +0200

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

grothoff pushed a commit to branch master
in repository anastasis.

The following commit(s) were added to refs/heads/master by this push:
     new d153d80  -more work on iban logic
d153d80 is described below

commit d153d8036ea14503f812717b8994a4a845ab643e
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Aug 23 18:22:06 2021 +0200

    -more work on iban logic
---
 doc/sphinx/reducer.rst                             |  17 ++-
 .../anastasis_authorization_plugin_iban.c          |  14 ++-
 src/backend/anastasis-httpd_truth.c                |  29 ++++-
 src/cli/resources/03-backup.json                   |  12 +-
 src/cli/resources/04-backup.json                   |  12 +-
 src/cli/resources/05-backup.json                   |  12 +-
 src/cli/resources/06-backup.json                   |  12 +-
 src/cli/test_iban.sh                               |   2 +-
 src/include/anastasis_database_plugin.h            |  26 ++++
 src/reducer/anastasis_api_recovery_redux.c         | 104 +++++++++++++---
 src/stasis/plugin_anastasis_postgres.c             | 135 ++++++++++++++++++++-
 11 files changed, 333 insertions(+), 42 deletions(-)

diff --git a/doc/sphinx/reducer.rst b/doc/sphinx/reducer.rst
index e1ca9ba..320db48 100644
--- a/doc/sphinx/reducer.rst
+++ b/doc/sphinx/reducer.rst
@@ -1641,6 +1641,8 @@ that applications must all handle. States other than 
``solved`` are:
             "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
               "state": "external-instructions",
               "method": "iban",
+              "async": true, // optional
+              "answer_code": 987654321, // optional
               "details": {
                 "...": "..."
               }
@@ -1648,7 +1650,12 @@ that applications must all handle. States other than 
``solved`` are:
           }
         }
 
-    The specific instructions depend on the ``method``.
+    If "async" is "true", then the client should
+    poll for the challenge being satisfied using
+    the "answer_code" that has been provided.
+
+    The specific instructions on how to satisfy
+    the challenge depend on the ``method``.
     They include:
 
       - **iban**: The user must perform a wire transfer from their account to 
the Anastasis provider.
@@ -1659,14 +1666,12 @@ that applications must all handle. States other than 
``solved`` are:
             "challenge_amount": "EUR:1",
             "credit_iban": "DE12345789000",
             "business_name": "Data Loss Incorporated",
-            "wire_transfer_subject": 987654321
+            "wire_transfer_subject": "Anastasis 987654321"
           }
 
         Note that the actual wire transfer subject must contain both
-        the numeric ``wire_transfer_subject`` given above as well as
-        the string ``Anastasis``. Thus, when generating human-readable
-        instructions from the above, the display output should be
-        ``Anastasis 987654321``.
+        the numeric ``answer_code`` as well as
+        the string ``Anastasis``.
 
 **poll:**
 
diff --git a/src/authorization/anastasis_authorization_plugin_iban.c 
b/src/authorization/anastasis_authorization_plugin_iban.c
index 3c72e16..49c2ad5 100644
--- a/src/authorization/anastasis_authorization_plugin_iban.c
+++ b/src/authorization/anastasis_authorization_plugin_iban.c
@@ -328,9 +328,19 @@ respond_with_challenge (struct 
ANASTASIS_AUTHORIZATION_State *as,
     if (TALER_MHD_xmime_matches (mime,
                                  "application/json"))
     {
+      char subject[64];
+
+      GNUNET_snprintf (subject,
+                       sizeof (subject),
+                       "Anastasis %llu",
+                       (unsigned long long) as->code);
       resp = TALER_MHD_MAKE_JSON_PACK (
         GNUNET_JSON_pack_string ("method",
                                  "iban"),
+        GNUNET_JSON_pack_bool ("async",
+                               true),
+        GNUNET_JSON_pack_uint64 ("answer_code",
+                                 as->code),
         GNUNET_JSON_pack_object_steal (
           "details",
           GNUNET_JSON_PACK (
@@ -340,8 +350,8 @@ respond_with_challenge (struct 
ANASTASIS_AUTHORIZATION_State *as,
                                      ctx->business_iban),
             GNUNET_JSON_pack_string ("business_name",
                                      ctx->business_name),
-            GNUNET_JSON_pack_uint64 ("wire_transfer_subject",
-                                     as->code))));
+            GNUNET_JSON_pack_string ("wire_transfer_subject",
+                                     subject))));
     }
     else
     {
diff --git a/src/backend/anastasis-httpd_truth.c 
b/src/backend/anastasis-httpd_truth.c
index 2c757db..3b853dc 100644
--- a/src/backend/anastasis-httpd_truth.c
+++ b/src/backend/anastasis-httpd_truth.c
@@ -1435,6 +1435,33 @@ AH_handler_truth_get (
                                  connection);
       }
       /* continue with authorization plugin below */
+      {
+        enum GNUNET_DB_QueryStatus qs;
+
+        qs = db->get_unlimited_challenge_code (
+          db->cls,
+          &gc->truth_uuid,
+          gc->authorization->code_rotation_period,
+          gc->authorization->code_validity_period,
+          &gc->code);
+        switch (qs)
+        {
+        case GNUNET_DB_STATUS_HARD_ERROR:
+        case GNUNET_DB_STATUS_SOFT_ERROR:
+        case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+          GNUNET_break (0);
+          GNUNET_free (decrypted_truth);
+          return TALER_MHD_reply_with_error (gc->connection,
+                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                             TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                             "create_challenge_code");
+        case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+          /* challenge code was stored successfully*/
+          GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                      "Got challenge code\n");
+          break;
+        }
+      }
       break;
     default:
       GNUNET_break (0);
@@ -1491,7 +1518,7 @@ AH_handler_truth_get (
         return TALER_MHD_reply_with_error (gc->connection,
                                            MHD_HTTP_INTERNAL_SERVER_ERROR,
                                            TALER_EC_GENERIC_DB_FETCH_FAILED,
-                                           "store_challenge_code");
+                                           "create_challenge_code");
       case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
         /* 0 == retry_counter of existing challenge => rate limit exceeded */
         GNUNET_free (decrypted_truth);
diff --git a/src/cli/resources/03-backup.json b/src/cli/resources/03-backup.json
index 9d599d7..4dd5368 100644
--- a/src/cli/resources/03-backup.json
+++ b/src/cli/resources/03-backup.json
@@ -55,7 +55,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #1 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0"
+      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0",
+      "http_status": 200
     },
     "http://localhost:8087/": {
       "methods": [
@@ -73,7 +74,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #2 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG"
+      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG",
+      "http_status": 200
     },
     "http://localhost:8088/": {
       "methods": [
@@ -91,7 +93,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #3 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR"
+      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR",
+      "http_status": 200
     },
     "http://localhost:8089/": {
       "methods": [
@@ -109,7 +112,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #4 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M"
+      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M",
+      "http_status": 200
     }
   },
   "selected_country": "xx",
diff --git a/src/cli/resources/04-backup.json b/src/cli/resources/04-backup.json
index 15c329a..db51f5a 100644
--- a/src/cli/resources/04-backup.json
+++ b/src/cli/resources/04-backup.json
@@ -55,7 +55,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #1 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0"
+      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0",
+      "http_status": 200
     },
     "http://localhost:8087/": {
       "methods": [
@@ -73,7 +74,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #2 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG"
+      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG",
+      "http_status": 200
     },
     "http://localhost:8088/": {
       "methods": [
@@ -91,7 +93,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #3 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR"
+      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR",
+      "http_status": 200
     },
     "http://localhost:8089/": {
       "methods": [
@@ -109,7 +112,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #4 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M"
+      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M",
+      "http_status": 200
     }
   },
   "selected_country": "xx",
diff --git a/src/cli/resources/05-backup.json b/src/cli/resources/05-backup.json
index c0ce8ae..143d9e3 100644
--- a/src/cli/resources/05-backup.json
+++ b/src/cli/resources/05-backup.json
@@ -55,7 +55,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #1 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0"
+      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0",
+      "http_status": 200
     },
     "http://localhost:8087/": {
       "methods": [
@@ -73,7 +74,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #2 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG"
+      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG",
+      "http_status": 200
     },
     "http://localhost:8088/": {
       "methods": [
@@ -91,7 +93,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #3 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR"
+      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR",
+      "http_status": 200
     },
     "http://localhost:8089/": {
       "methods": [
@@ -109,7 +112,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #4 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M"
+      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M",
+      "http_status": 200
     }
   },
   "selected_country": "xx",
diff --git a/src/cli/resources/06-backup.json b/src/cli/resources/06-backup.json
index d1f0b9e..9944a17 100644
--- a/src/cli/resources/06-backup.json
+++ b/src/cli/resources/06-backup.json
@@ -55,7 +55,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #1 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0"
+      "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0",
+      "http_status": 200
     },
     "http://localhost:8087/": {
       "methods": [
@@ -73,7 +74,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #2 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG"
+      "salt": "D378FWXHJB8JHPQFQRZGGV9PWG",
+      "http_status": 200
     },
     "http://localhost:8088/": {
       "methods": [
@@ -91,7 +93,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #3 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR"
+      "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR",
+      "http_status": 200
     },
     "http://localhost:8089/": {
       "methods": [
@@ -109,7 +112,8 @@
       "currency": "TESTKUDOS",
       "business_name": "Data loss #4 Inc.",
       "storage_limit_in_megabytes": 1,
-      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M"
+      "salt": "PN0VJF6KDSBYN40SGRCEXPB07M",
+      "http_status": 200
     }
   },
   "selected_country": "xx",
diff --git a/src/cli/test_iban.sh b/src/cli/test_iban.sh
index 777bcfb..8045db3 100755
--- a/src/cli/test_iban.sh
+++ b/src/cli/test_iban.sh
@@ -429,7 +429,7 @@ SUBJECT="Anastasis ${NUMBER}"
 
 # FIXME-MS: must do wire transfer using $SUBJECT and $AMOUNT here!
 
-#bash
+bash
 
 echo "TEST INCOMPLETE --- BAILING for now"
 
diff --git a/src/include/anastasis_database_plugin.h 
b/src/include/anastasis_database_plugin.h
index 1265f7b..079201d 100644
--- a/src/include/anastasis_database_plugin.h
+++ b/src/include/anastasis_database_plugin.h
@@ -660,6 +660,32 @@ struct ANASTASIS_DatabasePlugin
     uint64_t *code);
 
 
+  /**
+   * Setup challenge code for a given challenge identified by the
+   * challenge public key. The function will first check if there is
+   * already a valid code for this challenge present and won't insert
+   * a new one in this case.  This variant is not rate-limited, will
+   * return the existing challenge if it has not yet expired and will
+   * simply create new challenges when the old ones need to be
+   * rotated.
+   *
+   * @param cls closure
+   * @param truth_uuid the identifier for the challenge
+   * @param rotation_period for how long is the code available
+   * @param validity_period for how long is the code available
+   * @param[out] code set to the code which will be checked for later
+   * @return transaction status,
+   *        #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a code is now in the DB
+   */
+  enum GNUNET_DB_QueryStatus
+  (*get_unlimited_challenge_code)(
+    void *cls,
+    const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
+    struct GNUNET_TIME_Relative rotation_period,
+    struct GNUNET_TIME_Relative validity_period,
+    uint64_t *code);
+
+
   /**
    * Remember in the database that we successfully sent a challenge.
    *
diff --git a/src/reducer/anastasis_api_recovery_redux.c 
b/src/reducer/anastasis_api_recovery_redux.c
index c29a08a..6b85a75 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -398,6 +398,51 @@ find_challenge_in_ri (json_t *state,
 }
 
 
+/**
+ * Find challenge of @a uuid in @a state under "cs".
+ *
+ * @param state the state to search
+ * @param uuid the UUID to search for
+ * @return NULL on error, otherwise challenge entry; RC is NOT incremented
+ */
+static json_t *
+find_challenge_in_cs (json_t *state,
+                      const struct ANASTASIS_CRYPTO_TruthUUIDP *uuid)
+{
+  json_t *rd = json_object_get (state,
+                                "recovery_document");
+  json_t *cs = json_object_get (rd,
+                                "cs");
+  json_t *c;
+  size_t off;
+
+  json_array_foreach (cs, off, c)
+  {
+    struct ANASTASIS_CRYPTO_TruthUUIDP u;
+    struct GNUNET_JSON_Specification spec[] = {
+      GNUNET_JSON_spec_fixed_auto ("uuid",
+                                   &u),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (c,
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break (0);
+      continue;
+    }
+    if (0 !=
+        GNUNET_memcmp (uuid,
+                       &u))
+      continue;
+    return c;
+  }
+  return NULL;
+}
+
+
 /**
  * Defines a callback for the response status for a challenge start
  * operation.
@@ -713,9 +758,17 @@ answer_feedback_cb (
       const json_t *body = csr->details.external_challenge;
       const char *method;
       json_t *details;
+      bool is_async = false;
+      uint64_t code = 0;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_string ("method",
                                  &method),
+        GNUNET_JSON_spec_mark_optional (
+          GNUNET_JSON_spec_bool ("async",
+                                 &is_async)),
+        GNUNET_JSON_spec_mark_optional (
+          GNUNET_JSON_spec_uint64 ("answer_code",
+                                   &code)),
         GNUNET_JSON_spec_json ("details",
                                &details),
         GNUNET_JSON_spec_end ()
@@ -741,7 +794,31 @@ answer_feedback_cb (
                                             err));
         return;
       }
+      if (is_async)
+      {
+        json_t *c = find_challenge_in_cs (sctx->state,
+                                          &cd->uuid);
 
+        if (NULL == c)
+        {
+          GNUNET_break (0);
+          set_state (sctx->state,
+                     ANASTASIS_RECOVERY_STATE_ERROR);
+          sctx->cb (sctx->cb_cls,
+                    TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
+                    sctx->state);
+          sctx_free (sctx);
+          return;
+        }
+        GNUNET_assert (0 ==
+                       json_object_set_new (c,
+                                            "async",
+                                            json_true ()));
+        GNUNET_assert (0 ==
+                       json_object_set_new (c,
+                                            "answer-pin",
+                                            json_integer (code)));
+      }
       reply = GNUNET_JSON_PACK (
         GNUNET_JSON_pack_string ("state",
                                  "external-instructions"),
@@ -815,10 +892,11 @@ solve_challenge_cb (void *cls,
     return;
   }
 
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (sctx->args,
-                         tspec,
-                         NULL, NULL))
+  if ( (NULL != sctx->args) &&
+       (GNUNET_OK !=
+        GNUNET_JSON_parse (sctx->args,
+                           tspec,
+                           NULL, NULL)) )
   {
     GNUNET_break_op (0);
     ANASTASIS_redux_fail_ (sctx->cb,
@@ -845,7 +923,7 @@ solve_challenge_cb (void *cls,
           (! cd->async) )
         continue;
 
-      challenge = find_challenge_in_ri (sctx->state,
+      challenge = find_challenge_in_cs (sctx->state,
                                         &cd->uuid);
       if (NULL == challenge)
       {
@@ -963,6 +1041,7 @@ solve_challenge_cb (void *cls,
     struct ANASTASIS_Challenge *ci = ri->cs[i];
     const struct ANASTASIS_ChallengeDetails *cd;
     int ret;
+    json_t *c;
 
     cd = ANASTASIS_challenge_get_details (ci);
     if (cd->async)
@@ -980,6 +1059,9 @@ solve_challenge_cb (void *cls,
       sctx_free (sctx);
       return;
     }
+    c = find_challenge_in_cs (sctx->state,
+                              &cd->uuid);
+    GNUNET_assert (NULL != c);
     if (0 == strcmp ("question",
                      cd->type))
     {
@@ -999,7 +1081,7 @@ solve_challenge_cb (void *cls,
       }
       /* persist answer, in case payment is required */
       GNUNET_assert (0 ==
-                     json_object_set (challenge,
+                     json_object_set (c,
                                       "answer",
                                       janswer));
       ret = ANASTASIS_challenge_answer (ci,
@@ -1023,7 +1105,7 @@ solve_challenge_cb (void *cls,
         /* persist answer, in case async processing
            happens via poll */
         GNUNET_assert (0 ==
-                       json_object_set (challenge,
+                       json_object_set (c,
                                         "answer-pin",
                                         pin));
         ret = ANASTASIS_challenge_answer2 (ci,
@@ -1316,14 +1398,6 @@ poll_challenges (json_t *state,
     = GNUNET_new (struct SelectChallengeContext);
   json_t *rd;
 
-  if (NULL == arguments)
-  {
-    ANASTASIS_redux_fail_ (cb,
-                           cb_cls,
-                           TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
-                           "arguments missing");
-    return NULL;
-  }
   rd = json_object_get (state,
                         "recovery_document");
   if (NULL == rd)
diff --git a/src/stasis/plugin_anastasis_postgres.c 
b/src/stasis/plugin_anastasis_postgres.c
index 8c06243..506c304 100644
--- a/src/stasis/plugin_anastasis_postgres.c
+++ b/src/stasis/plugin_anastasis_postgres.c
@@ -38,6 +38,12 @@
  */
 #define MAX_RETRIES 3
 
+/**
+ * Maximum value allowed for nonces. Limited to 2^52 to ensure the
+ * numeric value survives a conversion to float by JavaScript.
+ */
+#define NONCE_MAX_VALUE (1LLU << 52)
+
 
 /**
  * Type of the "cls" argument given to each of the functions in
@@ -2125,7 +2131,7 @@ postgres_create_challenge_code (
     }
 
     *code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
-                                      INT64_MAX);
+                                      NONCE_MAX_VALUE);
     *retransmission_date = GNUNET_TIME_UNIT_ZERO_ABS;
     {
       struct GNUNET_PQ_QueryParam params[] = {
@@ -2168,6 +2174,132 @@ retry:
 }
 
 
+/**
+ * Setup challenge code for a given challenge identified by the
+ * challenge public key. The function will first check if there is
+ * already a valid code for this challenge present and won't insert
+ * a new one in this case.  This variant is not rate-limited, will
+ * return the existing challenge if it has not yet expired and will
+ * simply create new challenges when the old ones need to be
+ * rotated.
+ *
+ * @param cls closure
+ * @param truth_uuid the identifier for the challenge
+ * @param rotation_period for how long is the code available
+ * @param validity_period for how long is the code available
+ * @param[out] code set to the code which will be checked for later
+ * @return transaction status,
+ *        #GNUNET_DB_STATUS_SUCCESS_ONE_RESULT if @a code is now in the DB
+ */
+static enum GNUNET_DB_QueryStatus
+postgres_get_unlimited_challenge_code (
+  void *cls,
+  const struct ANASTASIS_CRYPTO_TruthUUIDP *truth_uuid,
+  struct GNUNET_TIME_Relative rotation_period,
+  struct GNUNET_TIME_Relative validity_period,
+  uint64_t *code)
+{
+  struct PostgresClosure *pg = cls;
+  enum GNUNET_DB_QueryStatus qs;
+  struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
+  struct GNUNET_TIME_Absolute expiration_date;
+  struct GNUNET_TIME_Absolute ex_rot;
+
+  check_connection (pg);
+  GNUNET_TIME_round_abs (&now);
+  expiration_date = GNUNET_TIME_absolute_add (now,
+                                              validity_period);
+  ex_rot = GNUNET_TIME_absolute_subtract (now,
+                                          rotation_period);
+  for (unsigned int retries = 0; retries<MAX_RETRIES; retries++)
+  {
+    if (GNUNET_OK !=
+        begin_transaction (pg,
+                           "get_unlimited_challenge_code"))
+    {
+      GNUNET_break (0);
+      return GNUNET_DB_STATUS_HARD_ERROR;
+    }
+
+    {
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (truth_uuid),
+        TALER_PQ_query_param_absolute_time (&now),
+        TALER_PQ_query_param_absolute_time (&ex_rot),
+        GNUNET_PQ_query_param_end
+      };
+      struct GNUNET_PQ_ResultSpec rs[] = {
+        GNUNET_PQ_result_spec_uint64 ("code",
+                                      code),
+        GNUNET_PQ_result_spec_end
+      };
+      enum GNUNET_DB_QueryStatus qs;
+
+      qs = GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
+                                                     
"challengecode_select_meta",
+                                                     params,
+                                                     rs);
+      switch (qs)
+      {
+      case GNUNET_DB_STATUS_HARD_ERROR:
+        GNUNET_break (0);
+        rollback (pg);
+        return qs;
+      case GNUNET_DB_STATUS_SOFT_ERROR:
+        goto retry;
+      case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+        /* no active challenge, create fresh one (below) */
+        break;
+      case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
+        rollback (pg);
+        return qs;
+      }
+    }
+
+    *code = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                      NONCE_MAX_VALUE);
+    {
+      uint32_t retry_counter = UINT32_MAX;
+      struct GNUNET_PQ_QueryParam params[] = {
+        GNUNET_PQ_query_param_auto_from_type (truth_uuid),
+        GNUNET_PQ_query_param_uint64 (code),
+        TALER_PQ_query_param_absolute_time (&now),
+        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)
+      {
+      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:
+        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 qs;
+    return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT;
+retry:
+    rollback (pg);
+  }
+  return GNUNET_DB_STATUS_SOFT_ERROR;
+}
+
+
 /**
  * Remember in the database that we successfully sent a challenge.
  *
@@ -2675,6 +2807,7 @@ libanastasis_plugin_db_postgres_init (void *cls)
   plugin->test_challenge_code_satisfied =
     &postgres_test_challenge_code_satisfied;
   plugin->create_challenge_code = &postgres_create_challenge_code;
+  plugin->get_unlimited_challenge_code = 
&postgres_get_unlimited_challenge_code;
   plugin->mark_challenge_sent = &postgres_mark_challenge_sent;
   plugin->challenge_gc = &postgres_challenge_gc;
   plugin->record_truth_upload_payment = &postgres_record_truth_upload_payment;

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