From bf0cb6ab135c2a6d58a0684c17a565ed8422d5a4 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Sun, 16 Jan 2022 17:33:21 -0300 Subject: splitting syncWorker with the factory so the former do not require nodejs runtime --- .../src/crypto/workers/cryptoImplementation.ts | 63 +++------ .../src/crypto/workers/synchronousWorker.ts | 130 +---------------- .../src/crypto/workers/synchronousWorkerFactory.ts | 153 +++++++++++++++++++++ packages/taler-wallet-core/src/index.ts | 1 + 4 files changed, 173 insertions(+), 174 deletions(-) create mode 100644 packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactory.ts (limited to 'packages') diff --git a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts index f9dcc6493..bff2e0eb5 100644 --- a/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts +++ b/packages/taler-wallet-core/src/crypto/workers/cryptoImplementation.ts @@ -25,54 +25,24 @@ */ // FIXME: Crypto should not use DB Types! -import { DenominationRecord, WireFee } from "../../db.js"; - import { - buildSigPS, - CoinDepositPermission, - DenomKeyType, - ExchangeProtocolVersion, - FreshCoin, - hashDenomPub, - RecoupRefreshRequest, + AmountJson, Amounts, BenchmarkResult, buildSigPS, + CoinDepositPermission, createEddsaKeyPair, createHashContext, decodeCrock, + DenomKeyType, DepositInfo, eddsaGetPublic, eddsaSign, eddsaVerify, + encodeCrock, ExchangeProtocolVersion, + FreshCoin, hash, hashDenomPub, kdf, keyExchangeEcdheEddsa, + // Logger, + MakeSyncSignatureRequest, PlanchetCreationRequest, PlanchetCreationResult, + randomBytes, RecoupRefreshRequest, RecoupRequest, - RefreshPlanchetInfo, - TalerSignaturePurpose, -} from "@gnu-taler/taler-util"; -// FIXME: These types should be internal to the wallet! -import { - BenchmarkResult, - PlanchetCreationResult, - PlanchetCreationRequest, - DepositInfo, - MakeSyncSignatureRequest, -} from "@gnu-taler/taler-util"; -import { AmountJson, Amounts } from "@gnu-taler/taler-util"; -import * as timer from "../../util/timer.js"; -import { - encodeCrock, - decodeCrock, - createEddsaKeyPair, - hash, - rsaBlind, - eddsaVerify, - eddsaSign, - rsaUnblind, - stringToBytes, - createHashContext, - keyExchangeEcdheEddsa, - setupRefreshPlanchet, - rsaVerify, + RefreshPlanchetInfo, rsaBlind, rsaUnblind, rsaVerify, setupRefreshPlanchet, setupRefreshTransferPub, setupTipPlanchet, - setupWithdrawPlanchet, - eddsaGetPublic, + setupWithdrawPlanchet, stringToBytes, TalerSignaturePurpose, Timestamp, timestampTruncateToSecond } from "@gnu-taler/taler-util"; -import { randomBytes } from "@gnu-taler/taler-util"; -import { kdf } from "@gnu-taler/taler-util"; -import { Timestamp, timestampTruncateToSecond } from "@gnu-taler/taler-util"; - -import { Logger } from "@gnu-taler/taler-util"; +import bigint from "big-integer"; +import { DenominationRecord, WireFee } from "../../db.js"; +import * as timer from "../../util/timer.js"; import { CreateRecoupRefreshReqRequest, CreateRecoupReqRequest, @@ -80,11 +50,10 @@ import { DerivedTipPlanchet, DeriveRefreshSessionRequest, DeriveTipRequest, - SignTrackTransactionRequest, + SignTrackTransactionRequest } from "../cryptoTypes.js"; -import bigint from "big-integer"; -const logger = new Logger("cryptoImplementation.ts"); +// const logger = new Logger("cryptoImplementation.ts"); function amountToBuffer(amount: AmountJson): Uint8Array { const buffer = new ArrayBuffer(8 + 4 + 12); @@ -161,7 +130,7 @@ async function myEddsaSign( export class CryptoImplementation { static enableTracing = false; - constructor(private primitiveWorker?: PrimitiveWorker) {} + constructor(private primitiveWorker?: PrimitiveWorker) { } /** * Create a pre-coin of the given denomination to be withdrawn from then given diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorker.ts b/packages/taler-wallet-core/src/crypto/workers/synchronousWorker.ts index 9de28dbeb..4d341718e 100644 --- a/packages/taler-wallet-core/src/crypto/workers/synchronousWorker.ts +++ b/packages/taler-wallet-core/src/crypto/workers/synchronousWorker.ts @@ -14,135 +14,16 @@ GNU Taler; see the file COPYING. If not, see */ +import { Logger } from "@gnu-taler/taler-util"; import { CryptoImplementation, - PrimitiveWorker, + PrimitiveWorker } from "./cryptoImplementation.js"; -import { CryptoWorkerFactory } from "./cryptoApi.js"; -import { CryptoWorker } from "./cryptoWorkerInterface.js"; -import child_process from "child_process"; -import type internal from "stream"; -import { OpenedPromise, openPromise } from "../../index.js"; -import { j2s, Logger } from "@gnu-taler/taler-util"; const logger = new Logger("synchronousWorker.ts"); -class MyPrimitiveWorker implements PrimitiveWorker { - proc: child_process.ChildProcessByStdio< - internal.Writable, - internal.Readable, - null - >; - requests: Array<{ - p: OpenedPromise; - req: any; - }> = []; - - constructor() { - const stdoutChunks: Buffer[] = []; - this.proc = child_process.spawn("taler-crypto-worker", { - //stdio: ["pipe", "pipe", "inherit"], - stdio: ["pipe", "pipe", "inherit"], - detached: true, - }); - this.proc.on("close", function (code) { - logger.error("child process exited"); - }); - (this.proc.stdout as any).unref(); - (this.proc.stdin as any).unref(); - this.proc.unref(); - - this.proc.stdout.on("data", (x) => { - // console.log("got chunk", x.toString("utf-8")); - if (x instanceof Buffer) { - const nlIndex = x.indexOf("\n"); - if (nlIndex >= 0) { - const before = x.slice(0, nlIndex); - const after = x.slice(nlIndex + 1); - stdoutChunks.push(after); - const str = Buffer.concat([...stdoutChunks, before]).toString( - "utf-8", - ); - const req = this.requests.shift()!; - if (this.requests.length === 0) { - this.proc.unref(); - } - //logger.info(`got response: ${str}`); - req.p.resolve(JSON.parse(str)); - } else { - stdoutChunks.push(x); - } - } else { - throw Error(`unexpected data chunk type (${typeof x})`); - } - }); - } - - async setupRefreshPlanchet(req: { - transfer_secret: string; - coin_index: number; - }): Promise<{ - coin_pub: string; - coin_priv: string; - blinding_key: string; - }> { - return this.queueRequest({ - op: "setup_refresh_planchet", - args: req, - }); - } - - async queueRequest(req: any): Promise { - const p = openPromise(); - if (this.requests.length === 0) { - this.proc.ref(); - } - this.requests.push({ req, p }); - this.proc.stdin.write(JSON.stringify(req) + "\n"); - return p.promise; - } - - async eddsaVerify(req: { - msg: string; - sig: string; - pub: string; - }): Promise<{ valid: boolean }> { - return this.queueRequest({ - op: "eddsa_verify", - args: req, - }); - } - - async eddsaSign(req: { - msg: string; - priv: string; - }): Promise<{ sig: string }> { - return this.queueRequest({ - op: "eddsa_sign", - args: req, - }); - } -} - -/** - * The synchronous crypto worker produced by this factory doesn't run in the - * background, but actually blocks the caller until the operation is done. - */ -export class SynchronousCryptoWorkerFactory implements CryptoWorkerFactory { - startWorker(): CryptoWorker { - if (typeof require === "undefined") { - throw Error("cannot make worker, require(...) not defined"); - } - return new SynchronousCryptoWorker(); - } - - getConcurrency(): number { - return 1; - } -} - /** * Worker implementation that uses node subprocesses. */ @@ -157,14 +38,9 @@ export class SynchronousCryptoWorker { */ onerror: undefined | ((m: any) => void); - primitiveWorker: PrimitiveWorker; - - constructor() { + constructor(private primitiveWorker?: PrimitiveWorker) { this.onerror = undefined; this.onmessage = undefined; - if (process.env["TALER_WALLET_PRIMITIVE_WORKER"]) { - this.primitiveWorker = new MyPrimitiveWorker(); - } } /** diff --git a/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactory.ts b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactory.ts new file mode 100644 index 000000000..ca63c7687 --- /dev/null +++ b/packages/taler-wallet-core/src/crypto/workers/synchronousWorkerFactory.ts @@ -0,0 +1,153 @@ +/* + This file is part of GNU Taler + (C) 2019 GNUnet e.V. + + 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 + */ + +import { + PrimitiveWorker, +} from "./cryptoImplementation.js"; + +import { CryptoWorkerFactory } from "./cryptoApi.js"; +import { CryptoWorker } from "./cryptoWorkerInterface.js"; + +import child_process from "child_process"; +import type internal from "stream"; +import { OpenedPromise, openPromise } from "../../index.js"; +import { Logger } from "@gnu-taler/taler-util"; +import { SynchronousCryptoWorker } from "./synchronousWorker.js"; + +const logger = new Logger("synchronousWorkerFactory.ts"); + +class MyPrimitiveWorker implements PrimitiveWorker { + proc: child_process.ChildProcessByStdio< + internal.Writable, + internal.Readable, + null + >; + requests: Array<{ + p: OpenedPromise; + req: any; + }> = []; + + constructor() { + const stdoutChunks: Buffer[] = []; + this.proc = child_process.spawn("taler-crypto-worker", { + //stdio: ["pipe", "pipe", "inherit"], + stdio: ["pipe", "pipe", "inherit"], + detached: true, + }); + this.proc.on("close", (): void => { + logger.error("child process exited"); + }); + (this.proc.stdout as any).unref(); + (this.proc.stdin as any).unref(); + this.proc.unref(); + + this.proc.stdout.on("data", (x) => { + // console.log("got chunk", x.toString("utf-8")); + if (x instanceof Buffer) { + const nlIndex = x.indexOf("\n"); + if (nlIndex >= 0) { + const before = x.slice(0, nlIndex); + const after = x.slice(nlIndex + 1); + stdoutChunks.push(after); + const str = Buffer.concat([...stdoutChunks, before]).toString( + "utf-8", + ); + const req = this.requests.shift(); + if (!req) { + throw Error("request was undefined") + } + if (this.requests.length === 0) { + this.proc.unref(); + } + //logger.info(`got response: ${str}`); + req.p.resolve(JSON.parse(str)); + } else { + stdoutChunks.push(x); + } + } else { + throw Error(`unexpected data chunk type (${typeof x})`); + } + }); + } + + async setupRefreshPlanchet(req: { + transfer_secret: string; + coin_index: number; + }): Promise<{ + coin_pub: string; + coin_priv: string; + blinding_key: string; + }> { + return this.queueRequest({ + op: "setup_refresh_planchet", + args: req, + }); + } + + async queueRequest(req: any): Promise { + const p = openPromise(); + if (this.requests.length === 0) { + this.proc.ref(); + } + this.requests.push({ req, p }); + this.proc.stdin.write(`${JSON.stringify(req)}\n`); + return p.promise; + } + + async eddsaVerify(req: { + msg: string; + sig: string; + pub: string; + }): Promise<{ valid: boolean }> { + return this.queueRequest({ + op: "eddsa_verify", + args: req, + }); + } + + async eddsaSign(req: { + msg: string; + priv: string; + }): Promise<{ sig: string }> { + return this.queueRequest({ + op: "eddsa_sign", + args: req, + }); + } +} + +/** + * The synchronous crypto worker produced by this factory doesn't run in the + * background, but actually blocks the caller until the operation is done. + */ +export class SynchronousCryptoWorkerFactory implements CryptoWorkerFactory { + startWorker(): CryptoWorker { + if (typeof require === "undefined") { + throw Error("cannot make worker, require(...) not defined"); + } + + let primitiveWorker; + if (process.env["TALER_WALLET_PRIMITIVE_WORKER"]) { + primitiveWorker = new MyPrimitiveWorker(); + } + + return new SynchronousCryptoWorker(primitiveWorker); + } + + getConcurrency(): number { + return 1; + } +} diff --git a/packages/taler-wallet-core/src/index.ts b/packages/taler-wallet-core/src/index.ts index 5489bd5a3..179ba6b8f 100644 --- a/packages/taler-wallet-core/src/index.ts +++ b/packages/taler-wallet-core/src/index.ts @@ -36,6 +36,7 @@ export * from "./db-utils.js"; export { CryptoImplementation } from "./crypto/workers/cryptoImplementation.js"; export type { CryptoWorker } from "./crypto/workers/cryptoWorkerInterface.js"; export { CryptoWorkerFactory, CryptoApi } from "./crypto/workers/cryptoApi.js"; +export { SynchronousCryptoWorker } from "./crypto/workers/synchronousWorker.js" export * from "./pending-types.js"; -- cgit v1.2.3