View Issue Details

IDProjectCategoryView StatusLast Update
0006830Anastasiscommand line toolspublic2021-06-28 22:52
ReporterChristian Grothoff Assigned ToChristian Grothoff  
PrioritylowSeverityfeatureReproducibilityN/A
Status closedResolutionfixed 
Platformi7OSDebian GNU/LinuxOS Versionsqueeze
Product VersionGit master 
Target Version0.0.0Fixed in Version0.0.0 
Summary0006830: re-implement cost-based selection
DescriptionThe attached diff shows the code that had to be retired when we went from single-currency to multi-currency support.
That said, IF multiple providers do use the same currency, we can and should still use the cheaper one if possible. So this code should be rewritten to select the cheapest provider per currency domain, instead of simply ignoring costs.
TagsNo tags attached.
Attached Files
cost.diff (10,524 bytes)   
diff --git a/src/reducer/anastasis_api_backup_redux.c b/src/reducer/anastasis_api_backup_redux.c
index b1c2543..ec80434 100644
--- a/src/reducer/anastasis_api_backup_redux.c
+++ b/src/reducer/anastasis_api_backup_redux.c
@@ -317,12 +317,6 @@ del_authentication (json_t *state,
  */
 struct PolicyBuilder
 {
-  /**
-   * Financial cost of the providers selected in @e best_sel.
-   * Only valid during the go_with() function.
-   */
-  struct TALER_Amount best_cost;
-
   /**
    * Authentication providers available overall, from our state.
    */
@@ -338,11 +332,6 @@ struct PolicyBuilder
    */
   json_t *policies;
 
-  /**
-   * Currency we are using.
-   */
-  const char *currency;
-
   /**
    * Array of length @e req_methods.
    */
@@ -397,14 +386,8 @@ static void
 eval_provider_selection (struct PolicyBuilder *pb,
                          const char *prov_sel[])
 {
-  struct TALER_Amount curr_cost;
   unsigned int curr_diversity;
 
-  /* most hold here, as invariant passed earlier in go_with() */
-  GNUNET_assert (GNUNET_OK ==
-                 TALER_amount_get_zero (pb->currency,
-                                        &curr_cost));
-
   /* calculate cost */
   for (unsigned int i = 0; i < pb->req_methods; i++)
   {
@@ -450,19 +433,6 @@ eval_provider_selection (struct PolicyBuilder *pb,
       if (0 == strcmp (type,
                        method_type))
       {
-        if ( (GNUNET_YES !=
-              TALER_amount_cmp_currency (&curr_cost,
-                                         &method_cost)) ||
-             (0 >
-              TALER_amount_add (&curr_cost,
-                                &curr_cost,
-                                &method_cost)) )
-        {
-          GNUNET_break (0);
-          pb->ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
-          pb->hint = "'usage_fee' addition failure";
-          return;
-        }
         found = true;
       }
     }
@@ -493,17 +463,10 @@ eval_provider_selection (struct PolicyBuilder *pb,
   }
   if (curr_diversity < pb->best_diversity)
     return;
-  if ( (GNUNET_YES ==
-        TALER_amount_cmp_currency (&curr_cost,
-                                   &pb->best_cost)) &&
-       (0 < TALER_amount_cmp (&curr_cost,
-                              &pb->best_cost)) )
-    return;
   memcpy (pb->best_sel,
           prov_sel,
           sizeof (const char *) * pb->req_methods);
   pb->best_diversity = curr_diversity;
-  pb->best_cost = curr_cost;
 }
 
 
@@ -554,7 +517,6 @@ static void
 go_with (struct PolicyBuilder *pb)
 {
   const unsigned int *m_idx = pb->m_idx;
-  struct TALER_Amount recovery_cost;
   const char *best_sel[pb->req_methods];
   const char *prov_sel[pb->req_methods];
   json_t *method_arr;
@@ -562,28 +524,9 @@ go_with (struct PolicyBuilder *pb)
   /* compute best provider selection (store in best_sel) */
   pb->best_diversity = 0;
   pb->best_sel = best_sel;
-  memset (&pb->best_cost,
-          0,
-          sizeof (struct TALER_Amount));
   provider_candidate (pb,
                       prov_sel,
                       0);
-  if (GNUNET_OK !=
-      TALER_amount_get_zero (pb->currency,
-                             &recovery_cost))
-  {
-    pb->ec = TALER_EC_ANASTASIS_REDUCER_STATE_INVALID;
-    pb->hint = "'currency' invalid";
-    return;
-  }
-  if (GNUNET_OK !=
-      TALER_amount_is_valid (&pb->best_cost))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Did not find providers supporting requested authorization methods\n");
-    return;
-  }
-
   /* Convert best_sel to entry in 'policies' array */
   method_arr = json_array ();
   GNUNET_assert (NULL != method_arr);
@@ -599,9 +542,7 @@ go_with (struct PolicyBuilder *pb)
                                           policy_method));
   }
   {
-    json_t *policy = json_pack ("{s:o, s:o}",
-                                "recovery_cost",
-                                TALER_JSON_from_amount (&pb->best_cost),
+    json_t *policy = json_pack ("{s:o}",
                                 "methods",
                                 method_arr);
     GNUNET_assert (NULL != policy);
@@ -667,16 +608,6 @@ done_authentication (json_t *state,
     .ec = TALER_EC_NONE
   };
 
-  pb.currency = json_string_value (json_object_get (state,
-                                                    "currency"));
-  if (NULL == pb.currency)
-  {
-    ANASTASIS_redux_fail_ (cb,
-                           cb_cls,
-                           TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
-                           "'currency' must be provided");
-    return NULL;
-  }
   pb.providers = json_object_get (state,
                                   "authentication_providers");
   if ( (NULL == pb.providers) ||
@@ -815,8 +746,6 @@ add_policy (json_t *state,
   const json_t *auth_providers;
   const json_t *auth_methods;
   json_t *methods;
-  struct TALER_Amount recovery_cost;
-  const char *currency;
 
   if (NULL == arguments)
   {
@@ -846,19 +775,6 @@ add_policy (json_t *state,
                            "'policies' not an array");
     return NULL;
   }
-  currency = json_string_value (json_object_get (state,
-                                                 "currency"));
-  if ( (NULL == currency) ||
-       (GNUNET_OK !=
-        TALER_amount_get_zero (currency,
-                               &recovery_cost)) )
-  {
-    ANASTASIS_redux_fail_ (cb,
-                           cb_cls,
-                           TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
-                           "'currency' must be a vaild currency");
-    return NULL;
-  }
   auth_providers = json_object_get (state,
                                     "authentication_providers");
   if (! json_is_object (auth_providers))
@@ -999,18 +915,6 @@ add_policy (json_t *state,
           if (0 != strcmp (type,
                            method_type))
             continue;
-          if (0 >
-              TALER_amount_add (&recovery_cost,
-                                &recovery_cost,
-                                &method_cost))
-          {
-            GNUNET_break (0);
-            ANASTASIS_redux_fail_ (cb,
-                                   cb_cls,
-                                   TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
-                                   "cost addition failed");
-            return NULL;
-          }
           found = true;
           break;
         }
@@ -1034,9 +938,7 @@ add_policy (json_t *state,
   {
     json_t *policy;
 
-    policy = json_pack ("{s:o, s:o}",
-                        "recovery_cost",
-                        TALER_JSON_from_amount (&recovery_cost),
+    policy = json_pack ("{s:o}",
                         "methods",
                         methods);
     GNUNET_assert (NULL != policy);
diff --git a/src/reducer/anastasis_api_redux.c b/src/reducer/anastasis_api_redux.c
index 1b449fc..73b781f 100644
--- a/src/reducer/anastasis_api_redux.c
+++ b/src/reducer/anastasis_api_redux.c
@@ -660,12 +660,12 @@ check_config (const char *url)
 /**
  * Begin asynchronous check for provider configurations.
  *
- * @param currency the currency to initiate the provider checks for
+ * @param currencies the currencies to initiate the provider checks for
  * @param[in,out] state to set provider list for
  * @return #TALER_EC_NONE on success
  */
 static enum TALER_ErrorCode
-begin_provider_config_check (const char *currency,
+begin_provider_config_check (const json_t *currencies,
                              json_t *state)
 {
   if (NULL == provider_list)
@@ -732,9 +732,27 @@ begin_provider_config_check (const char *currency,
         return TALER_EC_ANASTASIS_REDUCER_RESOURCE_MALFORMED;
       }
 
-      if (0 != strcasecmp (currency,
-                           cur))
-        continue;
+      {
+        bool found = false;
+        json_t *cu;
+        size_t off;
+
+        json_array_foreach (currencies, off, cu)
+        {
+          const char *currency;
+
+          currency = json_string_value (cu);
+          if (NULL == currency)
+          {
+            json_decref (pl);
+            return TALER_EC_ANASTASIS_REDUCER_INPUT_INVALID;
+          }
+          found = (0 == strcasecmp (currency,
+                                    cur));
+        }
+        if (! found)
+          continue;
+      }
       GNUNET_assert (0 ==
                      json_object_set_new (pl,
                                           url,
@@ -966,7 +984,7 @@ select_country (json_t *state,
 {
   const json_t *required_attrs;
   const json_t *country_code;
-  const char *currency;
+  const json_t *currencies;
   const json_t *redux_id_attr;
 
   if (NULL == arguments)
@@ -1016,14 +1034,15 @@ select_country (json_t *state,
     }
   }
 
-  currency = json_string_value (json_object_get (arguments,
-                                                 "currency"));
-  if (NULL == currency)
+  currencies = json_object_get (arguments,
+                                "currencies");
+  if ( (NULL == currencies) ||
+       (! json_is_array (currencies))  )
   {
     ANASTASIS_redux_fail_ (cb,
                            cb_cls,
                            TALER_EC_ANASTASIS_REDUCER_STATE_INVALID,
-                           "'currency' missing");
+                           "'currencies' missing");
     return NULL;
   }
   /* We now have an idea of the currency, begin fetching
@@ -1031,7 +1050,7 @@ select_country (json_t *state,
   {
     enum TALER_ErrorCode ec;
 
-    ec = begin_provider_config_check (currency,
+    ec = begin_provider_config_check (currencies,
                                       state);
     if (TALER_EC_NONE != ec)
     {
@@ -1039,7 +1058,7 @@ select_country (json_t *state,
       ANASTASIS_redux_fail_ (cb,
                              cb_cls,
                              ec,
-                             currency);
+                             NULL);
       return NULL;
     }
   }
@@ -1070,9 +1089,9 @@ select_country (json_t *state,
                                   "selected_country",
                                   (json_t *) country_code));
   GNUNET_assert (0 ==
-                 json_object_set_new (state,
-                                      "currency",
-                                      json_string (currency)));
+                 json_object_set (state,
+                                  "currencies",
+                                  (json_t *) currencies));
   GNUNET_assert (0 ==
                  json_object_set (state,
                                   "required_attributes",
cost.diff (10,524 bytes)   

Activities

Christian Grothoff

2021-06-27 00:10

manager   ~0017979

327a594..502b0f2 adds some multi-currency aware cost-based policy generation. Alas, I still need to review other aspects of the policy generation, like making sure that one challenge/truth/key-share is only ever mapped to one provider.

Christian Grothoff

2021-06-28 22:51

manager   ~0017980

Fixed in 502b0f2..1241f52

Issue History

Date Modified Username Field Change
2021-04-02 21:26 Christian Grothoff New Issue
2021-04-02 21:26 Christian Grothoff File Added: cost.diff
2021-04-02 21:26 Christian Grothoff Status new => confirmed
2021-04-02 21:26 Christian Grothoff Target Version => 0.3.0
2021-04-11 17:28 Christian Grothoff Target Version 0.3.0 => 0.2.0
2021-06-27 00:10 Christian Grothoff Note Added: 0017979
2021-06-28 22:51 Christian Grothoff Assigned To => Christian Grothoff
2021-06-28 22:51 Christian Grothoff Status confirmed => resolved
2021-06-28 22:51 Christian Grothoff Resolution open => fixed
2021-06-28 22:51 Christian Grothoff Fixed in Version => 0.0.0
2021-06-28 22:51 Christian Grothoff Note Added: 0017980
2021-06-28 22:51 Christian Grothoff Target Version 0.2.0 => 0.0.0
2021-06-28 22:52 Christian Grothoff Status resolved => closed