diff --git a/packages/taler-wallet-cli/src/harness/harness.ts b/packages/taler-wallet-cli/src/harness/harness.ts index 137027964..eac55281b 100644 --- a/packages/taler-wallet-cli/src/harness/harness.ts +++ b/packages/taler-wallet-cli/src/harness/harness.ts @@ -1860,6 +1860,10 @@ function shellWrap(s: string) { return "'" + s.replace("\\", "\\\\").replace("'", "\\'") + "'"; } +export interface WalletCliOpts { + cryptoWorkerType?: "sync" | "node-worker-thread"; +} + export class WalletCli { private currentTimetravel: Duration | undefined; private _client: WalletCoreApiClient; @@ -1879,6 +1883,7 @@ export class WalletCli { constructor( private globalTestState: GlobalTestState, private name: string = "default", + cliOpts: WalletCliOpts = {}, ) { const self = this; this._client = { @@ -1886,12 +1891,15 @@ export class WalletCli { logger.info( `calling wallet with timetravel arg ${j2s(self.timetravelArg)}`, ); + const cryptoWorkerArg = cliOpts.cryptoWorkerType + ? `--crypto-worker=${cliOpts.cryptoWorkerType}` + : ""; const resp = await sh( self.globalTestState, `wallet-${self.name}`, `taler-wallet-cli ${ self.timetravelArg ?? "" - } --no-throttle -LTRACE --skip-defaults --wallet-db '${ + } ${cryptoWorkerArg} --no-throttle -LTRACE --skip-defaults --wallet-db '${ self.dbfile }' api '${op}' ${shellWrap(JSON.stringify(payload))}`, ); diff --git a/packages/taler-wallet-cli/src/index.ts b/packages/taler-wallet-cli/src/index.ts index f5f863ca3..47a520c83 100644 --- a/packages/taler-wallet-cli/src/index.ts +++ b/packages/taler-wallet-cli/src/index.ts @@ -181,6 +181,9 @@ export const walletCli = clk setDangerousTimetravel(x / 1000); }, }) + .maybeOption("cryptoWorker", ["--crypto-worker"], clk.STRING, { + help: "Override crypto worker implementation type." + }) .maybeOption("log", ["-L", "--log"], clk.STRING, { help: "configure log level (NONE, ..., TRACE)", onPresentHandler: (x) => { @@ -228,6 +231,7 @@ async function withWallet( notifyHandler: (n) => { logger.info(`wallet notification: ${j2s(n)}`); }, + cryptoWorkerType: walletCliArgs.wallet.cryptoWorker as any, }); if (checkEnvFlag("TALER_WALLET_BATCH_WITHDRAWAL")) { diff --git a/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts b/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts new file mode 100644 index 000000000..fefdab27a --- /dev/null +++ b/packages/taler-wallet-cli/src/integrationtests/test-wallet-cryptoworker.ts @@ -0,0 +1,55 @@ +/* + This file is part of GNU Taler + (C) 2020 Taler Systems S.A. + + GNU 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. + + GNU 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 + GNU Taler; see the file COPYING. If not, see + */ + +/** + * Imports. + */ +import { j2s } from "@gnu-taler/taler-util"; +import { + checkReserve, + CryptoDispatcher, + depositCoin, + downloadExchangeInfo, + findDenomOrThrow, + NodeHttpLib, + refreshCoin, + SynchronousCryptoWorkerFactory, + TalerError, + topupReserveWithDemobank, + WalletApiOperation, + withdrawCoin, +} from "@gnu-taler/taler-wallet-core"; +import { GlobalTestState, WalletCli } from "../harness/harness.js"; +import { createSimpleTestkudosEnvironment } from "../harness/helpers.js"; + +/** + * Run test for the different crypto workers. + */ +export async function runWalletCryptoWorkerTest(t: GlobalTestState) { + const wallet1 = new WalletCli(t, "w1", { + cryptoWorkerType: "sync", + }); + + await wallet1.client.call(WalletApiOperation.CryptoTest, {}); + + const wallet2 = new WalletCli(t, "w2", { + cryptoWorkerType: "node-worker-thread", + }); + + await wallet2.client.call(WalletApiOperation.CryptoTest, {}); +} + +runWalletCryptoWorkerTest.suites = ["wallet"]; diff --git a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts b/packages/taler-wallet-cli/src/integrationtests/testrunner.ts index 98e56d6ff..c22689e46 100644 --- a/packages/taler-wallet-cli/src/integrationtests/testrunner.ts +++ b/packages/taler-wallet-cli/src/integrationtests/testrunner.ts @@ -93,6 +93,7 @@ import { runTestWithdrawalManualTest } from "./test-withdrawal-manual.js"; import { runAgeRestrictionsPeerTest } from "./test-age-restrictions-peer.js"; import { runWalletBalanceTest } from "./test-wallet-balance.js"; import { runAgeRestrictionsMixedMerchantTest } from "./test-age-restrictions-mixed-merchant.js"; +import { runWalletCryptoWorkerTest } from "./test-wallet-cryptoworker.js"; /** * Test runner. @@ -115,6 +116,7 @@ const allTests: TestMainFunction[] = [ runBankApiTest, runClaimLoopTest, runClauseSchnorrTest, + runWalletCryptoWorkerTest, runDepositTest, runDenomUnofferedTest, runExchangeManagementTest, diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts index 85f9acddc..1c0d509e6 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoDispatcher.ts @@ -15,7 +15,8 @@ */ /** - * API to access the Taler crypto worker thread. + * API to access the Taler crypto worker. + * * @author Florian Dold */ @@ -76,6 +77,10 @@ interface WorkItem { */ const NUM_PRIO = 5; +/** + * A crypto worker factory is responsible for creating new + * crypto workers on-demand. + */ export interface CryptoWorkerFactory { /** * Start a new worker. diff --git a/packages/taler-wallet-core/src/headless/helpers.ts b/packages/taler-wallet-core/src/headless/helpers.ts index 63967d4ad..2be9be9a1 100644 --- a/packages/taler-wallet-core/src/headless/helpers.ts +++ b/packages/taler-wallet-core/src/headless/helpers.ts @@ -61,6 +61,8 @@ export interface DefaultNodeWalletArgs { * of the default one. */ httpLib?: HttpRequestLibrary; + + cryptoWorkerType?: "sync" | "node-worker-thread"; } /** @@ -160,10 +162,11 @@ export async function getDefaultNodeWallet2( const myDb = await openTalerDatabase(myIdbFactory, myVersionChange); let workerFactory; - if (process.env["TALER_WALLET_SYNC_CRYPTO"]) { + const cryptoWorkerType = args.cryptoWorkerType ?? "node-worker-thread"; + if (cryptoWorkerType === "sync") { logger.info("using synchronous crypto worker"); workerFactory = new SynchronousCryptoWorkerFactory(); - } else { + } else if (cryptoWorkerType === "node-worker-thread") { try { // Try if we have worker threads available, fails in older node versions. const _r = "require"; @@ -177,6 +180,8 @@ export async function getDefaultNodeWallet2( ); workerFactory = new SynchronousCryptoWorkerFactory(); } + } else { + throw Error(`unsupported crypto worker type '${cryptoWorkerType}'`); } const timer = new SetTimeoutTimerAPI(); diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index 68ec15591..8689c92c7 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -219,6 +219,7 @@ async function reinitWallet(): Promise { httpLib = new BrowserHttpLib(); // We could (should?) use the BrowserCryptoWorkerFactory here, // but right now we don't, to have less platform differences. + // cryptoWorker = new BrowserCryptoWorkerFactory(); cryptoWorker = new SynchronousCryptoWorkerFactory(); timer = new SetTimeoutTimerAPI(); }