aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/crypto/cryptoApi-test.ts8
-rw-r--r--src/crypto/cryptoApi.ts88
-rw-r--r--src/crypto/startWorker.js41
-rw-r--r--src/headless/taler-wallet-cli.ts3
-rw-r--r--src/wallet.ts5
-rw-r--r--src/webex/wxBackend.ts3
6 files changed, 83 insertions, 65 deletions
diff --git a/src/crypto/cryptoApi-test.ts b/src/crypto/cryptoApi-test.ts
index 6d43e2e6e..9c592412e 100644
--- a/src/crypto/cryptoApi-test.ts
+++ b/src/crypto/cryptoApi-test.ts
@@ -24,7 +24,7 @@ import {
ReserveRecord,
} from "../dbTypes";
-import { CryptoApi } from "./cryptoApi";
+import { CryptoApi, NodeCryptoWorkerFactory } from "./cryptoApi";
const masterPub1: string =
"CQQZ9DY3MZ1ARMN5K1VKDETS04Y2QCKMMCFHZSWJWWVN82BTTH00";
@@ -73,7 +73,7 @@ const denomInvalid1 = JSON.parse(JSON.stringify(denomValid1));
denomInvalid1.value.value += 1;
test("string hashing", async t => {
- const crypto = new CryptoApi();
+ const crypto = new CryptoApi(new NodeCryptoWorkerFactory());
const s = await crypto.hashString("hello taler");
const sh =
"8RDMADB3YNF3QZBS3V467YZVJAMC2QAQX0TZGVZ6Q5PFRRAJFT70HHN0QF661QR9QWKYMMC7YEMPD679D2RADXCYK8Y669A2A5MKQFR";
@@ -82,7 +82,7 @@ test("string hashing", async t => {
});
test("precoin creation", async t => {
- const crypto = new CryptoApi();
+ const crypto = new CryptoApi(new NodeCryptoWorkerFactory());
const { priv, pub } = await crypto.createEddsaKeypair();
const r: ReserveRecord = {
created: 0,
@@ -103,7 +103,7 @@ test("precoin creation", async t => {
});
test("denom validation", async t => {
- const crypto = new CryptoApi();
+ const crypto = new CryptoApi(new NodeCryptoWorkerFactory());
let v: boolean;
v = await crypto.isValidDenom(denomValid1, masterPub1);
t.true(v);
diff --git a/src/crypto/cryptoApi.ts b/src/crypto/cryptoApi.ts
index 5e3237836..accebd651 100644
--- a/src/crypto/cryptoApi.ts
+++ b/src/crypto/cryptoApi.ts
@@ -39,9 +39,7 @@ import { ContractTerms, PaybackRequest } from "../talerTypes";
import { BenchmarkResult, CoinWithDenom, PayCoinInfo } from "../walletTypes";
import * as timer from "../timer";
-
-import { startWorker } from "./startWorker";
-import { throws } from "assert";
+import { string } from "prop-types";
/**
* State of a crypto worker.
@@ -50,7 +48,7 @@ interface WorkerState {
/**
* The actual worker thread.
*/
- w: Worker | null;
+ w: CryptoWorker | null;
/**
* Work we're currently executing or null if not busy.
@@ -86,6 +84,67 @@ interface WorkItem {
*/
const NUM_PRIO = 5;
+interface CryptoWorker {
+ postMessage(message: any): void;
+
+ terminate(): void;
+
+ onmessage: (m: any) => void;
+ onerror: (m: any) => void;
+}
+
+export interface CryptoWorkerFactory {
+ /**
+ * Start a new worker.
+ */
+ startWorker(): CryptoWorker;
+
+ /**
+ * Query the number of workers that should be
+ * run at the same time.
+ */
+ getConcurrency(): number
+}
+
+
+export class NodeCryptoWorkerFactory implements CryptoWorkerFactory {
+ startWorker(): CryptoWorker {
+ if (typeof require === "undefined") {
+ throw Error("cannot make worker, require(...) not defined");
+ }
+ const workerCtor = require("./nodeWorker").Worker;
+ const workerPath = __dirname + "/cryptoWorker.js";
+ return new workerCtor(workerPath);
+ }
+
+ getConcurrency(): number {
+ return 2;
+ }
+}
+
+
+export class BrowserCryptoWorkerFactory implements CryptoWorkerFactory {
+ startWorker(): CryptoWorker {
+ const workerCtor = Worker;
+ const workerPath = "/dist/cryptoWorker-bundle.js";
+ return new workerCtor(workerPath) as CryptoWorker;
+ }
+
+ getConcurrency(): number {
+ let concurrency = 2;
+ try {
+ // only works in the browser
+ // tslint:disable-next-line:no-string-literal
+ concurrency = (navigator as any)["hardwareConcurrency"];
+ concurrency = Math.max(1, Math.ceil(concurrency / 2));
+ } catch (e) {
+ concurrency = 2;
+ }
+ return concurrency;
+ }
+}
+
+
/**
* Crypto API that interfaces manages a background crypto thread
* for the execution of expensive operations.
@@ -94,6 +153,9 @@ export class CryptoApi {
private nextRpcId: number = 1;
private workers: WorkerState[];
private workQueues: WorkItem[][];
+
+ private workerFactory: CryptoWorkerFactory;
+
/**
* Number of busy workers.
*/
@@ -106,6 +168,7 @@ export class CryptoApi {
public enableTracing = false;
+
/**
* Terminate all worker threads.
*/
@@ -146,7 +209,7 @@ export class CryptoApi {
ws.currentWorkItem = work;
this.numBusy++;
if (!ws.w) {
- const w = startWorker();
+ const w = this.workerFactory.startWorker();
w.onmessage = (m: MessageEvent) => this.handleWorkerMessage(ws, m);
w.onerror = (e: ErrorEvent) => this.handleWorkerError(ws, e);
ws.w = w;
@@ -239,17 +302,9 @@ export class CryptoApi {
currentWorkItem.resolve(msg.data.result);
}
- constructor() {
- let concurrency = 2;
- try {
- // only works in the browser
- // tslint:disable-next-line:no-string-literal
- concurrency = (navigator as any)["hardwareConcurrency"];
- concurrency = Math.max(1, Math.ceil(concurrency / 2));
- } catch (e) {
- // ignore
- }
- this.workers = new Array<WorkerState>(concurrency);
+ constructor(workerFactory: CryptoWorkerFactory) {
+ this.workerFactory = workerFactory;
+ this.workers = new Array<WorkerState>(workerFactory.getConcurrency());
for (let i = 0; i < this.workers.length; i++) {
this.workers[i] = {
@@ -258,6 +313,7 @@ export class CryptoApi {
w: null,
};
}
+
this.workQueues = [];
for (let i = 0; i < NUM_PRIO; i++) {
this.workQueues.push([]);
diff --git a/src/crypto/startWorker.js b/src/crypto/startWorker.js
deleted file mode 100644
index a64152c64..000000000
--- a/src/crypto/startWorker.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- This file is part of TALER
- (C) 2017 Inria and 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/>
- */
-
-
-// @ts-nocheck
-
-
-/**
- * Start a crypto worker, using different worker
- * mechanisms depending on the environment.
- *
- * @returns {Worker}
- */
-export function startWorker() {
- let workerCtor;
- let workerPath;
- if (typeof Worker !== "undefined") {
- // we're in the browser
- workerCtor = Worker;
- workerPath = "/dist/cryptoWorker-bundle.js";
- } else if (typeof "require" !== "undefined") {
- workerCtor = require("./nodeWorker").Worker;
- workerPath = __dirname + "/cryptoWorker.js";
- } else {
- throw Error("Can't create worker, unknown environment");
- }
- return new workerCtor(workerPath);
-}
diff --git a/src/headless/taler-wallet-cli.ts b/src/headless/taler-wallet-cli.ts
index 0c6c2ba98..95ee40e7d 100644
--- a/src/headless/taler-wallet-cli.ts
+++ b/src/headless/taler-wallet-cli.ts
@@ -26,6 +26,7 @@ import URI = require("urijs");
import querystring = require("querystring");
import { CheckPaymentResponse } from "../talerTypes";
+import { NodeCryptoWorkerFactory } from "../crypto/cryptoApi";
const enableTracing = false;
@@ -268,7 +269,7 @@ export async function main() {
myUnsupportedUpgrade,
);
- const myWallet = new Wallet(myDb, myHttpLib, myBadge, myNotifier);
+ const myWallet = new Wallet(myDb, myHttpLib, myBadge, myNotifier, new NodeCryptoWorkerFactory());
const reserveResponse = await myWallet.createReserve({
amount: amounts.parseOrThrow("TESTKUDOS:10.0"),
diff --git a/src/wallet.ts b/src/wallet.ts
index 6d4eeb26c..e3b609351 100644
--- a/src/wallet.ts
+++ b/src/wallet.ts
@@ -22,7 +22,7 @@
/**
* Imports.
*/
-import { CryptoApi } from "./crypto/cryptoApi";
+import { CryptoApi, CryptoWorkerFactory } from "./crypto/cryptoApi";
import {
amountToPretty,
canonicalJson,
@@ -360,12 +360,13 @@ export class Wallet {
http: HttpRequestLibrary,
badge: Badge,
notifier: Notifier,
+ cryptoWorkerFactory: CryptoWorkerFactory,
) {
this.db = db;
this.http = http;
this.badge = badge;
this.notifier = notifier;
- this.cryptoApi = new CryptoApi();
+ this.cryptoApi = new CryptoApi(cryptoWorkerFactory);
this.timerGroup = new TimerGroup();
const init = async () => {
diff --git a/src/webex/wxBackend.ts b/src/webex/wxBackend.ts
index 0baa7d414..831495359 100644
--- a/src/webex/wxBackend.ts
+++ b/src/webex/wxBackend.ts
@@ -58,6 +58,7 @@ import URI = require("urijs");
import Port = chrome.runtime.Port;
import MessageSender = chrome.runtime.MessageSender;
import { TipToken } from "../talerTypes";
+import { BrowserCryptoWorkerFactory } from "../crypto/cryptoApi";
const NeedsWallet = Symbol("NeedsWallet");
@@ -711,7 +712,7 @@ async function reinitWallet() {
const http = new BrowserHttpLib();
const notifier = new ChromeNotifier();
console.log("setting wallet");
- const wallet = new Wallet(db, http, badge, notifier);
+ const wallet = new Wallet(db, http, badge, notifier, new BrowserCryptoWorkerFactory());
// Useful for debugging in the background page.
(window as any).talerWallet = wallet;
currentWallet = wallet;