gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis] branch master updated: fundamental redux refactoring


From: gnunet
Subject: [taler-anastasis] branch master updated: fundamental redux refactoring
Date: Mon, 15 Feb 2021 12:34:38 +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 9b903c7  fundamental redux refactoring
9b903c7 is described below

commit 9b903c7e74a0812457d03cd6a2eb3b4431f7f4ab
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Feb 15 12:34:36 2021 +0100

    fundamental redux refactoring
---
 contrib/gana                               |   2 +-
 src/cli/anastasis-cli-redux.c              |   3 +-
 src/include/anastasis_redux.h              | 153 +------
 src/reducer/anastasis_api_backup_redux.c   | 143 +++----
 src/reducer/anastasis_api_recovery_redux.c | 114 +++---
 src/reducer/anastasis_api_redux.c          | 629 ++++++++++++++++-------------
 src/reducer/anastasis_api_redux.h          | 165 +++++++-
 7 files changed, 636 insertions(+), 573 deletions(-)

diff --git a/contrib/gana b/contrib/gana
index 30748ad..c17bb5f 160000
--- a/contrib/gana
+++ b/contrib/gana
@@ -1 +1 @@
-Subproject commit 30748ada3fa0b5d5281dca87b117e774db62a431
+Subproject commit c17bb5f294870f1179c3f104bafbe3ad9992c67e
diff --git a/src/cli/anastasis-cli-redux.c b/src/cli/anastasis-cli-redux.c
index 1a8533b..962cd10 100644
--- a/src/cli/anastasis-cli-redux.c
+++ b/src/cli/anastasis-cli-redux.c
@@ -166,6 +166,7 @@ shutdown_task (void *cls)
     ANASTASIS_redux_action_cancel (ra);
     ra = NULL;
   }
+  ANASTASIS_redux_done ();
   if (NULL != ctx)
   {
     GNUNET_CURL_fini (ctx);
@@ -308,10 +309,10 @@ run (void *cls,
     ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
                             &rc);
     rc = GNUNET_CURL_gnunet_rc_create (ctx);
+    ANASTASIS_redux_init (ctx);
     ra = ANASTASIS_redux_action (prev_state,
                                  action,
                                  arguments,
-                                 ctx,
                                  &action_cb,
                                  cls);
   }
diff --git a/src/include/anastasis_redux.h b/src/include/anastasis_redux.h
index c8241da..7a0ff53 100644
--- a/src/include/anastasis_redux.h
+++ b/src/include/anastasis_redux.h
@@ -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
@@ -14,7 +14,7 @@
   Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
 */
 /**
- * @file lib/anastasis_redux.h
+ * @file include/anastasis_redux.h
  * @brief anastasis reducer api
  * @author Christian Grothoff
  * @author Dominik Meister
@@ -29,124 +29,20 @@
 #include <regex.h>
 
 
-#define ANASTASIS_GENERIC_STATES(REDUX_STATE) \
-  REDUX_STATE (ERROR) \
-  REDUX_STATE (CONTINENT_SELECTING)   \
-  REDUX_STATE (COUNTRY_SELECTING)  \
-  REDUX_STATE (USER_ATTRIBUTES_COLLECTING)
-
-#define GENERATE_GENERIC_ENUM(ENUM) ANASTASIS_GENERIC_STATE_ ## ENUM,
-
-enum ANASTASIS_GenericState
-{
-  ANASTASIS_GENERIC_STATES (GENERATE_GENERIC_ENUM)
-};
-
-#undef GENERATE_GENERIC_ENUM
-
-#define ANASTASIS_BACKUP_STATES(REDUX_STATE) \
-  ANASTASIS_GENERIC_STATES (REDUX_STATE) \
-  REDUX_STATE (AUTHENTICATIONS_EDITING)  \
-  REDUX_STATE (POLICIES_REVIEWING)   \
-  REDUX_STATE (SECRET_EDITING) \
-  REDUX_STATE (POLICIES_PAYING) \
-  REDUX_STATE (BACKUP_FINISHED)
-
-#define GENERATE_BACKUP_ENUM(ENUM) ANASTASIS_BACKUP_STATE_ ## ENUM,
-
-enum ANASTASIS_BackupState
-{
-  ANASTASIS_BACKUP_STATES (GENERATE_BACKUP_ENUM)
-};
-
-#undef GENERATE_BACKUP_ENUM
-
-#define ANASTASIS_RECOVERY_STATES(REDUX_STATE) \
-  ANASTASIS_GENERIC_STATES (REDUX_STATE) \
-  REDUX_STATE (CHALLENGE_SELECTING)  \
-  REDUX_STATE (CHALLENGE_PAYING)   \
-  REDUX_STATE (CHALLENGE_SOLVING)  \
-  REDUX_STATE (RECOVERY_FINISHED)
-
-#define GENERATE_RECOVERY_ENUM(ENUM) ANASTASIS_RECOVERY_STATE_ ## ENUM,
-
-enum ANASTASIS_RecoveryState
-{
-  ANASTASIS_RECOVERY_STATES (GENERATE_RECOVERY_ENUM)
-};
-
-#undef GENERATE_RECOVERY_ENUM
-
-
-/**
- * JSON containing country specific identity attributes to ask the user for.
- */
-extern const json_t *redux_id_attr;
-
-/**
- * Currency of chosen country
- */
-extern const char *currency;
-
-
-/**
- * Returns the enum value to a string value of a state.
- *
- * @param state_string
- * @return #ANASTASIS_GENERIC_STATE_ERROR on error
- */
-enum ANASTASIS_GenericState
-ANASTASIS_generic_state_from_string (const char *state_string);
-
-
-/**
- * Returns the string value of a state.
- *
- * @param state_string
- * @return NULL on error
- */
-const char *
-ANASTASIS_generic_state_to_string (enum ANASTASIS_GenericState gs);
-
-
-/**
- * Returns the enum value to a string value of a state.
- *
- * @param state_string
- * @return #ANASTASIS_BACKUP_STATE_ERROR on error
- */
-enum ANASTASIS_BackupState
-ANASTASIS_backup_state_from_string (const char *state_string);
-
-
 /**
- * Returns the string value of a state.
+ * Initialize reducer subsystem.
  *
- * @param state_string
- * @return NULL on error
+ * @param ctx context to use for CURL requests.
  */
-const char *
-ANASTASIS_backup_state_to_string (enum ANASTASIS_BackupState bs);
-
-
-/**
- * Returns the enum value to a string value of a state.
- *
- * @param state_string
- * @return XXX on error
- */
-enum ANASTASIS_RecoveryState
-ANASTASIS_recovery_state_from_string (const char *state_string);
+void
+ANASTASIS_redux_init (struct GNUNET_CURL_Context *ctx);
 
 
 /**
- * Returns the string value of a state.
- *
- * @param state_string
- * @return NULL on error
+ * Terminate reducer subsystem.
  */
-const char *
-ANASTASIS_recovery_state_to_string (enum ANASTASIS_RecoveryState rs);
+void
+ANASTASIS_redux_done (void);
 
 
 /**
@@ -185,10 +81,9 @@ ANASTASIS_recovery_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg);
  * @param new_state the new state of the operation (client should 
json_incref() to keep an alias)
  */
 typedef void
-(*ANASTASIS_ActionCallback)(
-  void *cls,
-  enum TALER_ErrorCode error,
-  json_t *new_state);
+(*ANASTASIS_ActionCallback)(void *cls,
+                            enum TALER_ErrorCode error,
+                            json_t *new_state);
 
 
 /**
@@ -197,15 +92,6 @@ typedef void
 struct ANASTASIS_ReduxAction;
 
 
-/**
- * Cancel ongoing redux action.
- *
- * @param ra action to cancel
- */
-void
-ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction *ra);
-
-
 /**
  * Operates on a state depending on given #ANASTASIS_BackupState
  * or #ANASTASIS_RecoveryState and #ANASTASIS_BackupAction or
@@ -217,7 +103,6 @@ ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction 
*ra);
  * @param state input state
  * @param action what action to perform
  * @param arguments data for the @a action
- * @param ctx Curl context
  * @param cb function to call with the result
  * @param cb_cls closure for @a cb
  * @return failure state or new state
@@ -226,23 +111,17 @@ struct ANASTASIS_ReduxAction *
 ANASTASIS_redux_action (const json_t *state,
                         const char *action,
                         const json_t *arguments,
-                        struct GNUNET_CURL_Context *ctx,
                         ANASTASIS_ActionCallback cb,
                         void *cb_cls);
 
 
 /**
- * Function to return a json error response.
+ * Cancel ongoing redux action.
  *
- * @param cb callback to give error to
- * @param cb_cls callback closure
- * @param ec error code
- * @param detail error detail
+ * @param ra action to cancel
  */
 void
-ANASTASIS_redux_fail (ANASTASIS_ActionCallback cb,
-                      void *cb_cls,
-                      enum TALER_ErrorCode ec,
-                      const char *detail);
+ANASTASIS_redux_action_cancel (struct ANASTASIS_ReduxAction *ra);
+
 
 #endif  /* _ANASTASIS_REDUX_H */
diff --git a/src/reducer/anastasis_api_backup_redux.c 
b/src/reducer/anastasis_api_backup_redux.c
index 417b94a..eaf1bb0 100644
--- a/src/reducer/anastasis_api_backup_redux.c
+++ b/src/reducer/anastasis_api_backup_redux.c
@@ -35,7 +35,7 @@ static const char *backup_strings[] = {
 
 
 enum ANASTASIS_BackupState
-ANASTASIS_backup_state_from_string (const char *state_string)
+ANASTASIS_backup_state_from_string_ (const char *state_string)
 {
   for (enum ANASTASIS_BackupState i = 0;
        i < sizeof (backup_strings) / sizeof(*backup_strings);
@@ -48,7 +48,7 @@ ANASTASIS_backup_state_from_string (const char *state_string)
 
 
 const char *
-ANASTASIS_backup_state_to_string (enum ANASTASIS_BackupState bs)
+ANASTASIS_backup_state_to_string_ (enum ANASTASIS_BackupState bs)
 {
   if ( (bs < 0) ||
        (bs >= sizeof (backup_strings) / sizeof(*backup_strings)) )
@@ -75,11 +75,6 @@ struct TruthUploadState
    */
   struct ANASTASIS_CRYPTO_PowSalt backend_salt;
 
-  /**
-   * Curl context.
-   */
-  struct GNUNET_CURL_Context *ctx;
-
   /**
    * The ID data to generate user identifier
    */
@@ -255,14 +250,12 @@ static unsigned int policy_arr_length = 0;
  *
  *  @param state FIXME: Description
  *  @param arguments FIXME: Description
- *  @param ctx Curl context
  *  @param cb FIXME: Description
  *  @param cb_cls FIXME: Description
  */
 typedef struct ANASTASIS_ReduxAction *
 (*DispatchHandler)(json_t *state,
                    const json_t *arguments,
-                   struct GNUNET_CURL_Context *ctx,
                    ANASTASIS_ActionCallback cb,
                    void *cb_cls);
 
@@ -322,7 +315,7 @@ ANASTASIS_backup_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   size_t index;
   json_t *root;
   json_t *continents = json_array ();
-  json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
+  const json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
 
   GNUNET_assert (NULL != redux_countries);
   root = json_object_get (redux_countries,
@@ -352,7 +345,7 @@ ANASTASIS_backup_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   }
   initial_state = json_pack ("{s:s, s:o}",
                              "backup_state",
-                             ANASTASIS_generic_state_to_string (
+                             ANASTASIS_generic_state_to_string_ (
                                ANASTASIS_BACKUP_STATE_CONTINENT_SELECTING),
                              "continents",
                              continents);
@@ -368,7 +361,6 @@ ANASTASIS_backup_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -376,7 +368,6 @@ ANASTASIS_backup_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
 static struct ANASTASIS_ReduxAction *
 add_authentication (json_t *state,
                     const json_t *arguments,
-                    struct GNUNET_CURL_Context *ctx,
                     ANASTASIS_ActionCallback cb,
                     void *cb_cls)
 {
@@ -390,11 +381,12 @@ add_authentication (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Authentication method required!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -406,11 +398,11 @@ add_authentication (json_t *state,
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
                                (json_int_t)
-                               TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                               
TALER_EC_ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED,
                                "hint",
                                "Authentication method not supported!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_AUTHENTICATION_METHOD_NOT_SUPPORTED,
         error);
     return NULL;
   }
@@ -420,11 +412,11 @@ add_authentication (json_t *state,
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
                                (json_int_t)
-                               TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Authentication data missing!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -675,7 +667,6 @@ method_candidate (struct PolicyBuilder *pb,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -683,7 +674,6 @@ method_candidate (struct PolicyBuilder *pb,
 static struct ANASTASIS_ReduxAction *
 done_authentication (json_t *state,
                      const json_t *arguments,
-                     struct GNUNET_CURL_Context *ctx,
                      ANASTASIS_ActionCallback cb,
                      void *cb_cls)
 {
@@ -726,7 +716,7 @@ done_authentication (json_t *state,
                                            "policies",
                                            pb.policies));
   set_state (state,
-             ANASTASIS_backup_state_to_string (
+             ANASTASIS_backup_state_to_string_ (
                ANASTASIS_BACKUP_STATE_POLICIES_REVIEWING));
   cb (cb_cls,
       TALER_EC_NONE,
@@ -742,7 +732,6 @@ done_authentication (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -750,7 +739,6 @@ done_authentication (json_t *state,
 static struct ANASTASIS_ReduxAction *
 del_authentication (json_t *state,
                     const json_t *arguments,
-                    struct GNUNET_CURL_Context *ctx,
                     ANASTASIS_ActionCallback cb,
                     void *cb_cls)
 {
@@ -758,11 +746,12 @@ del_authentication (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Arguments missing!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -777,11 +766,12 @@ del_authentication (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
                                "hint",
                                "Operation failed");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
         error);
     return NULL;
   }
@@ -800,7 +790,6 @@ del_authentication (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -808,7 +797,6 @@ del_authentication (json_t *state,
 static struct ANASTASIS_ReduxAction *
 add_policy (json_t *state,
             const json_t *arguments,
-            struct GNUNET_CURL_Context *ctx,
             ANASTASIS_ActionCallback cb,
             void *cb_cls)
 {
@@ -816,11 +804,12 @@ add_policy (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Arguments missing!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -845,11 +834,11 @@ add_policy (json_t *state,
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
                                (json_int_t)
-                               TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Policy is malformed!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -936,7 +925,6 @@ add_policy (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -944,7 +932,6 @@ add_policy (json_t *state,
 static struct ANASTASIS_ReduxAction *
 del_policy (json_t *state,
             const json_t *arguments,
-            struct GNUNET_CURL_Context *ctx,
             ANASTASIS_ActionCallback cb,
             void *cb_cls)
 {
@@ -952,11 +939,12 @@ del_policy (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Arguments missing!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     return NULL;
   }
@@ -972,11 +960,12 @@ del_policy (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               
TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
                                "hint",
                                "Operation failed");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID_FOR_STATE,
         error);
     return NULL;
   }
@@ -1144,7 +1133,6 @@ initialize_truths (json_t *state)
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -1152,13 +1140,12 @@ initialize_truths (json_t *state)
 static struct ANASTASIS_ReduxAction *
 done_policy_review (json_t *state,
                     const json_t *arguments,
-                    struct GNUNET_CURL_Context *ctx,
                     ANASTASIS_ActionCallback cb,
                     void *cb_cls)
 {
   GNUNET_assert (NULL != state);
   set_state (state,
-             ANASTASIS_backup_state_to_string (
+             ANASTASIS_backup_state_to_string_ (
                ANASTASIS_BACKUP_STATE_SECRET_EDITING));
 
   GNUNET_assert (0 ==
@@ -1466,7 +1453,7 @@ secret_share_payment_cb (void *cls,
   sss->payment_order_id = GNUNET_strdup (pd.order_id);
   TALER_MERCHANT_parse_pay_uri_free (&pd);
   set_state (sss->state,
-             ANASTASIS_backup_state_to_string (
+             ANASTASIS_backup_state_to_string_ (
                ANASTASIS_BACKUP_STATE_POLICIES_PAYING));
   if (check_uploads (rec_doc_uploads, false))
   {
@@ -1525,7 +1512,7 @@ secret_share_result_cb (void *cls,
       if (check_uploads (rec_doc_uploads, true))
       {
         set_state (sss->state,
-                   ANASTASIS_backup_state_to_string (
+                   ANASTASIS_backup_state_to_string_ (
                      ANASTASIS_BACKUP_STATE_BACKUP_FINISHED));
         sss->cb (sss->cb_cls,
                  TALER_EC_NONE,
@@ -1548,7 +1535,7 @@ secret_share_result_cb (void *cls,
                                "hint",
                                "Unexpected response code!");
     sss->cb (sss->cb_cls,
-             TALER_EC_INVALID,  // FIXME: ERROR CODE
+             TALER_EC_ANASTASIS_REDUCER_BACKEND_FAILURE,
              error);
     sss->cb = NULL;
     return;
@@ -1587,14 +1574,12 @@ free_enter_secret (void *cls)
  *
  * @param state json state to operate on
  * @param provider_ids ids of providers to upload recovery document explicitly 
to
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  */
 static void
 upload_rec_documents (json_t *state,
                       json_t *provider_ids,
-                      struct GNUNET_CURL_Context *ctx,
                       ANASTASIS_ActionCallback cb,
                       void *cb_cls)
 {
@@ -1648,7 +1633,7 @@ upload_rec_documents (json_t *state,
 
   sss->state = json_incref (state);
   // FIXME: implement PaymentDetails
-  sss->sso = ANASTASIS_secret_share (ctx,
+  sss->sso = ANASTASIS_secret_share (ANASTASIS_REDUX_ctx_,
                                      sss->id_data,
                                      policy_arr,
                                      policy_arr_length,
@@ -1719,7 +1704,7 @@ truth_upload_cb (void *cls,
 
     }
     set_state (tus->state,
-               ANASTASIS_backup_state_to_string (
+               ANASTASIS_backup_state_to_string_ (
                  ANASTASIS_BACKUP_STATE_POLICIES_PAYING));
     tus->cb (tus->cb_cls,
              TALER_EC_NONE,
@@ -1761,7 +1746,6 @@ truth_upload_cb (void *cls,
     // try uploading recovery document
     upload_rec_documents (tus->state,
                           NULL,
-                          tus->ctx,
                           tus->cb,
                           tus->cb_cls);
   }
@@ -1773,14 +1757,12 @@ truth_upload_cb (void *cls,
  *
  * @param state state to operate on
  * @param truth_indices indices of truths to upload explicitly
- * @param ctx CURL context
  * @param cb callback (#ANASTASIS_ActionCallback) to call after upload
  * @param cb_cls callback closure
  */
 static void
 upload_truths (json_t *state,
                json_t *truth_indices,
-               struct GNUNET_CURL_Context *ctx,
                ANASTASIS_ActionCallback cb,
                void *cb_cls)
 {
@@ -1811,7 +1793,7 @@ upload_truths (json_t *state,
           if (truth_index == tus_arr[i]->index)
           {
             tus_arr[i]->tuo = ANASTASIS_truth_upload (
-              tus_arr[i]->ctx,
+              ANASTASIS_REDUX_ctx_,
               &tus_arr[i]->user_id,
               tus_arr[i]->anastasis_url,
               tus_arr[i]->method,
@@ -1847,7 +1829,7 @@ upload_truths (json_t *state,
       {
         if ((int) json_integer_value (truth) == tus_arr[i]->index)
         {
-          tus_arr[i]->tuo = ANASTASIS_truth_upload (tus_arr[i]->ctx,
+          tus_arr[i]->tuo = ANASTASIS_truth_upload (ANASTASIS_REDUX_ctx_,
                                                     &tus_arr[i]->user_id,
                                                     tus_arr[i]->anastasis_url,
                                                     tus_arr[i]->method,
@@ -1915,7 +1897,6 @@ upload_truths (json_t *state,
       tus->index = truth_index;
       tus->cb = cb;
       tus->cb_cls = cb_cls;
-      tus->ctx = ctx;
 
       if (0 == strcmp ("question", tus->method))
       {
@@ -1933,7 +1914,7 @@ upload_truths (json_t *state,
       GNUNET_array_append (tus_arr,
                            tus_arr_length,
                            tus);
-      tus->tuo = ANASTASIS_truth_upload (tus->ctx,
+      tus->tuo = ANASTASIS_truth_upload (ANASTASIS_REDUX_ctx_,
                                          &tus->user_id,
                                          tus->anastasis_url,
                                          tus->method,
@@ -1963,7 +1944,6 @@ upload_truths (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -1971,7 +1951,6 @@ upload_truths (json_t *state,
 static struct ANASTASIS_ReduxAction *
 enter_secret (json_t *state,
               const json_t *arguments,
-              struct GNUNET_CURL_Context *ctx,
               ANASTASIS_ActionCallback cb,
               void *cb_cls)
 {
@@ -1982,11 +1961,12 @@ enter_secret (json_t *state,
   {
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
-                               (json_int_t) TALER_EC_INVALID,
+                               (json_int_t)
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Arguments missing!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     json_decref (error);
     return NULL;
@@ -1999,11 +1979,11 @@ enter_secret (json_t *state,
     json_t *error = json_pack ("{s:I, s:s}",
                                "code",
                                (json_int_t)
-                               TALER_EC_GENERIC_PARAMETER_MALFORMED,
+                               TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
                                "hint",
                                "Secret is malformed!");
     cb (cb_cls,
-        TALER_EC_INVALID,
+        TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
         error);
     json_decref (error);
     return NULL;
@@ -2019,7 +1999,6 @@ enter_secret (json_t *state,
   upload_truths (state,
                  json_object_get (state,
                                   "truths"),
-                 ctx,
                  cb,
                  cb_cls);
   return ra;
@@ -2033,7 +2012,6 @@ enter_secret (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -2041,7 +2019,6 @@ enter_secret (json_t *state,
 static struct ANASTASIS_ReduxAction *
 pay_backup (json_t *state,
             const json_t *arguments,
-            struct GNUNET_CURL_Context *ctx,
             ANASTASIS_ActionCallback cb,
             void *cb_cls)
 {
@@ -2054,7 +2031,6 @@ pay_backup (json_t *state,
     upload_rec_documents (state,
                           json_object_get (arguments,
                                            "provider_id"),
-                          ctx,
                           cb,
                           cb_cls);
   }
@@ -2064,7 +2040,6 @@ pay_backup (json_t *state,
     upload_truths (state,
                    json_object_get (arguments,
                                     "truth_index"),
-                   ctx,
                    cb,
                    cb_cls);
   }
@@ -2078,13 +2053,11 @@ pay_backup (json_t *state,
     if (check_uploads (truth_uploads, true))
       upload_rec_documents (state,
                             NULL,
-                            ctx,
                             cb,
                             cb_cls);
     else
       upload_truths (state,
                      NULL,
-                     ctx,
                      cb,
                      cb_cls);
   }
@@ -2099,7 +2072,6 @@ pay_backup (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -2107,14 +2079,13 @@ pay_backup (json_t *state,
 static struct ANASTASIS_ReduxAction *
 back_finished (json_t *state,
                const json_t *arguments,
-               struct GNUNET_CURL_Context *ctx,
                ANASTASIS_ActionCallback cb,
                void *cb_cls)
 {
   // FIXME: implement
   GNUNET_assert (NULL != state);
   set_state (state,
-             ANASTASIS_backup_state_to_string (
+             ANASTASIS_backup_state_to_string_ (
                ANASTASIS_BACKUP_STATE_SECRET_EDITING));
 
   cb (cb_cls,
@@ -2130,7 +2101,6 @@ back_finished (json_t *state,
  * by a callback function.
  * This function can do network access to talk to anastasis service providers.
  *
- * @param ctx the CURL context used to connect to the backend
  * @param[in,out] state input/output state (to be modified)
  * @param action what action to perform
  * @param arguments data for the @a action
@@ -2138,8 +2108,7 @@ back_finished (json_t *state,
  * @param cb_cls closure for @a cb
  */
 struct ANASTASIS_ReduxAction *
-ANASTASIS_backup_action_ (struct GNUNET_CURL_Context *ctx,
-                          json_t *state,
+ANASTASIS_backup_action_ (json_t *state,
                           const char *action,
                           const json_t *arguments,
                           ANASTASIS_ActionCallback cb,
@@ -2217,19 +2186,12 @@ ANASTASIS_backup_action_ (struct GNUNET_CURL_Context 
*ctx,
                                                       "backup_state"));
   enum ANASTASIS_BackupState bs;
 
-  if (NULL == s)
-  {
-    GNUNET_break (0);
-    cb (cb_cls,
-        TALER_EC_INVALID, // FIXME: Define correct error code
-        NULL);
-    return NULL;
-  }
-  bs = ANASTASIS_backup_state_from_string (s);
+  GNUNET_assert (NULL != s);
+  bs = ANASTASIS_backup_state_from_string_ (s);
   if (ANASTASIS_BACKUP_STATE_ERROR == bs)
   {
     cb (cb_cls,
-        TALER_EC_INVALID, // FIXME: Define correct error code
+        TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
         NULL);
     return NULL;
   }
@@ -2241,14 +2203,13 @@ ANASTASIS_backup_action_ (struct GNUNET_CURL_Context 
*ctx,
     {
       return dispatchers[i].fun (state,
                                  arguments,
-                                 ctx,
                                  cb,
                                  cb_cls);
     }
   }
-  ANASTASIS_redux_fail (cb,
-                        cb_cls,
-                        TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                        action);
+  ANASTASIS_redux_fail_ (cb,
+                         cb_cls,
+                         TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
+                         action);
   return NULL;
 }
diff --git a/src/reducer/anastasis_api_recovery_redux.c 
b/src/reducer/anastasis_api_recovery_redux.c
index 5d4b375..b795568 100644
--- a/src/reducer/anastasis_api_recovery_redux.c
+++ b/src/reducer/anastasis_api_recovery_redux.c
@@ -36,7 +36,7 @@ static const char *recovery_strings[] = {
 
 
 enum ANASTASIS_RecoveryState
-ANASTASIS_recovery_state_from_string (const char *state_string)
+ANASTASIS_recovery_state_from_string_ (const char *state_string)
 {
   for (enum ANASTASIS_RecoveryState i = 0;
        i < sizeof (recovery_strings) / sizeof(*recovery_strings);
@@ -49,7 +49,7 @@ ANASTASIS_recovery_state_from_string (const char 
*state_string)
 
 
 const char *
-ANASTASIS_recovery_state_to_string (enum ANASTASIS_RecoveryState rs)
+ANASTASIS_recovery_state_to_string_ (enum ANASTASIS_RecoveryState rs)
 {
   if ( (rs < 0) ||
        (rs >= sizeof (recovery_strings) / sizeof(*recovery_strings)) )
@@ -66,14 +66,12 @@ ANASTASIS_recovery_state_to_string (enum 
ANASTASIS_RecoveryState rs)
  *
  * @param state FIXME: Description
  * @param arguments FIXME: Description
- * @param ctx Curl context
  * @param cb FIXME: Description
  * @param cb_cls FIXME: Description
  */
 typedef struct ANASTASIS_ReduxAction *
 (*DispatchHandler)(json_t *state,
                    const json_t *arguments,
-                   struct GNUNET_CURL_Context *ctx,
                    ANASTASIS_ActionCallback cb,
                    void *cb_cls);
 
@@ -174,10 +172,6 @@ challenge_payment_cb (void *cls,
   json_t *challenge;
   struct ChallengeState *cs = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-              "At %s:%d the taler pay url is %s\n",
-              __FILE__, __LINE__,
-              taler_pay_url);
   if (http_status != MHD_HTTP_PAYMENT_REQUIRED)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -186,10 +180,10 @@ challenge_payment_cb (void *cls,
                 http_status,
                 __FILE__,
                 __LINE__);
-    ANASTASIS_redux_fail (cs->cb,
-                          cs->cb_cls,
-                          TALER_EC_INVALID, // FIXME: Error code
-                          "Unexpected response code!");
+    ANASTASIS_redux_fail_ (cs->cb,
+                           cs->cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_BACKEND_FAILURE,
+                           "Unexpected response code!");
     return;
   }
 
@@ -201,10 +195,10 @@ challenge_payment_cb (void *cls,
                 "Did not find `%s' in `%s'\n",
                 "/-/-/",
                 taler_pay_url);
-    ANASTASIS_redux_fail (cs->cb,
-                          cs->cb_cls,
-                          TALER_EC_INVALID, // FIXME: Error code
-                          "Invalid pay uri!");
+    ANASTASIS_redux_fail_ (cs->cb,
+                           cs->cb_cls,
+                           TALER_EC_INVALID, // FIXME: Error code
+                           "Invalid pay uri!");
     return;
   }
   m = strstr (taler_pay_url, "/-/-/");
@@ -214,10 +208,10 @@ challenge_payment_cb (void *cls,
                 "Did not find `%s' in `%s'\n",
                 "/-/-/",
                 taler_pay_url);
-    ANASTASIS_redux_fail (cs->cb,
-                          cs->cb_cls,
-                          TALER_EC_INVALID, // FIXME: Error code
-                          "Invalid pay uri!");
+    ANASTASIS_redux_fail_ (cs->cb,
+                           cs->cb_cls,
+                           TALER_EC_INVALID, // FIXME: Error code
+                           "Invalid pay uri!");
 
     /* NOTE: The above is a simplifying assumption for the
         test-logic, hitting this code merely means that
@@ -236,7 +230,7 @@ challenge_payment_cb (void *cls,
               cs->payment_order_id);
 
   set_state (cs->state,
-             ANASTASIS_recovery_state_to_string (
+             ANASTASIS_recovery_state_to_string_ (
                ANASTASIS_RECOVERY_STATE_CHALLENGE_PAYING));
 
   recovery_information = json_object_get (cs->state,
@@ -275,17 +269,17 @@ challenge_start_cb (void *cls,
 
   if (http_status_code != MHD_HTTP_OK)
   {
-    ANASTASIS_redux_fail (cs->cb,
-                          cs->cb_cls,
-                          TALER_EC_INVALID, // FIXME: Error code
-                          "Unexpected response code!");
+    ANASTASIS_redux_fail_ (cs->cb,
+                           cs->cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_BACKEND_FAILURE,
+                           "Unexpected response code!");
 
     return;
   }
   else
   {
     set_state (cs->state,
-               ANASTASIS_recovery_state_to_string (
+               ANASTASIS_recovery_state_to_string_ (
                  ANASTASIS_RECOVERY_STATE_CHALLENGE_SOLVING));
   }
   ci = ANASTASIS_challenge_get_details (cs->c);
@@ -329,7 +323,7 @@ ANASTASIS_recovery_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   size_t index;
   json_t *root;
   json_t *continents = json_array ();
-  json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
+  const json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
 
   GNUNET_assert (NULL != redux_countries);
   root = json_object_get (redux_countries, "countries");
@@ -357,7 +351,7 @@ ANASTASIS_recovery_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
   }
   initial_state = json_pack ("{s:s, s:o}",
                              "recovery_state",
-                             ANASTASIS_generic_state_to_string (
+                             ANASTASIS_generic_state_to_string_ (
                                ANASTASIS_RECOVERY_STATE_CONTINENT_SELECTING),
                              "continents",
                              continents);
@@ -369,16 +363,15 @@ ANASTASIS_recovery_start (const struct 
GNUNET_CONFIGURATION_Handle *cfg)
 static struct ANASTASIS_ReduxAction *
 select_challenge (json_t *state,
                   const json_t *arguments,
-                  struct GNUNET_CURL_Context *ctx,
                   ANASTASIS_ActionCallback cb,
                   void *cb_cls)
 {
   if (NULL == arguments)
   {
-    ANASTASIS_redux_fail (cb,
-                          cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                          "select_challenge");
+    ANASTASIS_redux_fail_ (cb,
+                           cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+                           "select_challenge");
     return NULL;
   }
   json_t *recovery_information;
@@ -441,17 +434,16 @@ select_challenge (json_t *state,
 static struct ANASTASIS_ReduxAction *
 pay_challenge (json_t *state,
                const json_t *arguments,
-               struct GNUNET_CURL_Context *ctx,
                ANASTASIS_ActionCallback cb,
                void *cb_cls)
 {
   // FIXME: implement
   if (NULL == arguments)
   {
-    ANASTASIS_redux_fail (cb,
-                          cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                          "pay_challenge");
+    ANASTASIS_redux_fail_ (cb,
+                           cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+                           "pay_challenge");
     return NULL;
   }
 
@@ -518,10 +510,10 @@ challenge_answer_cb (void *af_cls,
   struct ChallengeState *cs = af_cls;
   if (http_status_code != MHD_HTTP_OK)
   {
-    ANASTASIS_redux_fail (cs->cb,
-                          cs->cb_cls,
-                          ec,
-                          "Unexpected response code!");
+    ANASTASIS_redux_fail_ (cs->cb,
+                           cs->cb_cls,
+                           ec,
+                           "Unexpected response code!");
     return;
   }
   if (check_policy_fulfilled (cs->state))
@@ -530,7 +522,7 @@ challenge_answer_cb (void *af_cls,
       = GNUNET_new (struct RecoverSecretState);
     // FIXME: implement -> call recovery begin again
     set_state (cs->state,
-               ANASTASIS_recovery_state_to_string (
+               ANASTASIS_recovery_state_to_string_ (
                  ANASTASIS_RECOVERY_STATE_RECOVERY_FINISHED));
   }
 }
@@ -539,16 +531,15 @@ challenge_answer_cb (void *af_cls,
 static struct ANASTASIS_ReduxAction *
 solve_challenge (json_t *state,
                  const json_t *arguments,
-                 struct GNUNET_CURL_Context *ctx,
                  ANASTASIS_ActionCallback cb,
                  void *cb_cls)
 {
   if (NULL == arguments)
   {
-    ANASTASIS_redux_fail (cb,
-                          cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                          "solve_challenge");
+    ANASTASIS_redux_fail_ (cb,
+                           cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID,
+                           "solve_challenge");
     return NULL;
   }
   json_t *recovery_information;
@@ -613,7 +604,6 @@ solve_challenge (json_t *state,
 static struct ANASTASIS_ReduxAction *
 back_challenge_solving (json_t *state,
                         const json_t *arguments,
-                        struct GNUNET_CURL_Context *ctx,
                         ANASTASIS_ActionCallback cb,
                         void *cb_cls)
 {
@@ -631,7 +621,6 @@ back_challenge_solving (json_t *state,
  * by a callback function.
  * This function can do network access to talk to anastasis service providers.
  *
- * @param ctx the CURL context used to connect to the backend
  * @param[in,out] state input/output state (to be modified)
  * @param action what action to perform
  * @param arguments data for the @a action
@@ -639,8 +628,7 @@ back_challenge_solving (json_t *state,
  * @param cb_cls closure for @a cb
  */
 struct ANASTASIS_ReduxAction *
-ANASTASIS_recovery_action_ (struct GNUNET_CURL_Context *ctx,
-                            json_t *state,
+ANASTASIS_recovery_action_ (json_t *state,
                             const char *action,
                             const json_t *arguments,
                             ANASTASIS_ActionCallback cb,
@@ -688,19 +676,12 @@ ANASTASIS_recovery_action_ (struct GNUNET_CURL_Context 
*ctx,
                                                       "recovery_state"));
   enum ANASTASIS_RecoveryState rs;
 
-  if (NULL == s)
-  {
-    GNUNET_break (0);
-    cb (cb_cls,
-        TALER_EC_INVALID, // FIXME: Define correct error code
-        NULL);
-    return NULL;
-  }
-  rs = ANASTASIS_recovery_state_from_string (s);
+  GNUNET_assert (NULL != s);
+  rs = ANASTASIS_recovery_state_from_string_ (s);
   if (ANASTASIS_RECOVERY_STATE_ERROR == rs)
   {
     cb (cb_cls,
-        TALER_EC_INVALID, // FIXME: Define correct error code
+        TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
         NULL);
     return NULL;
   }
@@ -712,14 +693,13 @@ ANASTASIS_recovery_action_ (struct GNUNET_CURL_Context 
*ctx,
     {
       return dispatchers[i].fun (state,
                                  arguments,
-                                 ctx,
                                  cb,
                                  cb_cls);
     }
   }
-  ANASTASIS_redux_fail (cb,
-                        cb_cls,
-                        TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                        action);
+  ANASTASIS_redux_fail_ (cb,
+                         cb_cls,
+                         TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
+                         action);
   return NULL;
 }
diff --git a/src/reducer/anastasis_api_redux.c 
b/src/reducer/anastasis_api_redux.c
index ccdf905..80465d4 100644
--- a/src/reducer/anastasis_api_redux.c
+++ b/src/reducer/anastasis_api_redux.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
@@ -20,7 +20,6 @@
  * @author Dominik Meister
  * @author Dennis Neufeld
  */
-
 #include <platform.h>
 #include <jansson.h>
 #include "anastasis_redux.h"
@@ -37,8 +36,26 @@ static const char *generic_strings[] = {
 #undef GENERATE_STRING
 
 
+/**
+ * Extract the mode of a state from json
+ *
+ * @param state the state to operate on
+ * @return "backup_state" or "recovery_state"
+ */
+static const char *
+get_state_mode (const json_t *state)
+{
+  if (json_object_get (state, "backup_state"))
+    return "backup_state";
+  if (json_object_get (state, "recovery_state"))
+    return "recovery_state";
+  GNUNET_assert (0);
+  return NULL;
+}
+
+
 enum ANASTASIS_GenericState
-ANASTASIS_generic_state_from_string (const char *state_string)
+ANASTASIS_generic_state_from_string_ (const char *state_string)
 {
   for (enum ANASTASIS_GenericState i = 0;
        i < sizeof (generic_strings) / sizeof(*generic_strings);
@@ -51,7 +68,7 @@ ANASTASIS_generic_state_from_string (const char *state_string)
 
 
 const char *
-ANASTASIS_generic_state_to_string (enum ANASTASIS_GenericState gs)
+ANASTASIS_generic_state_to_string_ (enum ANASTASIS_GenericState gs)
 {
   if ( (gs < 0) ||
        (gs >= sizeof (generic_strings) / sizeof(*generic_strings)) )
@@ -64,10 +81,10 @@ ANASTASIS_generic_state_to_string (enum 
ANASTASIS_GenericState gs)
 
 
 void
-ANASTASIS_redux_fail (ANASTASIS_ActionCallback cb,
-                      void *cb_cls,
-                      enum TALER_ErrorCode ec,
-                      const char *detail)
+ANASTASIS_redux_fail_ (ANASTASIS_ActionCallback cb,
+                       void *cb_cls,
+                       enum TALER_ErrorCode ec,
+                       const char *detail)
 {
   json_t *estate;
 
@@ -92,18 +109,23 @@ ANASTASIS_redux_fail (ANASTASIS_ActionCallback cb,
 
 struct SelectCountryHandle;
 
+
 /**
  * State for a "get config" operation.
  */
 struct ConfigRequest
 {
 
+  /**
+   * Kept in a DLL, given that we may have multiple backends.
+   */
   struct ConfigRequest *next;
 
+  /**
+   * Kept in a DLL, given that we may have multiple backends.
+   */
   struct ConfigRequest *prev;
 
-  struct SelectCountryHandle *sch;
-
   /**
    * Obtained status code.
    */
@@ -160,9 +182,6 @@ struct ConfigRequest
 
 struct SelectCountryHandle
 {
-  struct ConfigRequest *cr_head;
-
-  struct ConfigRequest *cr_tail;
 
   /**
    * Current state
@@ -184,26 +203,39 @@ struct SelectCountryHandle
 /**
  * JSON containing country specific identity attributes to ask the user for.
  */
-const json_t *redux_id_attr;
+static json_t *redux_id_attr;
 
+/**
+ * Head of DLL of Anastasis backend configuration requests.
+ */
+static struct ConfigRequest *cr_head;
 
 /**
- * Callback function which is called by the reducer in dependence of
- * given state and action.
+ * Tail of DLL of Anastasis backend configuration requests.
+ */
+static struct ConfigRequest *cr_tail;
+
+/**
+ * Reducer API's CURL context handle.
+ */
+struct GNUNET_CURL_Context *ANASTASIS_REDUX_ctx_;
+
+/**
+ * JSON containing country specific information.
+ */
+json_t *redux_countries;
+
+
+/**
+ * Initialize reducer subsystem.
  *
- * @param state the previous state to operate on
- * @param arguments the arguments needed by operation to operate on state
- * @param ctx Curl context
- * @param cb Callback function which returns the new state
- * @param cb_cls closure for @a cb
- * @return handle to cancel async actions, NULL if @a cb was already called
+ * @param ctx context to use for CURL requests.
  */
-typedef struct ANASTASIS_ReduxAction *
-(*DispatchHandler)(json_t *state,
-                   const json_t *arguments,
-                   struct GNUNET_CURL_Context *ctx,
-                   ANASTASIS_ActionCallback cb,
-                   void *cb_cls);
+void
+ANASTASIS_redux_init (struct GNUNET_CURL_Context *ctx)
+{
+  ANASTASIS_REDUX_ctx_ = ctx;
+}
 
 
 /**
@@ -228,28 +260,218 @@ free_config_request (struct ConfigRequest *cr)
 
 
 /**
- * Function to free a #SelectCountryHandle.
+ * Terminate reducer subsystem.
+ */
+void
+ANASTASIS_redux_done ()
+{
+  struct ConfigRequest *cr;
+
+  while (NULL != (cr = cr_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (cr_head,
+                                 cr_tail,
+                                 cr);
+    free_config_request (cr);
+  }
+  ANASTASIS_REDUX_ctx_ = NULL;
+  if (NULL != redux_countries)
+  {
+    json_decref (redux_countries);
+    redux_countries = NULL;
+  }
+  if (NULL != redux_id_attr)
+  {
+    json_decref (redux_id_attr);
+    redux_id_attr = NULL;
+  }
+}
+
+
+/**
+ * Function to load json containing all countries.
+ * Returns the countries.
  *
- * @param cls closure for a #SelectCountryHandle.
+ * @return json_t *
+ */
+const json_t *
+ANASTASIS_redux_countries_init_ (void)
+{
+  char *dn;
+  json_error_t error;
+
+  if (NULL != redux_countries)
+    return redux_countries;
+
+  {
+    char *path;
+
+    path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
+    if (NULL == path)
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
+    GNUNET_asprintf (&dn,
+                     "%s/redux.countries.json",
+                     path);
+    GNUNET_free (path);
+  }
+  redux_countries = json_load_file (dn,
+                                    JSON_COMPACT,
+                                    &error);
+  if (NULL == redux_countries)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to parse `%s': %s at %d:%d (%d)\n",
+                dn,
+                error.text,
+                error.line,
+                error.column,
+                error.position);
+    GNUNET_free (dn);
+    return NULL;
+  }
+  GNUNET_free (dn);
+  return redux_countries;
+}
+
+
+/**
+ * Function called with the results of a #ANASTASIS_get_config().
+ *
+ * @param cls closure
+ * @param http_status HTTP status of the request
+ * @param methods supported methods by this provider
+ * @param annual_fee Annual fee of this service
+ * @param insurance Amount of insurance of this service
+ * @param salt Salt of this provider server
  */
 static void
-free_select_country (void *cls)
+config_cb (void *cls,
+           unsigned int http_status,
+           const json_t *methods,
+           const char *conf_currency,
+           const struct TALER_Amount *annual_fee,
+           const struct TALER_Amount *insurance,
+           const struct ANASTASIS_CRYPTO_PowSalt *salt)
+{
+  struct ConfigRequest *cr = cls;
+
+  cr->co = NULL;
+  GNUNET_SCHEDULER_cancel (cr->tt);
+  cr->tt = NULL;
+  cr->http_status = http_status;
+  if (MHD_HTTP_OK == http_status)
+  {
+    cr->backend_methods = json_incref ((json_t *) methods);
+    cr->backend_cost = *annual_fee;
+    cr->backend_currency = GNUNET_strdup (conf_currency);
+    cr->backend_insurance = *insurance;
+    cr->backend_salt = *salt;
+  }
+}
+
+
+/**
+ * Aborts a "get config" after timeout.
+ *
+ * @param cls closure for a "get config" request
+ */
+static void
+config_request_timeout (void *cls)
+{
+  struct ConfigRequest *cr = cls;
+
+  cr->tt = NULL;
+  ANASTASIS_config_cancel (cr->co);
+  cr->co = NULL;
+}
+
+
+/**
+ * Schedule job to obtain Anastasis provider configuration at @a url.
+ *
+ * @param url base URL of Anastasis provider
+ * @param name name of the provider
+ * @param id ID of the provider
+ */
+static void
+check_config (const char *url,
+              const char *name,
+              const char *id)
 {
-  struct SelectCountryHandle *sch = cls;
   struct ConfigRequest *cr;
 
-  while (NULL != (cr = sch->cr_head))
+  for (cr = cr_head; NULL != cr; cr = cr->next)
   {
-    GNUNET_CONTAINER_DLL_remove (sch->cr_head,
-                                 sch->cr_tail,
+    if (0 != strcmp (url,
+                     cr->backend_url))
+      continue;
+    if (NULL != cr->co)
+      return; /* already on it */
+    break;
+  }
+  if (NULL == cr)
+  {
+    cr = GNUNET_new (struct ConfigRequest);
+    cr->backend_url = GNUNET_strdup (url);
+    cr->backend_name = GNUNET_strdup (name);
+    cr->backend_id = GNUNET_strdup (id);
+    GNUNET_CONTAINER_DLL_insert (cr_head,
+                                 cr_tail,
                                  cr);
-    free_config_request (cr);
   }
+  cr->co = ANASTASIS_get_config (ANASTASIS_REDUX_ctx_,
+                                 cr->backend_url,
+                                 &config_cb,
+                                 cr);
+  if (NULL == cr->co)
+  {
+    GNUNET_break (0);
+  }
+  else
+  {
+    cr->tt = GNUNET_SCHEDULER_add_delayed (CONFIG_GENERIC_TIMEOUT,
+                                           &config_request_timeout,
+                                           cr);
+  }
+}
+
+
+/**
+ * Callback function which is called by the reducer in dependence of
+ * given state and action.
+ *
+ * @param state the previous state to operate on
+ * @param arguments the arguments needed by operation to operate on state
+ * @param cb Callback function which returns the new state
+ * @param cb_cls closure for @a cb
+ * @return handle to cancel async actions, NULL if @a cb was already called
+ */
+typedef struct ANASTASIS_ReduxAction *
+(*DispatchHandler)(json_t *state,
+                   const json_t *arguments,
+                   ANASTASIS_ActionCallback cb,
+                   void *cb_cls);
+
+
+/**
+ * Function to free a #SelectCountryHandle.
+ *
+ * @param cls closure for a #SelectCountryHandle.
+ */
+static void
+free_select_country (void *cls)
+{
+  struct SelectCountryHandle *sch = cls;
+
   json_decref (sch->state);
   GNUNET_free (sch);
 }
 
 
+#if 0
 /**
  * Adds the server configuration from async #ConfigRequest
  * to the json state.
@@ -333,10 +555,6 @@ conclude_select_country (struct SelectCountryHandle *sch)
   struct ConfigRequest *cr;
   const char *currency;
 
-  /* Are we waiting for more /config requests to complete? */
-  for (cr = sch->cr_head; NULL != cr; cr = cr->next)
-    if (NULL != cr->co)
-      return;
   currency = json_string_value (json_object_get (sch->state,
                                                  "currency"));
   while (NULL != (cr = sch->cr_head))
@@ -360,182 +578,73 @@ conclude_select_country (struct SelectCountryHandle *sch)
 }
 
 
-/**
- * Retries a "get config" after timeout.
- *
- * @param cls closure for a "get config" request
- */
-static void
-config_request_timeout (void *cls)
-{
-  struct ConfigRequest *cr = cls;
-
-  cr->tt = NULL;
-  ANASTASIS_config_cancel (cr->co);
-  cr->co = NULL;
-  conclude_select_country (cr->sch);
-}
-
-
-/**
- * Function called with the results of a #ANASTASIS_get_config().
- *
- * @param cls closure
- * @param http_status HTTP status of the request
- * @param methods supported methods by this provider
- * @param annual_fee Annual fee of this service
- * @param insurance Amount of insurance of this service
- * @param salt Salt of this provider server
- */
-static void
-config_cb (void *cls,
-           unsigned int http_status,
-           const json_t *methods,
-           const char *conf_currency,
-           const struct TALER_Amount *annual_fee,
-           const struct TALER_Amount *insurance,
-           const struct ANASTASIS_CRYPTO_PowSalt *salt)
-{
-  struct ConfigRequest *cr = cls;
-  struct SelectCountryHandle *sch = cr->sch;
-
-  cr->co = NULL;
-  GNUNET_SCHEDULER_cancel (cr->tt);
-  cr->tt = NULL;
-  cr->http_status = http_status;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "At %s:%d url is %s\n", __FILE__, __LINE__,
-              cr->backend_url);
-  if (MHD_HTTP_OK == http_status)
-  {
-    cr->backend_methods = json_incref ((json_t *) methods);
-    cr->backend_cost = *annual_fee;
-    cr->backend_currency = GNUNET_strdup (conf_currency);
-    cr->backend_insurance = *insurance;
-    cr->backend_salt = *salt;
-  }
-  conclude_select_country (sch);
-}
-
-
-/**
- * Extract the mode of a state from json
- *
- * @param state the state to operate on
- * @return NULL on error
- */
-static const char *
-get_state_mode (const json_t *state)
-{
-  if (json_object_get (state, "backup_state"))
-    return "backup_state";
-  if (json_object_get (state, "recovery_state"))
-    return "recovery_state";
-  return NULL;
-}
-
-
-/**
- * Function to load json containing all countries.
- * Returns the countries.
- *
- * @return json_t *
- */
-json_t *
-ANASTASIS_redux_countries_init_ (void)
-{
-  char *dn;
-  json_error_t error;
-  json_t *redux_countries;
-
-  {
-    char *path;
-
-    path = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
-    if (NULL == path)
-    {
-      GNUNET_break (0);
-      return NULL;
-    }
-    GNUNET_asprintf (&dn,
-                     "%s/redux.countries.json",
-                     path);
-    GNUNET_free (path);
-  }
-  redux_countries = json_load_file (dn, JSON_COMPACT, &error);
-  if (NULL == redux_countries)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to parse `%s': %s at %d:%d (%d)\n",
-                dn,
-                error.text,
-                error.line,
-                error.column,
-                error.position);
-    GNUNET_free (dn);
-    return NULL;
-  }
-  GNUNET_free (dn);
-  return redux_countries;
-}
+#endif
 
 
 /**
  * Function to validate an input by regular expression ("validation-regex").
  *
- * @param ahv_number ahv number to validate
+ * @param input ahv number to validate
  * @param regexp regular expression to validate form of ahv number
  * @return true if validation passed, else false
  */
 static bool
-validate_regex (const char *ahv_number,
+validate_regex (const char *input,
                 const char *regexp)
 {
-  {
-    regex_t regex;
+  regex_t regex;
 
-    if (0 != regcomp (&regex,
-                      regexp,
-                      REG_EXTENDED))
-    {
-      GNUNET_break (0);
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Failed to compile regular expression.");
-      return false;
-    }
-    /* check if ahv has correct form */
-    if (0 != regexec (&regex,
-                      ahv_number,
-                      0,
-                      NULL,
-                      0))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "AHV number `%s' does not match regex\n",
-                  ahv_number);
-      regfree (&regex);
-      return false;
-    }
+  if (0 != regcomp (&regex,
+                    regexp,
+                    REG_EXTENDED))
+  {
+    GNUNET_break (0);
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to compile regular expression.");
+    return false;
+  }
+  /* check if input has correct form */
+  if (0 != regexec (&regex,
+                    input,
+                    0,
+                    NULL,
+                    0))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Input `%s' does not match regex\n",
+                input);
     regfree (&regex);
+    return false;
   }
+  regfree (&regex);
   return true;
 }
 
 
 /**
  * Function to load json containing country specific
- * identity attributes. Returns #GNUNET_OK if operation
- * succeeded, else #GNUNET_SYSERR.
+ * identity attributes.
  *
  * @param country_code country code (e.g. "de")
- * @return int
+ * @return NULL on error
  */
-static int
+static const json_t *
 redux_id_attr_init (const char *country_code)
 {
+  static char redux_id_cc[3];
+  json_t *redux_id_attr;
   char *dn;
   json_error_t error;
 
+  if (0 == strcmp (country_code,
+                   redux_id_cc))
+    return redux_id_attr;
+
+  if (NULL != redux_id_attr)
+  {
+    json_decref (redux_id_attr);
+    redux_id_attr = NULL;
+  }
   {
     char *path;
 
@@ -543,7 +652,7 @@ redux_id_attr_init (const char *country_code)
     if (NULL == path)
     {
       GNUNET_break (0);
-      return GNUNET_SYSERR;
+      return NULL;
     }
     GNUNET_asprintf (&dn,
                      "%s/redux.%s.json",
@@ -564,10 +673,14 @@ redux_id_attr_init (const char *country_code)
                 error.column,
                 error.position);
     GNUNET_free (dn);
-    return GNUNET_SYSERR;
+    return NULL;
   }
   GNUNET_free (dn);
-  return GNUNET_OK;
+  strncpy (redux_id_cc,
+           country_code,
+           sizeof (redux_id_cc));
+  redux_id_cc[2] = '\0';
+  return redux_id_attr;
 }
 
 
@@ -578,7 +691,6 @@ redux_id_attr_init (const char *country_code)
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -586,7 +698,6 @@ redux_id_attr_init (const char *country_code)
 static struct ANASTASIS_ReduxAction *
 select_continent (json_t *state,
                   const json_t *arguments,
-                  struct GNUNET_CURL_Context *ctx,
                   ANASTASIS_ActionCallback cb,
                   void *cb_cls)
 {
@@ -605,7 +716,7 @@ select_continent (json_t *state,
 
   size_t index;
   json_t *country;
-  json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
+  const json_t *redux_countries = ANASTASIS_redux_countries_init_ ();
   json_t *root = json_object_get (redux_countries, "countries");
   json_t *countries = json_array ();
   json_t *continent = json_object_get (arguments, "continent");
@@ -631,7 +742,7 @@ select_continent (json_t *state,
                    state,
                    s_mode,
                    json_string (
-                     ANASTASIS_backup_state_to_string (
+                     ANASTASIS_backup_state_to_string_ (
                        ANASTASIS_GENERIC_STATE_COUNTRY_SELECTING))));
 
   GNUNET_assert (0 ==
@@ -658,7 +769,6 @@ select_continent (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return #ANASTASIS_ReduxAction
@@ -666,16 +776,15 @@ select_continent (json_t *state,
 static struct ANASTASIS_ReduxAction *
 select_country (json_t *state,
                 const json_t *arguments,
-                struct GNUNET_CURL_Context *ctx,
                 ANASTASIS_ActionCallback cb,
                 void *cb_cls)
 {
   if (NULL == arguments)
   {
-    ANASTASIS_redux_fail (cb,
-                          cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                          "select_country");
+    ANASTASIS_redux_fail_ (cb,
+                           cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
+                           "select_country");
     return NULL;
   }
 
@@ -685,6 +794,7 @@ select_country (json_t *state,
   json_error_t error;
   json_t *country;
   const char *currency;
+  const json_t *redux_id_attr;
 
   country = json_object_get (arguments,
                              "country_code");
@@ -694,8 +804,7 @@ select_country (json_t *state,
   GNUNET_assert (NULL != currency);
   const char *s_mode = get_state_mode (state);
   GNUNET_assert (NULL != s_mode);
-  GNUNET_assert (GNUNET_SYSERR !=
-                 redux_id_attr_init (json_string_value (country)));
+  redux_id_attr = redux_id_attr_init (json_string_value (country));
   root = json_object_get (redux_id_attr,
                           "required_attributes");
   GNUNET_assert (NULL != root);
@@ -704,7 +813,7 @@ select_country (json_t *state,
                    state,
                    s_mode,
                    json_string (
-                     ANASTASIS_generic_state_to_string (
+                     ANASTASIS_generic_state_to_string_ (
                        ANASTASIS_GENERIC_STATE_USER_ATTRIBUTES_COLLECTING))));
   GNUNET_assert (0 ==
                  json_object_set_new (state,
@@ -762,8 +871,6 @@ select_country (json_t *state,
     sch->state = json_incref (state);
     json_array_foreach (provider_arr, index, provider)
     {
-      struct ConfigRequest *cr = GNUNET_new (struct ConfigRequest);
-
       const char *url = json_string_value (json_object_get (provider,
                                                             "provider_url"));
       const char *provider_name = json_string_value (json_object_get (provider,
@@ -773,30 +880,14 @@ select_country (json_t *state,
 
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Url is: %s\n", url);
-      cr->backend_url = GNUNET_strdup (url);
-      cr->backend_name = GNUNET_strdup (provider_name);
-      cr->backend_id = GNUNET_strdup (provider_id);
-      cr->sch = sch;
-      GNUNET_CONTAINER_DLL_insert (sch->cr_head,
-                                   sch->cr_tail,
-                                   cr);
-      cr->co = ANASTASIS_get_config (ctx,
-                                     cr->backend_url,
-                                     &config_cb,
-                                     cr);
-      if (NULL == cr->co)
-      {
-        GNUNET_break (0);
-      }
-      else
-      {
-        cr->tt = GNUNET_SCHEDULER_add_delayed (CONFIG_GENERIC_TIMEOUT,
-                                               &config_request_timeout,
-                                               cr);
-      }
+      check_config (url,
+                    provider_name,
+                    provider_id);
     }
     json_decref (provider_list);
+#if 0
     conclude_select_country (sch);
+#endif
     {
       struct ANASTASIS_ReduxAction *ra;
 
@@ -816,7 +907,6 @@ select_country (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -824,7 +914,6 @@ select_country (json_t *state,
 static struct ANASTASIS_ReduxAction *
 unselect_country (json_t *state,
                   const json_t *arguments,
-                  struct GNUNET_CURL_Context *ctx,
                   ANASTASIS_ActionCallback cb,
                   void *cb_cls)
 {
@@ -835,7 +924,7 @@ unselect_country (json_t *state,
                    state,
                    s_mode,
                    json_string (
-                     ANASTASIS_generic_state_to_string (
+                     ANASTASIS_generic_state_to_string_ (
                        ANASTASIS_GENERIC_STATE_COUNTRY_SELECTING))));
   cb (cb_cls,
       TALER_EC_NONE,
@@ -851,7 +940,6 @@ unselect_country (json_t *state,
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -859,7 +947,6 @@ unselect_country (json_t *state,
 static struct ANASTASIS_ReduxAction *
 unselect_continent (json_t *state,
                     const json_t *arguments,
-                    struct GNUNET_CURL_Context *ctx,
                     ANASTASIS_ActionCallback cb,
                     void *cb_cls)
 {
@@ -871,7 +958,7 @@ unselect_continent (json_t *state,
                    state,
                    s_mode,
                    json_string (
-                     ANASTASIS_generic_state_to_string (
+                     ANASTASIS_generic_state_to_string_ (
                        ANASTASIS_GENERIC_STATE_CONTINENT_SELECTING))));
   cb (cb_cls,
       TALER_EC_NONE,
@@ -1002,10 +1089,10 @@ policy_lookup_cb (void *cls,
     json_decref (challenges);
     json_decref (policies);
     json_decref (recovery_information);
-    ANASTASIS_redux_fail (rss->cb,
-                          rss->cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID, // FIXME: 
Error code
-                          "Failed fetching recovery information!");
+    ANASTASIS_redux_fail_ (rss->cb,
+                           rss->cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID, // 
FIXME: Error code
+                           "Failed fetching recovery information!");
   }
   rss->recovery = NULL;
 }
@@ -1052,7 +1139,6 @@ free_enter_user_attributes (void *cls)
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
  * @return NULL
@@ -1060,7 +1146,6 @@ free_enter_user_attributes (void *cls)
 static struct ANASTASIS_ReduxAction *
 enter_user_attributes (json_t *state,
                        const json_t *arguments,
-                       struct GNUNET_CURL_Context *ctx,
                        ANASTASIS_ActionCallback cb,
                        void *cb_cls)
 {
@@ -1072,10 +1157,10 @@ enter_user_attributes (json_t *state,
   GNUNET_assert (NULL != state);
   if (NULL == arguments)
   {
-    ANASTASIS_redux_fail (cb,
-                          cb_cls,
-                          TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
-                          "enter_user_attributes");
+    ANASTASIS_redux_fail_ (cb,
+                           cb_cls,
+                           TALER_EC_ANASTASIS_REDUCER_ACTION_INVALID,
+                           "enter_user_attributes");
     return NULL;
   }
   attributes = json_object_get (arguments,
@@ -1153,7 +1238,7 @@ enter_user_attributes (json_t *state,
     json_object_set_new (state,
                          s_mode,
                          json_string (
-                           ANASTASIS_backup_state_to_string (
+                           ANASTASIS_backup_state_to_string_ (
                              ANASTASIS_BACKUP_STATE_AUTHENTICATIONS_EDITING)));
     if (NULL != auth_providers)
       json_object_set_new (state,
@@ -1186,7 +1271,7 @@ enter_user_attributes (json_t *state,
     json_object_set_new (state,
                          s_mode,
                          json_string (
-                           ANASTASIS_recovery_state_to_string (
+                           ANASTASIS_recovery_state_to_string_ (
                              ANASTASIS_RECOVERY_STATE_CHALLENGE_SELECTING)));
     rss->state = json_incref (state);
     rss->cb = cb;
@@ -1227,7 +1312,7 @@ enter_user_attributes (json_t *state,
                                                  ANASTASIS_CRYPTO_PowSalt)));
         rss->recovery =
           ANASTASIS_recovery_begin (
-            ctx,
+            ANASTASIS_REDUX_ctx_,
             rss->id_data,
             (NULL != version)
             ? rss->version
@@ -1264,31 +1349,30 @@ enter_user_attributes (json_t *state,
 /**
  * A generic DispatchHandler/Callback function which is called for a
  * "back" action.
- * Returns an #ANASTASIS_ReduxAction if operation is async.
  *
  * @param state state to operate on
  * @param arguments arguments to use for operation on state
- * @param ctx CURL context
  * @param cb callback (#DispatchHandler) to call during/after operation
  * @param cb_cls callback closure
- * @return NULL
+ * @return NULL (no asynchronous action)
  */
 struct ANASTASIS_ReduxAction *
 ANASTASIS_back_generic_decrement_ (json_t *state,
                                    const json_t *arguments,
-                                   struct GNUNET_CURL_Context *ctx,
                                    ANASTASIS_ActionCallback cb,
                                    void *cb_cls)
 {
   enum ANASTASIS_BackupState state_index;
   const char *s_mode = get_state_mode (state);
-  GNUNET_assert (NULL != s_mode); // FIXME: call cb with error!
   const char *state_string = json_string_value (json_object_get (state,
                                                                  s_mode));
-  GNUNET_assert (NULL != state_string); // FIXME: call cb with error!
-  if (0 == strcmp ("backup_state", s_mode))
+
+  (void) arguments;
+  GNUNET_assert (NULL != state_string);
+  if (0 == strcmp ("backup_state",
+                   s_mode))
   {
-    state_index = ANASTASIS_backup_state_from_string (state_string);
+    state_index = ANASTASIS_backup_state_from_string_ (state_string);
     GNUNET_assert (state_index > 0);
     state_index = state_index - 1;
     GNUNET_assert (0 ==
@@ -1296,11 +1380,11 @@ ANASTASIS_back_generic_decrement_ (json_t *state,
                      state,
                      s_mode,
                      json_string (
-                       ANASTASIS_generic_state_to_string (state_index))));
+                       ANASTASIS_generic_state_to_string_ (state_index))));
   }
   else
   {
-    state_index = ANASTASIS_recovery_state_from_string (state_string);
+    state_index = ANASTASIS_recovery_state_from_string_ (state_string);
     GNUNET_assert (state_index > 0);
     state_index = state_index - 1;
     GNUNET_assert (0 ==
@@ -1308,7 +1392,7 @@ ANASTASIS_back_generic_decrement_ (json_t *state,
                      state,
                      s_mode,
                      json_string (
-                       ANASTASIS_generic_state_to_string (state_index))));
+                       ANASTASIS_generic_state_to_string_ (state_index))));
   }
   cb (cb_cls,
       TALER_EC_NONE,
@@ -1328,7 +1412,6 @@ ANASTASIS_back_generic_decrement_ (json_t *state,
  * @param state input state
  * @param action what action to perform
  * @param arguments data for the @a action
- * @param ctx Curl context
  * @param cb function to call with the result
  * @param cb_cls closure for @a cb
  * @return handle to cancel async actions, NULL if @a cb was already called
@@ -1337,7 +1420,6 @@ struct ANASTASIS_ReduxAction *
 ANASTASIS_redux_action (const json_t *state,
                         const char *action,
                         const json_t *arguments,
-                        struct GNUNET_CURL_Context *ctx,
                         ANASTASIS_ActionCallback cb,
                         void *cb_cls)
 {
@@ -1357,6 +1439,11 @@ ANASTASIS_redux_action (const json_t *state,
       "unselect_continent",
       &unselect_continent
     },
+    {
+      ANASTASIS_GENERIC_STATE_COUNTRY_SELECTING,
+      "back",
+      &ANASTASIS_back_generic_decrement_
+    },
     {
       ANASTASIS_GENERIC_STATE_COUNTRY_SELECTING,
       "select_continent",
@@ -1367,6 +1454,11 @@ ANASTASIS_redux_action (const json_t *state,
       "select_country",
       &select_country
     },
+    {
+      ANASTASIS_GENERIC_STATE_COUNTRY_SELECTING,
+      "unselect_country",
+      &unselect_country
+    },
     {
       ANASTASIS_GENERIC_STATE_USER_ATTRIBUTES_COLLECTING,
       "enter_user_attributes",
@@ -1388,17 +1480,17 @@ ANASTASIS_redux_action (const json_t *state,
   {
     s = json_string_value (json_object_get (state,
                                             "recovery_state"));
-    recovery_mode = true;
     if (NULL == s)
     {
-      GNUNET_break (0);
+      GNUNET_break_op (0);
       cb (cb_cls,
-          TALER_EC_INVALID, // FIXME: Define correct error code
+          TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
           NULL);
       return NULL;
     }
+    recovery_mode = true;
   }
-  gs = ANASTASIS_generic_state_from_string (s);
+  gs = ANASTASIS_generic_state_from_string_ (s);
   {
     json_t *new_state;
     struct ANASTASIS_ReduxAction *ret;
@@ -1415,7 +1507,6 @@ ANASTASIS_redux_action (const json_t *state,
         {
           ret = dispatchers[i].fun (new_state,
                                     arguments,
-                                    ctx,
                                     cb,
                                     cb_cls);
           json_decref (new_state);
@@ -1425,21 +1516,19 @@ ANASTASIS_redux_action (const json_t *state,
     }
     if (recovery_mode)
     {
-      ret = ANASTASIS_recovery_action_ (ctx,
-                                        new_state,
+      ret = ANASTASIS_recovery_action_ (new_state,
                                         action,
                                         arguments,
                                         cb,
-                                        NULL);
+                                        cb_cls);
     }
     else
     {
-      ret = ANASTASIS_backup_action_ (ctx,
-                                      new_state,
+      ret = ANASTASIS_backup_action_ (new_state,
                                       action,
                                       arguments,
                                       cb,
-                                      NULL);
+                                      cb_cls);
     }
     json_decref (new_state);
     return ret;
diff --git a/src/reducer/anastasis_api_redux.h 
b/src/reducer/anastasis_api_redux.h
index 1c41d9f..e1f04f4 100644
--- a/src/reducer/anastasis_api_redux.h
+++ b/src/reducer/anastasis_api_redux.h
@@ -1,7 +1,154 @@
+/*
+  This file is part of Anastasis
+  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
+  Foundation; either version 3, or (at your option) any later version.
+
+  Anastasis 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
+  Anastasis; see the file COPYING.GPL.  If not, see 
<http://www.gnu.org/licenses/>
+*/
+/**
+ * @file redux/anastasis_api_redux.h
+ * @brief anastasis reducer api, internal data structures
+ * @author Christian Grothoff
+ * @author Dominik Meister
+ * @author Dennis Neufeld
+ */
+
 #ifndef ANASTASIS_API_REDUX_H
 #define ANASTASIS_API_REDUX_H
 
 
+#define ANASTASIS_GENERIC_STATES(REDUX_STATE) \
+  REDUX_STATE (ERROR) \
+  REDUX_STATE (CONTINENT_SELECTING)   \
+  REDUX_STATE (COUNTRY_SELECTING)  \
+  REDUX_STATE (USER_ATTRIBUTES_COLLECTING)
+
+#define GENERATE_GENERIC_ENUM(ENUM) ANASTASIS_GENERIC_STATE_ ## ENUM,
+
+enum ANASTASIS_GenericState
+{
+  ANASTASIS_GENERIC_STATES (GENERATE_GENERIC_ENUM)
+};
+
+#undef GENERATE_GENERIC_ENUM
+
+#define ANASTASIS_BACKUP_STATES(REDUX_STATE) \
+  ANASTASIS_GENERIC_STATES (REDUX_STATE) \
+  REDUX_STATE (AUTHENTICATIONS_EDITING)  \
+  REDUX_STATE (POLICIES_REVIEWING)   \
+  REDUX_STATE (SECRET_EDITING) \
+  REDUX_STATE (POLICIES_PAYING) \
+  REDUX_STATE (BACKUP_FINISHED)
+
+#define GENERATE_BACKUP_ENUM(ENUM) ANASTASIS_BACKUP_STATE_ ## ENUM,
+
+enum ANASTASIS_BackupState
+{
+  ANASTASIS_BACKUP_STATES (GENERATE_BACKUP_ENUM)
+};
+
+#undef GENERATE_BACKUP_ENUM
+
+#define ANASTASIS_RECOVERY_STATES(REDUX_STATE) \
+  ANASTASIS_GENERIC_STATES (REDUX_STATE) \
+  REDUX_STATE (CHALLENGE_SELECTING)  \
+  REDUX_STATE (CHALLENGE_PAYING)   \
+  REDUX_STATE (CHALLENGE_SOLVING)  \
+  REDUX_STATE (RECOVERY_FINISHED)
+
+#define GENERATE_RECOVERY_ENUM(ENUM) ANASTASIS_RECOVERY_STATE_ ## ENUM,
+
+enum ANASTASIS_RecoveryState
+{
+  ANASTASIS_RECOVERY_STATES (GENERATE_RECOVERY_ENUM)
+};
+
+#undef GENERATE_RECOVERY_ENUM
+
+
+/**
+ * Returns the enum value to a string value of a state.
+ *
+ * @param state_string
+ * @return #ANASTASIS_GENERIC_STATE_ERROR on error
+ */
+enum ANASTASIS_GenericState
+ANASTASIS_generic_state_from_string_ (const char *state_string);
+
+
+/**
+ * Returns the string value of a state.
+ *
+ * @param state_string
+ * @return NULL on error
+ */
+const char *
+ANASTASIS_generic_state_to_string_ (enum ANASTASIS_GenericState gs);
+
+
+/**
+ * Returns the enum value to a string value of a state.
+ *
+ * @param state_string
+ * @return #ANASTASIS_BACKUP_STATE_ERROR on error
+ */
+enum ANASTASIS_BackupState
+ANASTASIS_backup_state_from_string_ (const char *state_string);
+
+
+/**
+ * Returns the string value of a state.
+ *
+ * @param state_string
+ * @return NULL on error
+ */
+const char *
+ANASTASIS_backup_state_to_string_ (enum ANASTASIS_BackupState bs);
+
+
+/**
+ * Returns the enum value to a string value of a state.
+ *
+ * @param state_string
+ * @return XXX on error
+ */
+enum ANASTASIS_RecoveryState
+ANASTASIS_recovery_state_from_string_ (const char *state_string);
+
+
+/**
+ * Returns the string value of a state.
+ *
+ * @param state_string
+ * @return NULL on error
+ */
+const char *
+ANASTASIS_recovery_state_to_string_ (enum ANASTASIS_RecoveryState rs);
+
+
+/**
+ * Function to return a json error response.
+ *
+ * @param cb callback to give error to
+ * @param cb_cls callback closure
+ * @param ec error code
+ * @param detail error detail
+ */
+void
+ANASTASIS_redux_fail_ (ANASTASIS_ActionCallback cb,
+                       void *cb_cls,
+                       enum TALER_ErrorCode ec,
+                       const char *detail);
+
+
 /**
  * State for a "recover secret" CMD.
  */
@@ -69,10 +216,12 @@ struct RecoverSecretState
 };
 
 
+extern struct GNUNET_CURL_Context *ANASTASIS_REDUX_ctx_;
+
+
 struct ANASTASIS_ReduxAction *
 ANASTASIS_back_generic_decrement_ (json_t *state,
                                    const json_t *arguments,
-                                   struct GNUNET_CURL_Context *ctx,
                                    ANASTASIS_ActionCallback cb,
                                    void *cb_cls);
 
@@ -83,7 +232,7 @@ ANASTASIS_back_generic_decrement_ (json_t *state,
  *
  * @return json_t *
  */
-json_t *
+const json_t *
 ANASTASIS_redux_countries_init_ (void);
 
 
@@ -101,8 +250,7 @@ ANASTASIS_redux_countries_init_ (void);
  * @param cb_cls closure for @a cb
  */
 struct ANASTASIS_ReduxAction *
-ANASTASIS_recovery_action_ (struct GNUNET_CURL_Context *ctx,
-                            json_t *state,
+ANASTASIS_recovery_action_ (json_t *state,
                             const char *action,
                             const json_t *arguments,
                             ANASTASIS_ActionCallback cb,
@@ -123,8 +271,7 @@ ANASTASIS_recovery_action_ (struct GNUNET_CURL_Context *ctx,
  * @param cb_cls closure for @a cb
  */
 struct ANASTASIS_ReduxAction *
-ANASTASIS_backup_action_ (struct GNUNET_CURL_Context *ctx,
-                          json_t *state,
+ANASTASIS_backup_action_ (json_t *state,
                           const char *action,
                           const json_t *arguments,
                           ANASTASIS_ActionCallback cb,
@@ -136,8 +283,14 @@ ANASTASIS_backup_action_ (struct GNUNET_CURL_Context *ctx,
  */
 struct ANASTASIS_ReduxAction
 {
+  /**
+   * Function to call to clean up.
+   */
   void (*cleanup)(void *cls);
 
+  /**
+   * Action-specific state, closure for @e cleanup.
+   */
   void *cleanup_cls;
 };
 

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