gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-wallet-webex] branch master updated: benchmark


From: gnunet
Subject: [GNUnet-SVN] [taler-wallet-webex] branch master updated: benchmark
Date: Thu, 20 Sep 2018 20:54:21 +0200

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

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

The following commit(s) were added to refs/heads/master by this push:
     new 3a6d5e6d benchmark
3a6d5e6d is described below

commit 3a6d5e6df162497954fd51734181618ff7df8d28
Author: Florian Dold <address@hidden>
AuthorDate: Thu Sep 20 20:52:50 2018 +0200

    benchmark
---
 src/crypto/cryptoWorker.ts     |  20 ++-
 src/crypto/emscInterface.ts    | 380 +++++++++++++++++++++++++----------------
 src/crypto/emscLoader.d.ts     |   8 +-
 src/crypto/emscLoader.js       |  29 +++-
 src/webex/pages/benchmark.html |  17 ++
 src/webex/pages/benchmark.tsx  | 111 ++++++++++++
 src/webex/pages/common.ts      |  31 ++++
 7 files changed, 440 insertions(+), 156 deletions(-)

diff --git a/src/crypto/cryptoWorker.ts b/src/crypto/cryptoWorker.ts
index 7cec5f28..3e71794b 100644
--- a/src/crypto/cryptoWorker.ts
+++ b/src/crypto/cryptoWorker.ts
@@ -53,6 +53,8 @@ import {
 
 import { canonicalJson } from "../helpers";
 
+import * as emscLoader from "./emscLoader";
+
 import {
   Amount,
   EddsaPublicKey,
@@ -580,6 +582,20 @@ worker.onmessage = (msg: MessageEvent) => {
     console.error(`unknown operation: '${msg.data.operation}'`);
     return;
   }
-  const res = f(...msg.data.args);
-  worker.postMessage({result: res, id: msg.data.id});
+
+  console.log("onmessage with", msg.data.operation);
+  console.log("foo");
+
+  emscLoader.getLib().then((p) => {
+    const lib = p.lib;
+    if (!native.isInitialized()) {
+      console.log("initializing emscripten for then first time with lib");
+      native.initialize(lib);
+    }
+
+    console.log("about to execute", msg.data.operation);
+    const res = f(...msg.data.args);
+    console.log("finished executing", msg.data.operation);
+    worker.postMessage({ result: res, id: msg.data.id });
+  });
 };
diff --git a/src/crypto/emscInterface.ts b/src/crypto/emscInterface.ts
index 0662f4a7..5d8f0336 100644
--- a/src/crypto/emscInterface.ts
+++ b/src/crypto/emscInterface.ts
@@ -28,9 +28,34 @@
  */
 import { AmountJson } from "../amounts";
 
-import { EmscFunGen, getLib } from "./emscLoader";
+import { EmscFunGen, EmscLib } from "./emscLoader";
 
-const emscLib = getLib();
+
+// Will be set only after initialization.
+let maybeEmscEnv: EmscEnvironment | undefined = undefined;
+
+export function isInitialized() {
+  return !!maybeEmscEnv;
+}
+
+
+export function initialize(lib: EmscLib) {
+  if (!lib) {
+    throw Error("library must be object");
+  }
+  if (maybeEmscEnv) {
+    throw Error("emsc lib already initialized");
+  }
+  maybeEmscEnv = new EmscEnvironment(lib);
+}
+
+
+function emsc() {
+  if (maybeEmscEnv) {
+    return maybeEmscEnv;
+  }
+  throw Error("cannot use taler emscripten before initialization");
+}
 
 
 /**
@@ -41,75 +66,131 @@ const PTR_SIZE = 4;
 
 const GNUNET_OK = 1;
 
+interface EmscFunctions {
+  amount_add(a1: number, a2: number, a3: number): number;
+  amount_cmp(a1: number, a2: number): number;
+  amount_get_zero(a1: string, a2: number): number;
+  amount_hton(a1: number, a2: number): void;
+  amount_normalize(a1: number): void;
+  amount_ntoh(a1: number, a2: number): void;
+  amount_subtract(a1: number, a2: number, a3: number): number;
+  ecdh_eddsa(a1: number, a2: number, a3: number): number;
+  eddsa_sign(a1: number, a2: number, a3: number): number;
+  eddsa_verify(a1: number, a2: number, a3: number, a4: number): number;
+  free(ptr: number): void;
+  get_currency(a: number): string;
+  get_fraction(a: number): number;
+  get_value(a: number): number;
+  hash(a1: number, a2: number, a3: number): void;
+  hash_context_abort(ctx: number): void;
+  hash_context_finish(a1: number, a2: number): void;
+  hash_context_read(a1: number, a2: number, a3: number): void;
+  hash_create_random(a1: number, a2: number): void;
+  memmove(a1: number, a2: number, a3: number): number;
+  random_block(a1: number, a2: number, a3: number): void;
+  rsa_blinding_key_free(a1: number): void;
+  rsa_public_key_free(a1: number): void;
+  rsa_signature_free(a1: number): void;
+  setup_fresh_coin(a1: number, a2: number, a3: number): void;
+  string_to_data(a1: number, a2: number, a3: number, a4: number): number;
+}
 
-/**
- * Get an emscripten-compiled function.
- */
-const getEmsc: EmscFunGen = (name: string, ret: any, argTypes: any[]) => {
-  return (...args: any[]) => {
-    return emscLib.ccall(name, ret, argTypes, args);
-  };
-};
+interface EmscAllocFunctions {
+  data_to_string_alloc(a1: number, a2: number): number;
+  ecdhe_key_create(): number;
+  ecdhe_public_key_from_private(a1: number): number;
+  ecdsa_key_create(): number;
+  ecdsa_public_key_from_private(a1: number): number;
+  eddsa_key_create(): number;
+  eddsa_public_key_from_private(a1: number): number;
+  get_amount(a1: number, a2: number, a3: string): number;
+  hash_context_start(): number;
+  malloc(size: number): number;
+  purpose_create(a1: number, a2: number, a3: number): number;
+  rsa_blind(a1: number, a2: number, a3: number, a4: number, a5: number): 
number;
+  rsa_blinding_key_create(a1: number): number;
+  rsa_blinding_key_decode(a1: number, a2: number): number;
+  rsa_blinding_key_encode(a1: number, a2: number): number;
+  rsa_public_key_decode(a1: number, a2: number): number;
+  rsa_public_key_encode(a1: number, a2: number): number;
+  rsa_signature_encode(a1: number, a2: number): number;
+  rsa_signature_decode(a1: number, a2: number): number;
+  rsa_unblind(a1: number, a2: number, a3: number): number;
+}
 
+class EmscEnvironment {
 
-/**
- * Wrapped emscripten functions that do not allocate any memory.
- */
-const emsc = {
-  amount_add: getEmsc("TALER_amount_add", "number", ["number", "number", 
"number"]),
-  amount_cmp: getEmsc("TALER_amount_cmp", "number", ["number", "number"]),
-  amount_get_zero: getEmsc("TALER_amount_get_zero", "number", ["string", 
"number"]),
-  amount_hton: getEmsc("TALER_amount_hton", "void", ["number", "number"]),
-  amount_normalize: getEmsc("TALER_amount_normalize", "void", ["number"]),
-  amount_ntoh: getEmsc("TALER_amount_ntoh", "void", ["number", "number"]),
-  amount_subtract: getEmsc("TALER_amount_subtract", "number", ["number", 
"number", "number"]),
-  ecdh_eddsa: getEmsc("GNUNET_CRYPTO_ecdh_eddsa", "number", ["number", 
"number", "number"]),
-  eddsa_sign: getEmsc("GNUNET_CRYPTO_eddsa_sign", "number", ["number", 
"number", "number"]),
-  eddsa_verify: getEmsc("GNUNET_CRYPTO_eddsa_verify", "number", ["number", 
"number", "number", "number"]),
-  free: (ptr: number) => emscLib._free(ptr),
-  get_currency: getEmsc("TALER_WR_get_currency", "string", ["number"]),
-  get_fraction: getEmsc("TALER_WR_get_fraction", "number", ["number"]),
-  get_value: getEmsc("TALER_WR_get_value", "number", ["number"]),
-  hash: getEmsc("GNUNET_CRYPTO_hash", "void", ["number", "number", "number"]),
-  hash_context_abort: getEmsc("GNUNET_CRYPTO_hash_context_abort", "void", 
["number"]),
-  hash_context_finish: getEmsc("GNUNET_CRYPTO_hash_context_finish", "void", 
["number", "number"]),
-  hash_context_read: getEmsc("GNUNET_CRYPTO_hash_context_read", "void", 
["number", "number", "number"]),
-  hash_create_random: getEmsc("GNUNET_CRYPTO_hash_create_random", "void", 
["number", "number"]),
-  memmove: getEmsc("memmove", "number", ["number", "number", "number"]),
-  random_block: getEmsc("GNUNET_CRYPTO_random_block", "void", ["number", 
"number", "number"]),
-  rsa_blinding_key_destroy: getEmsc("GNUNET_CRYPTO_rsa_blinding_key_free", 
"void", ["number"]),
-  rsa_public_key_free: getEmsc("GNUNET_CRYPTO_rsa_public_key_free", "void", 
["number"]),
-  rsa_signature_free: getEmsc("GNUNET_CRYPTO_rsa_signature_free", "void", 
["number"]),
-  setup_fresh_coin: getEmsc( "TALER_setup_fresh_coin", "void", ["number", 
"number", "number"]),
-  string_to_data: getEmsc("GNUNET_STRINGS_string_to_data", "number", 
["number", "number", "number", "number"]),
-};
+  /**
+   * Emscripten functions that don't do any memory allocations.
+   */
+  public funcs: EmscFunctions;
 
+  /**
+   * Emscripten functions that allocate memory.
+   */
+  public allocFuncs: EmscAllocFunctions;
 
-/**
- * Emscripten functions that allocate memory.
- */
-const emscAlloc = {
-  data_to_string_alloc: getEmsc("GNUNET_STRINGS_data_to_string_alloc", 
"number", ["number", "number"]),
-  ecdhe_key_create: getEmsc("GNUNET_CRYPTO_ecdhe_key_create", "number", []),
-  ecdhe_public_key_from_private: getEmsc( 
"TALER_WRALL_ecdhe_public_key_from_private", "number", ["number"]),
-  ecdsa_key_create: getEmsc("GNUNET_CRYPTO_ecdsa_key_create", "number", []),
-  ecdsa_public_key_from_private: getEmsc( 
"TALER_WRALL_ecdsa_public_key_from_private", "number", ["number"]),
-  eddsa_key_create: getEmsc("GNUNET_CRYPTO_eddsa_key_create", "number", []),
-  eddsa_public_key_from_private: getEmsc( 
"TALER_WRALL_eddsa_public_key_from_private", "number", ["number"]),
-  get_amount: getEmsc("TALER_WRALL_get_amount", "number", ["number", "number", 
"number", "string"]),
-  hash_context_start: getEmsc("GNUNET_CRYPTO_hash_context_start", "number", 
[]),
-  malloc: (size: number) => emscLib._malloc(size),
-  purpose_create: getEmsc("TALER_WRALL_purpose_create", "number", ["number", 
"number", "number"]),
-  rsa_blind: getEmsc("GNUNET_CRYPTO_rsa_blind", "number", ["number", "number", 
"number", "number", "number"]),
-  rsa_blinding_key_create: getEmsc("GNUNET_CRYPTO_rsa_blinding_key_create", 
"number", ["number"]),
-  rsa_blinding_key_decode: getEmsc("GNUNET_CRYPTO_rsa_blinding_key_decode", 
"number", ["number", "number"]),
-  rsa_blinding_key_encode: getEmsc("GNUNET_CRYPTO_rsa_blinding_key_encode", 
"number", ["number", "number"]),
-  rsa_public_key_decode: getEmsc("GNUNET_CRYPTO_rsa_public_key_decode", 
"number", ["number", "number"]),
-  rsa_public_key_encode: getEmsc("GNUNET_CRYPTO_rsa_public_key_encode", 
"number", ["number", "number"]),
-  rsa_signature_decode: getEmsc("GNUNET_CRYPTO_rsa_signature_decode", 
"number", ["number", "number"]),
-  rsa_signature_encode: getEmsc("GNUNET_CRYPTO_rsa_signature_encode", 
"number", ["number", "number"]),
-  rsa_unblind: getEmsc("GNUNET_CRYPTO_rsa_unblind", "number", ["number", 
"number", "number"]),
-};
+  public lib: EmscLib;
+
+  constructor(lib: EmscLib) {
+    const getEmsc: EmscFunGen = (name: string, ret: any, argTypes: any[]) => {
+      return (...args: any[]) => {
+        return lib.ccall(name, ret, argTypes, args);
+      };
+    };
+    this.lib = lib;
+    this.allocFuncs = {
+      data_to_string_alloc: getEmsc("GNUNET_STRINGS_data_to_string_alloc", 
"number", ["number", "number"]),
+      ecdhe_key_create: getEmsc("GNUNET_CRYPTO_ecdhe_key_create", "number", 
[]),
+      ecdhe_public_key_from_private: getEmsc( 
"TALER_WRALL_ecdhe_public_key_from_private", "number", ["number"]),
+      ecdsa_key_create: getEmsc("GNUNET_CRYPTO_ecdsa_key_create", "number", 
[]),
+      ecdsa_public_key_from_private: getEmsc( 
"TALER_WRALL_ecdsa_public_key_from_private", "number", ["number"]),
+      eddsa_key_create: getEmsc("GNUNET_CRYPTO_eddsa_key_create", "number", 
[]),
+      eddsa_public_key_from_private: getEmsc( 
"TALER_WRALL_eddsa_public_key_from_private", "number", ["number"]),
+      get_amount: getEmsc("TALER_WRALL_get_amount", "number", ["number", 
"number", "string"]),
+      hash_context_start: getEmsc("GNUNET_CRYPTO_hash_context_start", 
"number", []),
+      malloc: (size: number) => lib._malloc(size),
+      purpose_create: getEmsc("TALER_WRALL_purpose_create", "number", 
["number", "number", "number"]),
+      rsa_blind: getEmsc("GNUNET_CRYPTO_rsa_blind", "number", ["number", 
"number", "number", "number", "number"]),
+      rsa_blinding_key_create: 
getEmsc("GNUNET_CRYPTO_rsa_blinding_key_create", "number", ["number"]),
+      rsa_blinding_key_decode: 
getEmsc("GNUNET_CRYPTO_rsa_blinding_key_decode", "number", ["number", 
"number"]),
+      rsa_blinding_key_encode: 
getEmsc("GNUNET_CRYPTO_rsa_blinding_key_encode", "number", ["number", 
"number"]),
+      rsa_public_key_decode: getEmsc("GNUNET_CRYPTO_rsa_public_key_decode", 
"number", ["number", "number"]),
+      rsa_public_key_encode: getEmsc("GNUNET_CRYPTO_rsa_public_key_encode", 
"number", ["number", "number"]),
+      rsa_signature_decode: getEmsc("GNUNET_CRYPTO_rsa_signature_decode", 
"number", ["number", "number"]),
+      rsa_signature_encode: getEmsc("GNUNET_CRYPTO_rsa_signature_encode", 
"number", ["number", "number"]),
+      rsa_unblind: getEmsc("GNUNET_CRYPTO_rsa_unblind", "number", ["number", 
"number", "number"]),
+    };
+    this.funcs = {
+      amount_add: getEmsc("TALER_amount_add", "number", ["number", "number", 
"number"]),
+      amount_cmp: getEmsc("TALER_amount_cmp", "number", ["number", "number"]),
+      amount_get_zero: getEmsc("TALER_amount_get_zero", "number", ["string", 
"number"]),
+      amount_hton: getEmsc("TALER_amount_hton", "void", ["number", "number"]),
+      amount_normalize: getEmsc("TALER_amount_normalize", "void", ["number"]),
+      amount_ntoh: getEmsc("TALER_amount_ntoh", "void", ["number", "number"]),
+      amount_subtract: getEmsc("TALER_amount_subtract", "number", ["number", 
"number", "number"]),
+      ecdh_eddsa: getEmsc("GNUNET_CRYPTO_ecdh_eddsa", "number", ["number", 
"number", "number"]),
+      eddsa_sign: getEmsc("GNUNET_CRYPTO_eddsa_sign", "number", ["number", 
"number", "number"]),
+      eddsa_verify: getEmsc("GNUNET_CRYPTO_eddsa_verify", "number", ["number", 
"number", "number", "number"]),
+      free: (ptr: number) => lib._free(ptr),
+      get_currency: getEmsc("TALER_WR_get_currency", "string", ["number"]),
+      get_fraction: getEmsc("TALER_WR_get_fraction", "number", ["number"]),
+      get_value: getEmsc("TALER_WR_get_value", "number", ["number"]),
+      hash: getEmsc("GNUNET_CRYPTO_hash", "void", ["number", "number", 
"number"]),
+      hash_context_abort: getEmsc("GNUNET_CRYPTO_hash_context_abort", "void", 
["number"]),
+      hash_context_finish: getEmsc("GNUNET_CRYPTO_hash_context_finish", 
"void", ["number", "number"]),
+      hash_context_read: getEmsc("GNUNET_CRYPTO_hash_context_read", "void", 
["number", "number", "number"]),
+      hash_create_random: getEmsc("GNUNET_CRYPTO_hash_create_random", "void", 
["number", "number"]),
+      memmove: getEmsc("memmove", "number", ["number", "number", "number"]),
+      random_block: getEmsc("GNUNET_CRYPTO_random_block", "void", ["number", 
"number", "number"]),
+      rsa_blinding_key_free: getEmsc("GNUNET_CRYPTO_rsa_blinding_key_free", 
"void", ["number"]),
+      rsa_public_key_free: getEmsc("GNUNET_CRYPTO_rsa_public_key_free", 
"void", ["number"]),
+      rsa_signature_free: getEmsc("GNUNET_CRYPTO_rsa_signature_free", "void", 
["number"]),
+      setup_fresh_coin: getEmsc("TALER_setup_fresh_coin", "void", ["number", 
"number", "number"]),
+      string_to_data: getEmsc("GNUNET_STRINGS_string_to_data", "number", 
["number", "number", "number", "number"]),
+    };
+  }
+}
 
 
 /**
@@ -152,7 +233,7 @@ export class HashContext implements ArenaObject {
   private hashContextPtr: number | undefined;
 
   constructor() {
-    this.hashContextPtr = emscAlloc.hash_context_start();
+    this.hashContextPtr = emsc().allocFuncs.hash_context_start();
   }
 
   /**
@@ -162,7 +243,7 @@ export class HashContext implements ArenaObject {
     if (!this.hashContextPtr) {
       throw Error("assertion failed");
     }
-    emsc.hash_context_read(this.hashContextPtr, obj.nativePtr, obj.size());
+    emsc().funcs.hash_context_read(this.hashContextPtr, obj.nativePtr, 
obj.size());
   }
 
   /**
@@ -173,7 +254,7 @@ export class HashContext implements ArenaObject {
       throw Error("assertion failed");
     }
     h.alloc();
-    emsc.hash_context_finish(this.hashContextPtr, h.nativePtr);
+    emsc().funcs.hash_context_finish(this.hashContextPtr, h.nativePtr);
   }
 
   /**
@@ -181,7 +262,7 @@ export class HashContext implements ArenaObject {
    */
   destroy(): void {
     if (this.hashContextPtr) {
-      emsc.hash_context_abort(this.hashContextPtr);
+      emsc().funcs.hash_context_abort(this.hashContextPtr);
     }
     this.hashContextPtr = undefined;
   }
@@ -201,7 +282,7 @@ abstract class MallocArenaObject implements ArenaObject {
 
   destroy(): void {
     if (this._nativePtr && !this.isWeak) {
-      emsc.free(this.nativePtr);
+      emsc().funcs.free(this.nativePtr);
       this._nativePtr = undefined;
     }
   }
@@ -220,7 +301,7 @@ abstract class MallocArenaObject implements ArenaObject {
     if (this._nativePtr !== undefined) {
       throw Error("Double allocation");
     }
-    this.nativePtr = emscAlloc.malloc(size);
+    this.nativePtr = emsc().allocFuncs.malloc(size);
   }
 
   set nativePtr(v: number) {
@@ -314,18 +395,17 @@ export class Amount extends MallocArenaObject {
   constructor(args?: AmountJson, arena?: Arena) {
     super(arena);
     if (args) {
-      this.nativePtr = emscAlloc.get_amount(args.value,
-                                            0,
+      this.nativePtr = emsc().allocFuncs.get_amount(args.value,
                                             args.fraction,
                                             args.currency);
     } else {
-      this.nativePtr = emscAlloc.get_amount(0, 0, 0, "");
+      this.nativePtr = emsc().allocFuncs.get_amount(0, 0, "");
     }
   }
 
   static getZero(currency: string, a?: Arena): Amount {
     const am = new Amount(undefined, a);
-    const r = emsc.amount_get_zero(currency, am.nativePtr);
+    const r = emsc().funcs.amount_get_zero(currency, am.nativePtr);
     if (r !== GNUNET_OK) {
       throw Error("invalid currency");
     }
@@ -336,31 +416,31 @@ export class Amount extends MallocArenaObject {
   toNbo(a?: Arena): AmountNbo {
     const x = new AmountNbo(a);
     x.alloc();
-    emsc.amount_hton(x.nativePtr, this.nativePtr);
+    emsc().funcs.amount_hton(x.nativePtr, this.nativePtr);
     return x;
   }
 
   fromNbo(nbo: AmountNbo): void {
-    emsc.amount_ntoh(this.nativePtr, nbo.nativePtr);
+    emsc().funcs.amount_ntoh(this.nativePtr, nbo.nativePtr);
   }
 
   get value() {
-    return emsc.get_value(this.nativePtr);
+    return emsc().funcs.get_value(this.nativePtr);
   }
 
   get fraction() {
-    return emsc.get_fraction(this.nativePtr);
+    return emsc().funcs.get_fraction(this.nativePtr);
   }
 
   get currency(): string {
-    return emsc.get_currency(this.nativePtr);
+    return emsc().funcs.get_currency(this.nativePtr);
   }
 
   toJson(): AmountJson {
     return {
-      currency: emsc.get_currency(this.nativePtr),
-      fraction: emsc.get_fraction(this.nativePtr),
-      value: emsc.get_value(this.nativePtr),
+      currency: emsc().funcs.get_currency(this.nativePtr),
+      fraction: emsc().funcs.get_fraction(this.nativePtr),
+      value: emsc().funcs.get_value(this.nativePtr),
     };
   }
 
@@ -368,7 +448,7 @@ export class Amount extends MallocArenaObject {
    * Add an amount to this amount.
    */
   add(a: Amount) {
-    const res = emsc.amount_add(this.nativePtr, a.nativePtr, this.nativePtr);
+    const res = emsc().funcs.amount_add(this.nativePtr, a.nativePtr, 
this.nativePtr);
     if (res < 1) {
       // Overflow
       return false;
@@ -381,7 +461,7 @@ export class Amount extends MallocArenaObject {
    */
   sub(a: Amount) {
     // this = this - a
-    const res = emsc.amount_subtract(this.nativePtr, this.nativePtr, 
a.nativePtr);
+    const res = emsc().funcs.amount_subtract(this.nativePtr, this.nativePtr, 
a.nativePtr);
     if (res === 0) {
       // Underflow
       return false;
@@ -397,11 +477,11 @@ export class Amount extends MallocArenaObject {
     if (this.currency !== a.currency) {
       throw Error(`incomparable currencies (${this.currency} and 
${a.currency})`);
     }
-    return emsc.amount_cmp(this.nativePtr, a.nativePtr);
+    return emsc().funcs.amount_cmp(this.nativePtr, a.nativePtr);
   }
 
   normalize() {
-    emsc.amount_normalize(this.nativePtr);
+    emsc().funcs.amount_normalize(this.nativePtr);
   }
 }
 
@@ -443,13 +523,13 @@ abstract class PackedArenaObject extends 
MallocArenaObject {
   }
 
   randomize(qual: RandomQuality = RandomQuality.STRONG): void {
-    emsc.random_block(qual, this.nativePtr, this.size());
+    emsc().funcs.random_block(qual, this.nativePtr, this.size());
   }
 
   toCrock(): string {
-    const d = emscAlloc.data_to_string_alloc(this.nativePtr, this.size());
-    const s = emscLib.Pointer_stringify(d);
-    emsc.free(d);
+    const d = emsc().allocFuncs.data_to_string_alloc(this.nativePtr, 
this.size());
+    const s = emsc().lib.Pointer_stringify(d);
+    emsc().funcs.free(d);
     return s;
   }
 
@@ -465,7 +545,7 @@ abstract class PackedArenaObject extends MallocArenaObject {
     // We need to get the javascript string
     // to the emscripten heap first.
     const buf = ByteArray.fromStringWithNull(s);
-    const res = emsc.string_to_data(buf.nativePtr,
+    const res = emsc().funcs.string_to_data(buf.nativePtr,
                                   s.length,
                                   this.nativePtr,
                                   this.size());
@@ -478,21 +558,21 @@ abstract class PackedArenaObject extends 
MallocArenaObject {
   alloc() {
     // FIXME: should the client be allowed to call alloc multiple times?
     if (!this._nativePtr) {
-      this.nativePtr = emscAlloc.malloc(this.size());
+      this.nativePtr = emsc().allocFuncs.malloc(this.size());
     }
   }
 
   hash(): HashCode {
     const x = new HashCode();
     x.alloc();
-    emsc.hash(this.nativePtr, this.size(), x.nativePtr);
+    emsc().funcs.hash(this.nativePtr, this.size(), x.nativePtr);
     return x;
   }
 
   hexdump() {
     const bytes: string[] = [];
     for (let i = 0; i < this.size(); i++) {
-      let b = emscLib.getValue(this.nativePtr + i, "i8");
+      let b = emsc().lib.getValue(this.nativePtr + i, "i8");
       b = (b + 256) % 256;
       bytes.push("0".concat(b.toString(16)).slice(-2));
     }
@@ -554,11 +634,11 @@ function fromCrockDecoded<T extends MallocArenaObject>(s: 
string,
  * Encode an object using a special encoding function.
  */
 function encode<T extends MallocArenaObject>(obj: T, encodeFn: any, arena?: 
Arena): ByteArray {
-  const ptr = emscAlloc.malloc(PTR_SIZE);
+  const ptr = emsc().allocFuncs.malloc(PTR_SIZE);
   const len = encodeFn(obj.nativePtr, ptr);
   const res = new ByteArray(len, undefined, arena);
-  res.nativePtr = emscLib.getValue(ptr, "*");
-  emsc.free(ptr);
+  res.nativePtr = emsc().lib.getValue(ptr, "*");
+  emsc().funcs.free(ptr);
   return res;
 }
 
@@ -569,7 +649,7 @@ function encode<T extends MallocArenaObject>(obj: T, 
encodeFn: any, arena?: Aren
 export class EddsaPrivateKey extends PackedArenaObject {
   static create(a?: Arena): EddsaPrivateKey {
     const obj = new EddsaPrivateKey(a);
-    obj.nativePtr = emscAlloc.eddsa_key_create();
+    obj.nativePtr = emsc().allocFuncs.eddsa_key_create();
     return obj;
   }
 
@@ -579,7 +659,7 @@ export class EddsaPrivateKey extends PackedArenaObject {
 
   getPublicKey(a?: Arena): EddsaPublicKey {
     const obj = new EddsaPublicKey(a);
-    obj.nativePtr = emscAlloc.eddsa_public_key_from_private(this.nativePtr);
+    obj.nativePtr = 
emsc().allocFuncs.eddsa_public_key_from_private(this.nativePtr);
     return obj;
   }
 
@@ -595,7 +675,7 @@ export class EddsaPrivateKey extends PackedArenaObject {
 export class EcdsaPrivateKey extends PackedArenaObject {
   static create(a?: Arena): EcdsaPrivateKey {
     const obj = new EcdsaPrivateKey(a);
-    obj.nativePtr = emscAlloc.ecdsa_key_create();
+    obj.nativePtr = emsc().allocFuncs.ecdsa_key_create();
     return obj;
   }
 
@@ -605,7 +685,7 @@ export class EcdsaPrivateKey extends PackedArenaObject {
 
   getPublicKey(a?: Arena): EcdsaPublicKey {
     const obj = new EcdsaPublicKey(a);
-    obj.nativePtr = emscAlloc.ecdsa_public_key_from_private(this.nativePtr);
+    obj.nativePtr = 
emsc().allocFuncs.ecdsa_public_key_from_private(this.nativePtr);
     return obj;
   }
 
@@ -621,7 +701,7 @@ export class EcdsaPrivateKey extends PackedArenaObject {
 export class EcdhePrivateKey extends PackedArenaObject {
   static create(a?: Arena): EcdhePrivateKey {
     const obj = new EcdhePrivateKey(a);
-    obj.nativePtr = emscAlloc.ecdhe_key_create();
+    obj.nativePtr = emsc().allocFuncs.ecdhe_key_create();
     return obj;
   }
 
@@ -631,7 +711,7 @@ export class EcdhePrivateKey extends PackedArenaObject {
 
   getPublicKey(a?: Arena): EcdhePublicKey {
     const obj = new EcdhePublicKey(a);
-    obj.nativePtr = emscAlloc.ecdhe_public_key_from_private(this.nativePtr);
+    obj.nativePtr = 
emsc().allocFuncs.ecdhe_public_key_from_private(this.nativePtr);
     return obj;
   }
 
@@ -728,7 +808,7 @@ export class HashCode extends PackedArenaObject {
 
   random(qual: RandomQuality = RandomQuality.STRONG) {
     this.alloc();
-    emsc.hash_create_random(qual, this.nativePtr);
+    emsc().funcs.hash_create_random(qual, this.nativePtr);
   }
 }
 
@@ -746,7 +826,7 @@ export class ByteArray extends PackedArenaObject {
   constructor(desiredSize: number, init?: number, a?: Arena) {
     super(a);
     if (init === undefined) {
-      this.nativePtr = emscAlloc.malloc(desiredSize);
+      this.nativePtr = emsc().allocFuncs.malloc(desiredSize);
     } else {
       this.nativePtr = init;
     }
@@ -756,16 +836,16 @@ export class ByteArray extends PackedArenaObject {
   static fromStringWithoutNull(s: string, a?: Arena): ByteArray {
     // UTF-8 bytes, including 0-terminator
     const terminatedByteLength = countUtf8Bytes(s) + 1;
-    const hstr = emscAlloc.malloc(terminatedByteLength);
-    emscLib.stringToUTF8(s, hstr, terminatedByteLength);
+    const hstr = emsc().allocFuncs.malloc(terminatedByteLength);
+    emsc().lib.stringToUTF8(s, hstr, terminatedByteLength);
     return new ByteArray(terminatedByteLength - 1, hstr, a);
   }
 
   static fromStringWithNull(s: string, a?: Arena): ByteArray {
     // UTF-8 bytes, including 0-terminator
     const terminatedByteLength = countUtf8Bytes(s) + 1;
-    const hstr = emscAlloc.malloc(terminatedByteLength);
-    emscLib.stringToUTF8(s, hstr, terminatedByteLength);
+    const hstr = emsc().allocFuncs.malloc(terminatedByteLength);
+    emsc().lib.stringToUTF8(s, hstr, terminatedByteLength);
     return new ByteArray(terminatedByteLength, hstr, a);
   }
 
@@ -773,12 +853,12 @@ export class ByteArray extends PackedArenaObject {
     // this one is a bit more complicated than the other fromCrock functions,
     // since we don't have a fixed size
     const byteLength = countUtf8Bytes(s);
-    const hstr = emscAlloc.malloc(byteLength + 1);
-    emscLib.stringToUTF8(s, hstr, byteLength + 1);
+    const hstr = emsc().allocFuncs.malloc(byteLength + 1);
+    emsc().lib.stringToUTF8(s, hstr, byteLength + 1);
     const decodedLen = Math.floor((byteLength * 5) / 8);
     const ba = new ByteArray(decodedLen, undefined, a);
-    const res = emsc.string_to_data(hstr, byteLength, ba.nativePtr, 
decodedLen);
-    emsc.free(hstr);
+    const res = emsc().funcs.string_to_data(hstr, byteLength, ba.nativePtr, 
decodedLen);
+    emsc().funcs.free(hstr);
     if (res !== GNUNET_OK) {
       throw Error("decoding failed");
     }
@@ -802,9 +882,9 @@ export class EccSignaturePurpose extends PackedArenaObject {
               payload: PackedArenaObject,
               a?: Arena) {
     super(a);
-    this.nativePtr = emscAlloc.purpose_create(purpose,
-                                              payload.nativePtr,
-                                              payload.size());
+    this.nativePtr = emsc().allocFuncs.purpose_create(purpose,
+                                                      payload.nativePtr,
+                                                      payload.size());
     this.payloadSize = payload.size();
   }
 }
@@ -834,13 +914,13 @@ abstract class SignatureStruct {
       totalSize += member.size();
     }
 
-    const buf = emscAlloc.malloc(totalSize);
+    const buf = emsc().allocFuncs.malloc(totalSize);
     let ptr = buf;
     for (const f of this.fieldTypes()) {
       const name = f[0];
       const member = this.members[name];
       const size = member.size();
-      emsc.memmove(ptr, member.nativePtr, size);
+      emsc().funcs.memmove(ptr, member.nativePtr, size);
       ptr += size;
     }
     const ba = new ByteArray(totalSize, buf, a);
@@ -1081,7 +1161,7 @@ export class AbsoluteTimeNbo extends PackedArenaObject {
 // XXX: This only works up to 54 bit numbers.
 function set64(p: number, n: number) {
   for (let i = 0; i < 8; ++i) {
-    emscLib.setValue(p + (7 - i), n & 0xFF, "i8");
+    emsc().lib.setValue(p + (7 - i), n & 0xFF, "i8");
     n = Math.floor(n / 256);
   }
 }
@@ -1089,7 +1169,7 @@ function set64(p: number, n: number) {
 // XXX: This only works up to 54 bit numbers.
 function set32(p: number, n: number) {
   for (let i = 0; i < 4; ++i) {
-    emscLib.setValue(p + (3 - i), n & 0xFF, "i8");
+    emsc().lib.setValue(p + (3 - i), n & 0xFF, "i8");
     n = Math.floor(n / 256);
   }
 }
@@ -1277,7 +1357,7 @@ export class PaymentSignaturePS extends SignatureStruct {
  */
 export class RsaPublicKey extends MallocArenaObject {
   static fromCrock(s: string): RsaPublicKey {
-    return fromCrockDecoded(s, this, emscAlloc.rsa_public_key_decode);
+    return fromCrockDecoded(s, this, emsc().allocFuncs.rsa_public_key_decode);
   }
 
   toCrock() {
@@ -1285,12 +1365,12 @@ export class RsaPublicKey extends MallocArenaObject {
   }
 
   destroy() {
-    emsc.rsa_public_key_free(this.nativePtr);
+    emsc().funcs.rsa_public_key_free(this.nativePtr);
     this.nativePtr = 0;
   }
 
   encode(arena?: Arena): ByteArray {
-    return encode(this, emscAlloc.rsa_public_key_encode);
+    return encode(this, emsc().allocFuncs.rsa_public_key_encode);
   }
 }
 
@@ -1313,15 +1393,15 @@ export class EddsaSignature extends PackedArenaObject {
  */
 export class RsaSignature extends MallocArenaObject {
   static fromCrock(s: string, a?: Arena) {
-    return fromCrockDecoded(s, this, emscAlloc.rsa_signature_decode);
+    return fromCrockDecoded(s, this, emsc().allocFuncs.rsa_signature_decode);
   }
 
   encode(arena?: Arena): ByteArray {
-    return encode(this, emscAlloc.rsa_signature_encode);
+    return encode(this, emsc().allocFuncs.rsa_signature_encode);
   }
 
   destroy() {
-    emsc.rsa_signature_free(this.nativePtr);
+    emsc().funcs.rsa_signature_free(this.nativePtr);
     this.nativePtr = 0;
   }
 }
@@ -1334,17 +1414,17 @@ export function rsaBlind(hashCode: HashCode,
                          blindingKey: RsaBlindingKeySecret,
                          pkey: RsaPublicKey,
                          arena?: Arena): ByteArray|null {
-  const buf_ptr_out = emscAlloc.malloc(PTR_SIZE);
-  const buf_size_out = emscAlloc.malloc(PTR_SIZE);
-  const res = emscAlloc.rsa_blind(hashCode.nativePtr,
-                                blindingKey.nativePtr,
-                                pkey.nativePtr,
-                                buf_ptr_out,
-                                buf_size_out);
-  const buf_ptr = emscLib.getValue(buf_ptr_out, "*");
-  const buf_size = emscLib.getValue(buf_size_out, "*");
-  emsc.free(buf_ptr_out);
-  emsc.free(buf_size_out);
+  const buf_ptr_out = emsc().allocFuncs.malloc(PTR_SIZE);
+  const buf_size_out = emsc().allocFuncs.malloc(PTR_SIZE);
+  const res = emsc().allocFuncs.rsa_blind(hashCode.nativePtr,
+                                          blindingKey.nativePtr,
+                                          pkey.nativePtr,
+                                          buf_ptr_out,
+                                          buf_size_out);
+  const buf_ptr = emsc().lib.getValue(buf_ptr_out, "*");
+  const buf_size = emsc().lib.getValue(buf_size_out, "*");
+  emsc().funcs.free(buf_ptr_out);
+  emsc().funcs.free(buf_size_out);
   if (res !== GNUNET_OK) {
     // malicious key
     return null;
@@ -1361,7 +1441,7 @@ export function eddsaSign(purpose: EccSignaturePurpose,
                           a?: Arena): EddsaSignature {
   const sig = new EddsaSignature(a);
   sig.alloc();
-  const res = emsc.eddsa_sign(priv.nativePtr, purpose.nativePtr, 
sig.nativePtr);
+  const res = emsc().funcs.eddsa_sign(priv.nativePtr, purpose.nativePtr, 
sig.nativePtr);
   if (res < 1) {
     throw Error("EdDSA signing failed");
   }
@@ -1377,10 +1457,10 @@ export function eddsaVerify(purposeNum: number,
                             sig: EddsaSignature,
                             pub: EddsaPublicKey,
                             a?: Arena): boolean {
-  const r = emsc.eddsa_verify(purposeNum,
-                            verify.nativePtr,
-                            sig.nativePtr,
-                            pub.nativePtr);
+  const r = emsc().funcs.eddsa_verify(purposeNum,
+                                      verify.nativePtr,
+                                      sig.nativePtr,
+                                      pub.nativePtr);
   return r === GNUNET_OK;
 }
 
@@ -1393,9 +1473,9 @@ export function rsaUnblind(sig: RsaSignature,
                            pk: RsaPublicKey,
                            a?: Arena): RsaSignature {
   const x = new RsaSignature(a);
-  x.nativePtr = emscAlloc.rsa_unblind(sig.nativePtr,
-                                      bk.nativePtr,
-                                      pk.nativePtr);
+  x.nativePtr = emsc().allocFuncs.rsa_unblind(sig.nativePtr,
+                                              bk.nativePtr,
+                                              pk.nativePtr);
   return x;
 }
 
@@ -1424,7 +1504,7 @@ export function ecdhEddsa(priv: EcdhePrivateKey,
                           pub: EddsaPublicKey): HashCode {
   const h = new HashCode();
   h.alloc();
-  const res = emsc.ecdh_eddsa(priv.nativePtr, pub.nativePtr, h.nativePtr);
+  const res = emsc().funcs.ecdh_eddsa(priv.nativePtr, pub.nativePtr, 
h.nativePtr);
   if (res !== GNUNET_OK) {
     throw Error("ecdh_eddsa failed");
   }
@@ -1443,10 +1523,10 @@ export function setupFreshCoin(secretSeed: 
TransferSecretP,
   blindingKey.isWeak = true;
   const buf = new ByteArray(priv.size() + blindingKey.size());
 
-  emsc.setup_fresh_coin(secretSeed.nativePtr, coinIndex, buf.nativePtr);
+  emsc().funcs.setup_fresh_coin(secretSeed.nativePtr, coinIndex, 
buf.nativePtr);
 
   priv.nativePtr = buf.nativePtr;
   blindingKey.nativePtr = buf.nativePtr + priv.size();
 
-  return {priv, blindingKey};
+  return { priv, blindingKey };
 }
diff --git a/src/crypto/emscLoader.d.ts b/src/crypto/emscLoader.d.ts
index f62604ee..3ec4f4cf 100644
--- a/src/crypto/emscLoader.d.ts
+++ b/src/crypto/emscLoader.d.ts
@@ -15,7 +15,7 @@
  */
 
 
-declare function getLib(): EmscLib;
+declare function getLib(): Promise<{ lib: EmscLib }>;
 
 /**
  * Signature of the function that retrieves emscripten
@@ -44,6 +44,12 @@ interface EmscLib {
 
   stringToUTF8(s: string, addr: number, maxLength: number): void;
 
+  onRuntimeInitialized(f: () => void): void;
+
+  readBinary?: (filename: string) => Promise<ArrayBuffer>;
+
+  calledRun?: boolean;
+
   _free(ptr: number): void;
 
   _malloc(n: number): number;
diff --git a/src/crypto/emscLoader.js b/src/crypto/emscLoader.js
index ed866281..7251a598 100644
--- a/src/crypto/emscLoader.js
+++ b/src/crypto/emscLoader.js
@@ -24,6 +24,8 @@
  * the right way to load the library.
  */
 
+let cachedLib = undefined;
+
 /**
  * Load the taler emscripten lib.
  *
@@ -31,6 +33,11 @@
  * be globally available.  Inside node, require is used.
  */
 export function getLib() {
+  console.log("in getLib");
+  if (cachedLib) {
+    console.log("lib is cached");
+    return Promise.resolve({ lib: cachedLib });
+  }
   if (typeof require !== "undefined") {
     // Make sure that TypeScript doesn't try
     // to check the taler-emscripten-lib.
@@ -45,7 +52,8 @@ export function getLib() {
     const lib = indirectRequire("../../../emscripten/taler-emscripten-lib.js");
     g.importScripts = savedImportScripts;
     if (lib) {
-      return lib;
+      cachedLib = lib;
+      return Promise.resolve({ lib: cachedLib });
     }
     // When we're running as a webpack bundle, the above require might
     // have failed and returned 'undefined', so we try other ways to import.
@@ -57,7 +65,22 @@ export function getLib() {
     if (!self.TalerEmscriptenLib) {
       throw Error("can't import taler emscripten lib");
     }
-    return self.TalerEmscriptenLib
+    const locateFile = (path, scriptDir) => {
+      console.log("locating file", "path", path, "scriptDir", scriptDir);
+      // This is quite hacky and assumes that our scriptDir is dist/
+      return scriptDir + "../emscripten/" + path;
+    };
+    console.log("instantiating TalerEmscriptenLib");
+    //const lib = self.TalerEmscriptenLib({ locateFile });
+    const lib = self.TalerEmscriptenLib;
+    cachedLib = lib;
+    return Promise.resolve({ lib: lib });
+    //return new Promise((resolve, reject) => {
+    //  lib.then(mod => {
+    //    console.log("emscripten module fully loaded");
+    //    resolve({ lib: mod });
+    //  });
+    //});
   }
 
   // Last resort, we don't have require, we're not running in a webworker.
@@ -66,7 +89,7 @@ export function getLib() {
 
   if (typeof window !== "undefined") {
     if (window.TalerEmscriptenLib) {
-      return TalerEmscriptenLib;
+      return Promise.resolve(TalerEmscriptenLib);
     }
     throw Error("Looks like running in browser, but TalerEmscriptenLib is not 
defined");
   }
diff --git a/src/webex/pages/benchmark.html b/src/webex/pages/benchmark.html
new file mode 100644
index 00000000..a593d1e3
--- /dev/null
+++ b/src/webex/pages/benchmark.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="UTF-8">
+    <title>Taler Wallet: Benchmarks</title>
+    <link rel="stylesheet" type="text/css" href="../style/wallet.css">
+    <link rel="icon" href="/img/icon.png">
+    <script src="/dist/page-common-bundle.js"></script>
+    <script src="/dist/benchmark-bundle.js"></script>
+  </head>
+  <body>
+  <section id="main">
+    <h1>Benchmarks</h1>
+    <div id="container"></div>
+  </section>
+  </body>
+</html>
diff --git a/src/webex/pages/benchmark.tsx b/src/webex/pages/benchmark.tsx
new file mode 100644
index 00000000..1d91ac0b
--- /dev/null
+++ b/src/webex/pages/benchmark.tsx
@@ -0,0 +1,111 @@
+/*
+ This file is part of TALER
+ (C) 2015 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+
+/**
+ * Benchmarks for the wallet.
+ *
+ * @author Florian Dold
+ */
+
+import * as i18n from "../../i18n";
+
+import { runOnceWhenReady } from "./common";
+
+import { BenchmarkResult } from "../../walletTypes";
+
+import * as wxApi from "../wxApi";
+
+import * as React from "react";
+import * as ReactDOM from "react-dom";
+
+
+interface BenchmarkRunnerState {
+  repetitions: number;
+  result?: BenchmarkResult;
+  running: boolean;
+}
+
+
+function BenchmarkDisplay(props: BenchmarkRunnerState) {
+  const result = props.result;
+  if (!result) {
+    if (props.running) {
+      return <div>Waiting for results ...</div>;
+    } else {
+      return <div></div>;
+    }
+  }
+  return (
+    <>
+    <h2>Results for {result.repetitions} repetitions</h2>
+    <table className="pure-table">
+      <thead>
+      <tr>
+        <th>{i18n.str`Operation`}</th>
+        <th>{i18n.str`time (ms/op)`}</th>
+      </tr>
+      {
+        Object.keys(result.time).sort().map(
+          k =>
+            <tr>
+              <td>{k}</td>
+              <td>{result.time[k] / result.repetitions}</td>
+            </tr>
+        )
+      }
+      </thead>
+    </table>
+    </>
+  );
+}
+
+class BenchmarkRunner extends React.Component<any, BenchmarkRunnerState> {
+  constructor(props: any) {
+    super(props);
+    this.state = {
+      repetitions: 10,
+      running: false,
+    };
+  }
+
+  async run() {
+    this.setState({ result: undefined, running: true });
+    let result = await wxApi.benchmarkCrypto(this.state.repetitions);
+    this.setState({ result, running: false });
+  }
+
+  render() {
+    return (
+      <div>
+        <label>Repetitions:</label>
+        <input type="number"
+               value={this.state.repetitions}
+               onChange={(evt) => this.setState({ repetitions: 
Number.parseInt(evt.target.value) })} />
+        {" "}
+        <button onClick={() => this.run()}>Run</button>
+        <BenchmarkDisplay {...this.state} />
+      </div>
+    );
+  }
+}
+
+
+runOnceWhenReady(() => {
+  ReactDOM.render(<BenchmarkRunner />, document.getElementById("container")!);
+  // Will be used by the backend to detect when the popup gets closed,
+  // so we can clear notifications
+});
diff --git a/src/webex/pages/common.ts b/src/webex/pages/common.ts
new file mode 100644
index 00000000..695e5fc1
--- /dev/null
+++ b/src/webex/pages/common.ts
@@ -0,0 +1,31 @@
+/*
+ This file is part of TALER
+ (C) 2018 GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Common helper functions for all web extension pages.
+ */
+
+/**
+ * Make sure that a function is executed exactly once
+ * after the DOM has been loaded.
+ */
+export function runOnceWhenReady(f: () => void): void {
+  if (document.readyState === "loading") {
+    document.addEventListener("DOMContentLoaded", f);
+    return;
+  }
+  f();
+}

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



reply via email to

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