gnunet-svn
[Top][All Lists]
Advanced

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

[taler-wallet-core] branch master updated: anastasis-core: maximize dive


From: gnunet
Subject: [taler-wallet-core] branch master updated: anastasis-core: maximize diversity in provider selection
Date: Wed, 03 Nov 2021 10:44:16 +0100

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

dold pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 082bef33 anastasis-core: maximize diversity in provider selection
082bef33 is described below

commit 082bef334659502b6b27b4f61d6f58aab90a7710
Author: Florian Dold <florian@dold.me>
AuthorDate: Wed Nov 3 10:44:10 2021 +0100

    anastasis-core: maximize diversity in provider selection
---
 packages/anastasis-core/src/index.ts             | 104 +-------------
 packages/anastasis-core/src/policy-suggestion.ts | 169 +++++++++++++++++++++++
 2 files changed, 170 insertions(+), 103 deletions(-)

diff --git a/packages/anastasis-core/src/index.ts 
b/packages/anastasis-core/src/index.ts
index 786d8b76..db99db61 100644
--- a/packages/anastasis-core/src/index.ts
+++ b/packages/anastasis-core/src/index.ts
@@ -90,6 +90,7 @@ import {
 } from "./crypto.js";
 import { unzlibSync, zlibSync } from "fflate";
 import { EscrowMethod, RecoveryDocument } from "./recovery-document-types.js";
+import { ProviderInfo, suggestPolicies } from "./policy-suggestion.js";
 
 const { fetch } = fetchPonyfill({});
 
@@ -290,109 +291,6 @@ async function backupEnterUserAttributes(
   return newState;
 }
 
-interface PolicySelectionResult {
-  policies: Policy[];
-  policy_providers: PolicyProvider[];
-}
-
-type MethodSelection = number[];
-
-function enumerateSelections(n: number, m: number): MethodSelection[] {
-  const selections: MethodSelection[] = [];
-  const a = new Array(n);
-  const sel = (i: number) => {
-    if (i === n) {
-      selections.push([...a]);
-      return;
-    }
-    const start = i == 0 ? 0 : a[i - 1] + 1;
-    for (let j = start; j < m; j++) {
-      a[i] = j;
-      sel(i + 1);
-    }
-  };
-  sel(0);
-  return selections;
-}
-
-/**
- * Provider information used during provider/method mapping.
- */
-interface ProviderInfo {
-  url: string;
-  methodCost: Record<string, AmountString>;
-}
-
-/**
- * Assign providers to a method selection.
- */
-function assignProviders(
-  methods: AuthMethod[],
-  providers: ProviderInfo[],
-  methodSelection: number[],
-): Policy | undefined {
-  const selectedProviders: string[] = [];
-  for (const mi of methodSelection) {
-    const m = methods[mi];
-    let found = false;
-    for (const prov of providers) {
-      if (prov.methodCost[m.type]) {
-        selectedProviders.push(prov.url);
-        found = true;
-        break;
-      }
-    }
-    if (!found) {
-      /* No provider found for this method */
-      return undefined;
-    }
-  }
-  return {
-    methods: methodSelection.map((x, i) => {
-      return {
-        authentication_method: x,
-        provider: selectedProviders[i],
-      };
-    }),
-  };
-}
-
-function suggestPolicies(
-  methods: AuthMethod[],
-  providers: ProviderInfo[],
-): PolicySelectionResult {
-  const numMethods = methods.length;
-  if (numMethods === 0) {
-    throw Error("no methods");
-  }
-  let numSel: number;
-  if (numMethods <= 2) {
-    numSel = numMethods;
-  } else if (numMethods <= 4) {
-    numSel = numMethods - 1;
-  } else if (numMethods <= 6) {
-    numSel = numMethods - 2;
-  } else if (numMethods == 7) {
-    numSel = numMethods - 3;
-  } else {
-    numSel = 4;
-  }
-  const policies: Policy[] = [];
-  const selections = enumerateSelections(numSel, numMethods);
-  logger.info(`selections: ${j2s(selections)}`);
-  for (const sel of selections) {
-    const p = assignProviders(methods, providers, sel);
-    if (p) {
-      policies.push(p);
-    }
-  }
-  return {
-    policies,
-    policy_providers: providers.map((x) => ({
-      provider_url: x.url,
-    })),
-  };
-}
 
 /**
  * Truth data as stored in the reducer.
diff --git a/packages/anastasis-core/src/policy-suggestion.ts 
b/packages/anastasis-core/src/policy-suggestion.ts
new file mode 100644
index 00000000..62392146
--- /dev/null
+++ b/packages/anastasis-core/src/policy-suggestion.ts
@@ -0,0 +1,169 @@
+import { AmountString, j2s, Logger } from "@gnu-taler/taler-util";
+import { AuthMethod, Policy, PolicyProvider } from "./reducer-types.js";
+
+const logger = new Logger("anastasis-core:policy-suggestion.ts");
+
+/**
+ * Provider information used during provider/method mapping.
+ */
+export interface ProviderInfo {
+  url: string;
+  methodCost: Record<string, AmountString>;
+}
+
+export function suggestPolicies(
+  methods: AuthMethod[],
+  providers: ProviderInfo[],
+): PolicySelectionResult {
+  const numMethods = methods.length;
+  if (numMethods === 0) {
+    throw Error("no methods");
+  }
+  let numSel: number;
+  if (numMethods <= 2) {
+    numSel = numMethods;
+  } else if (numMethods <= 4) {
+    numSel = numMethods - 1;
+  } else if (numMethods <= 6) {
+    numSel = numMethods - 2;
+  } else if (numMethods == 7) {
+    numSel = numMethods - 3;
+  } else {
+    numSel = 4;
+  }
+  const policies: Policy[] = [];
+  const selections = enumerateMethodSelections(numSel, numMethods);
+  logger.info(`selections: ${j2s(selections)}`);
+  for (const sel of selections) {
+    const p = assignProviders(policies, methods, providers, sel);
+    if (p) {
+      policies.push(p);
+    }
+  }
+  return {
+    policies,
+    policy_providers: providers.map((x) => ({
+      provider_url: x.url,
+    })),
+  };
+}
+
+/**
+ * Assign providers to a method selection.
+ *
+ * The evaluation of the assignment is made with respect to
+ * previously generated policies.
+ */
+function assignProviders(
+  existingPolicies: Policy[],
+  methods: AuthMethod[],
+  providers: ProviderInfo[],
+  methodSelection: number[],
+): Policy | undefined {
+  const providerSelections = enumerateProviderMappings(
+    methodSelection.length,
+    providers.length,
+  );
+
+  let bestProvSel: ProviderSelection | undefined;
+  let bestDiversity = 0;
+
+  for (const provSel of providerSelections) {
+    // First, check if selection is even possible with the methods offered
+    let possible = true;
+    for (const methIndex in provSel) {
+      const provIndex = provSel[methIndex];
+      const meth = methods[methIndex];
+      const prov = providers[provIndex];
+      if (!prov.methodCost[meth.type]) {
+        possible = false;
+        break;
+      }
+    }
+    if (!possible) {
+      continue;
+    }
+
+    // Evaluate diversity, always prefer policies
+    // that increase diversity.
+    const providerSet = new Set<string>();
+    for (const pol of existingPolicies) {
+      for (const m of pol.methods) {
+        providerSet.add(m.provider);
+      }
+    }
+    for (const provIndex of provSel) {
+      const prov = providers[provIndex];
+      providerSet.add(prov.url);
+    }
+
+    const diversity = providerSet.size;
+    if (!bestProvSel || diversity > bestDiversity) {
+      bestProvSel = provSel;
+      bestDiversity = diversity;
+    }
+    // TODO: also evaluate costs and duplicates (same challenge at same 
provider)
+  }
+
+  if (!bestProvSel) {
+    return undefined;
+  }
+
+  return {
+    methods: bestProvSel.map((x, i) => ({
+      authentication_method: methodSelection[i],
+      provider: providers[x].url,
+    })),
+  };
+}
+
+type ProviderSelection = number[];
+
+/**
+ * Compute provider mappings.
+ * Enumerates all n-combinations with repetition of m providers.
+ */
+function enumerateProviderMappings(n: number, m: number): ProviderSelection[] {
+  const selections: ProviderSelection[] = [];
+  const a = new Array(n);
+  const sel = (i: number, start: number = 0) => {
+    if (i === n) {
+      selections.push([...a]);
+      return;
+    }
+    for (let j = start; j < m; j++) {
+      a[i] = j;
+      sel(i + 1, j);
+    }
+  };
+  sel(0);
+  return selections;
+}
+
+interface PolicySelectionResult {
+  policies: Policy[];
+  policy_providers: PolicyProvider[];
+}
+
+type MethodSelection = number[];
+
+/**
+ * Compute method selections.
+ * Enumerates all n-combinations without repetition of m methods.
+ */
+function enumerateMethodSelections(n: number, m: number): MethodSelection[] {
+  const selections: MethodSelection[] = [];
+  const a = new Array(n);
+  const sel = (i: number, start: number = 0) => {
+    if (i === n) {
+      selections.push([...a]);
+      return;
+    }
+    for (let j = start; j < m; j++) {
+      a[i] = j;
+      sel(i + 1, j + 1);
+    }
+  };
+  sel(0);
+  return selections;
+}

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