diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/crypto/cryptoApi-test.ts | 8 | ||||
-rw-r--r-- | src/crypto/cryptoApi.ts | 88 | ||||
-rw-r--r-- | src/crypto/startWorker.js | 41 | ||||
-rw-r--r-- | src/headless/taler-wallet-cli.ts | 3 | ||||
-rw-r--r-- | src/wallet.ts | 5 | ||||
-rw-r--r-- | src/webex/wxBackend.ts | 3 |
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; |