wallet-core: improve crypto worker code duplication
Also add new testCrypto call for later testing
This commit is contained in:
parent
4d232fd565
commit
dd14e67c70
@ -152,6 +152,14 @@ export enum TalerErrorCode {
|
|||||||
GENERIC_PARAMETER_MALFORMED = 26,
|
GENERIC_PARAMETER_MALFORMED = 26,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reserve public key given as part of a /reserves/ endpoint was malformed.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
GENERIC_RESERVE_PUB_MALFORMED = 27,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The currencies involved in the operation do not match.
|
* The currencies involved in the operation do not match.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
||||||
@ -456,14 +464,6 @@ export enum TalerErrorCode {
|
|||||||
EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE = 1018,
|
EXCHANGE_GENERIC_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE = 1018,
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reserve public key was malformed.
|
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
|
||||||
* (A value of 0 indicates that the error is generated client-side).
|
|
||||||
*/
|
|
||||||
EXCHANGE_GENERIC_RESERVE_PUB_MALFORMED = 1019,
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The time at the server is too far off from the time specified in the request. Most likely the client system time is wrong.
|
* The time at the server is too far off from the time specified in the request. Most likely the client system time is wrong.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
||||||
@ -1288,6 +1288,38 @@ export enum TalerErrorCode {
|
|||||||
EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID = 1778,
|
EXCHANGE_RESERVES_RESERVE_MERGE_SIGNATURE_INVALID = 1778,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature by the reserve affirming the open operation is invalid.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
EXCHANGE_RESERVES_OPEN_BAD_SIGNATURE = 1785,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature by the reserve affirming the close operation is invalid.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
EXCHANGE_RESERVES_CLOSE_BAD_SIGNATURE = 1786,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The signature by the reserve affirming the attestion request is invalid.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_FORBIDDEN (403).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
EXCHANGE_RESERVES_ATTEST_BAD_SIGNATURE = 1787,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The exchange does not know an origin account to which the remaining reserve balance could be wired to, and the wallet failed to provide one.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_CONFLICT (409).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
EXCHANGE_RESERVES_CLOSE_NO_TARGET_ACCOUNT = 1788,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The auditor that was supposed to be disabled is unknown to this exchange.
|
* The auditor that was supposed to be disabled is unknown to this exchange.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
|
* Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
|
||||||
@ -1768,14 +1800,6 @@ export enum TalerErrorCode {
|
|||||||
MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE = 2001,
|
MERCHANT_GENERIC_HOLE_IN_WIRE_FEE_STRUCTURE = 2001,
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The reserve key of given to a /reserves/ handler was malformed.
|
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_BAD_REQUEST (400).
|
|
||||||
* (A value of 0 indicates that the error is generated client-side).
|
|
||||||
*/
|
|
||||||
MERCHANT_GENERIC_RESERVE_PUB_MALFORMED = 2002,
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The proposal is not known to the backend.
|
* The proposal is not known to the backend.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
|
* Returned with an HTTP status code of #MHD_HTTP_NOT_FOUND (404).
|
||||||
@ -3064,6 +3088,14 @@ export enum TalerErrorCode {
|
|||||||
WALLET_CRYPTO_WORKER_ERROR = 7023,
|
WALLET_CRYPTO_WORKER_ERROR = 7023,
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The crypto worker received a bad request.
|
||||||
|
* Returned with an HTTP status code of #MHD_HTTP_UNINITIALIZED (0).
|
||||||
|
* (A value of 0 indicates that the error is generated client-side).
|
||||||
|
*/
|
||||||
|
WALLET_CRYPTO_WORKER_BAD_REQUEST = 7024,
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We encountered a timeout with our payment backend.
|
* We encountered a timeout with our payment backend.
|
||||||
* Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).
|
* Returned with an HTTP status code of #MHD_HTTP_GATEWAY_TIMEOUT (504).
|
||||||
|
@ -29,7 +29,7 @@ import { timer, performanceNow, TimerHandle } from "../../util/timer.js";
|
|||||||
import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js";
|
import { nullCrypto, TalerCryptoInterface } from "../cryptoImplementation.js";
|
||||||
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
||||||
|
|
||||||
const logger = new Logger("cryptoApi.ts");
|
const logger = new Logger("cryptoDispatcher.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* State of a crypto worker.
|
* State of a crypto worker.
|
||||||
@ -238,7 +238,7 @@ export class CryptoDispatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleWorkerMessage(ws: WorkerInfo, msg: any): void {
|
handleWorkerMessage(ws: WorkerInfo, msg: any): void {
|
||||||
const id = msg.data.id;
|
const id = msg.id;
|
||||||
if (typeof id !== "number") {
|
if (typeof id !== "number") {
|
||||||
logger.error("rpc id must be number");
|
logger.error("rpc id must be number");
|
||||||
return;
|
return;
|
||||||
@ -256,12 +256,12 @@ export class CryptoDispatcher {
|
|||||||
if (currentWorkItem.state === WorkItemState.Running) {
|
if (currentWorkItem.state === WorkItemState.Running) {
|
||||||
this.numBusy--;
|
this.numBusy--;
|
||||||
currentWorkItem.state = WorkItemState.Finished;
|
currentWorkItem.state = WorkItemState.Finished;
|
||||||
if (msg.data.type === "success") {
|
if (msg.type === "success") {
|
||||||
currentWorkItem.resolve(msg.data.result);
|
currentWorkItem.resolve(msg.result);
|
||||||
} else if (msg.data.type === "error") {
|
} else if (msg.type === "error") {
|
||||||
currentWorkItem.reject(
|
currentWorkItem.reject(
|
||||||
TalerError.fromDetail(TalerErrorCode.WALLET_CRYPTO_WORKER_ERROR, {
|
TalerError.fromDetail(TalerErrorCode.WALLET_CRYPTO_WORKER_ERROR, {
|
||||||
innerError: msg.data.error,
|
innerError: msg.error,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,8 +1,65 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 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 <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
|
import { TalerErrorDetail } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for all crypto workers.
|
||||||
|
*/
|
||||||
export interface CryptoWorker {
|
export interface CryptoWorker {
|
||||||
postMessage(message: any): void;
|
postMessage(message: any): void;
|
||||||
|
|
||||||
terminate(): void;
|
terminate(): void;
|
||||||
|
|
||||||
onmessage: ((m: any) => void) | undefined;
|
onmessage: ((m: any) => void) | undefined;
|
||||||
onerror: ((m: any) => void) | undefined;
|
onerror: ((m: any) => void) | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of requests sent to the crypto worker.
|
||||||
|
*/
|
||||||
|
export type CryptoWorkerRequestMessage = {
|
||||||
|
/**
|
||||||
|
* Operation ID to correlate request with the response.
|
||||||
|
*/
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation to execute.
|
||||||
|
*/
|
||||||
|
operation: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Operation-specific request payload.
|
||||||
|
*/
|
||||||
|
req: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of messages sent back by the crypto worker.
|
||||||
|
*/
|
||||||
|
export type CryptoWorkerResponseMessage =
|
||||||
|
| {
|
||||||
|
type: "success";
|
||||||
|
id: number;
|
||||||
|
result: any;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: "error";
|
||||||
|
id?: number;
|
||||||
|
error: TalerErrorDetail;
|
||||||
|
};
|
||||||
|
@ -17,12 +17,12 @@
|
|||||||
/**
|
/**
|
||||||
* Imports
|
* Imports
|
||||||
*/
|
*/
|
||||||
|
import { Logger } from "@gnu-taler/taler-util";
|
||||||
|
import os from "os";
|
||||||
|
import { nativeCryptoR } from "../cryptoImplementation.js";
|
||||||
import { CryptoWorkerFactory } from "./cryptoDispatcher.js";
|
import { CryptoWorkerFactory } from "./cryptoDispatcher.js";
|
||||||
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
||||||
import os from "os";
|
import { processRequestWithImpl } from "./worker-common.js";
|
||||||
import { Logger } from "@gnu-taler/taler-util";
|
|
||||||
import { nativeCryptoR } from "../cryptoImplementation.js";
|
|
||||||
import { getErrorDetailFromException } from "../../errors.js";
|
|
||||||
|
|
||||||
const logger = new Logger("nodeThreadWorker.ts");
|
const logger = new Logger("nodeThreadWorker.ts");
|
||||||
|
|
||||||
@ -71,44 +71,7 @@ const workerCode = `
|
|||||||
*/
|
*/
|
||||||
export function handleWorkerMessage(msg: any): void {
|
export function handleWorkerMessage(msg: any): void {
|
||||||
const handleRequest = async (): Promise<void> => {
|
const handleRequest = async (): Promise<void> => {
|
||||||
const req = msg.req;
|
const responseMsg = await processRequestWithImpl(msg, nativeCryptoR);
|
||||||
if (typeof req !== "object") {
|
|
||||||
logger.error("request must be an object");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const id = msg.id;
|
|
||||||
if (typeof id !== "number") {
|
|
||||||
logger.error("RPC id must be number");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const operation = msg.operation;
|
|
||||||
if (typeof operation !== "string") {
|
|
||||||
logger.error("RPC operation must be string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const impl = nativeCryptoR;
|
|
||||||
|
|
||||||
if (!(operation in impl)) {
|
|
||||||
logger.error(`crypto operation '${operation}' not found`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let responseMsg: any;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await (impl as any)[operation](impl, req);
|
|
||||||
responseMsg = { data: { type: "success", result, id } };
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error(`error during operation: ${e.stack ?? e.toString()}`);
|
|
||||||
responseMsg = {
|
|
||||||
data: {
|
|
||||||
type: "error",
|
|
||||||
error: getErrorDetailFromException(e),
|
|
||||||
id,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||||
const _r = "require";
|
const _r = "require";
|
||||||
@ -122,16 +85,12 @@ export function handleWorkerMessage(msg: any): void {
|
|||||||
logger.error("parent port not available (not running in thread?");
|
logger.error("parent port not available (not running in thread?");
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(
|
logger.error(`error in node worker: ${e.stack ?? e.toString()}`);
|
||||||
`error sending back operation result: ${e.stack ?? e.toString()}`,
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handleRequest().catch((e) => {
|
handleRequest();
|
||||||
logger.error("error in node worker", e);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleWorkerError(e: Error): void {
|
export function handleWorkerError(e: Error): void {
|
||||||
|
@ -24,6 +24,9 @@ import { OpenedPromise, openPromise } from "../../util/promiseUtils.js";
|
|||||||
|
|
||||||
const logger = new Logger("synchronousWorkerFactory.ts");
|
const logger = new Logger("synchronousWorkerFactory.ts");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client for the crypto helper process (taler-crypto-worker from exchange.git).
|
||||||
|
*/
|
||||||
export class CryptoRpcClient {
|
export class CryptoRpcClient {
|
||||||
proc: child_process.ChildProcessByStdio<
|
proc: child_process.ChildProcessByStdio<
|
||||||
internal.Writable,
|
internal.Writable,
|
||||||
|
@ -14,20 +14,24 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Logger } from "@gnu-taler/taler-util";
|
import { j2s, Logger } from "@gnu-taler/taler-util";
|
||||||
import { getErrorDetailFromException } from "../../errors.js";
|
|
||||||
import {
|
import {
|
||||||
nativeCryptoR,
|
nativeCryptoR,
|
||||||
TalerCryptoInterfaceR,
|
TalerCryptoInterfaceR,
|
||||||
} from "../cryptoImplementation.js";
|
} from "../cryptoImplementation.js";
|
||||||
|
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
||||||
import { CryptoRpcClient } from "./rpcClient.js";
|
import { CryptoRpcClient } from "./rpcClient.js";
|
||||||
|
import { processRequestWithImpl } from "./worker-common.js";
|
||||||
|
|
||||||
const logger = new Logger("synchronousWorker.ts");
|
const logger = new Logger("synchronousWorker.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worker implementation that uses node subprocesses.
|
* Worker implementation that uses node subprocesses.
|
||||||
|
*
|
||||||
|
* The node cryto worker can also use IPC to offload cryptographic
|
||||||
|
* operations to a helper process (ususally written in C / part of taler-exchange).
|
||||||
*/
|
*/
|
||||||
export class SynchronousCryptoWorker {
|
export class SynchronousCryptoWorker implements CryptoWorker {
|
||||||
/**
|
/**
|
||||||
* Function to be called when we receive a message from the worker thread.
|
* Function to be called when we receive a message from the worker thread.
|
||||||
*/
|
*/
|
||||||
@ -144,61 +148,19 @@ export class SynchronousCryptoWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleRequest(
|
|
||||||
operation: string,
|
|
||||||
id: number,
|
|
||||||
req: unknown,
|
|
||||||
): Promise<void> {
|
|
||||||
const impl = this.cryptoImplR;
|
|
||||||
|
|
||||||
if (!(operation in impl)) {
|
|
||||||
logger.error(`crypto operation '${operation}' not found`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let responseMsg: any;
|
|
||||||
try {
|
|
||||||
const result = await (impl as any)[operation](impl, req);
|
|
||||||
responseMsg = { data: { type: "success", result, id } };
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error(`error during operation: ${e.stack ?? e.toString()}`);
|
|
||||||
responseMsg = {
|
|
||||||
data: {
|
|
||||||
type: "error",
|
|
||||||
id,
|
|
||||||
error: getErrorDetailFromException(e),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setTimeout(() => this.dispatchMessage(responseMsg), 0);
|
|
||||||
} catch (e) {
|
|
||||||
logger.error("got error during dispatch", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the worker thread.
|
* Send a message to the worker thread.
|
||||||
*/
|
*/
|
||||||
postMessage(msg: any): void {
|
postMessage(msg: any): void {
|
||||||
const req = msg.req;
|
const handleRequest = async () => {
|
||||||
if (typeof req !== "object") {
|
const responseMsg = await processRequestWithImpl(msg, this.cryptoImplR);
|
||||||
logger.error("request must be an object");
|
try {
|
||||||
return;
|
setTimeout(() => this.dispatchMessage(responseMsg), 0);
|
||||||
}
|
} catch (e) {
|
||||||
const id = msg.id;
|
logger.error("got error during dispatch", e);
|
||||||
if (typeof id !== "number") {
|
}
|
||||||
logger.error("RPC id must be number");
|
};
|
||||||
return;
|
handleRequest().catch((e) => {
|
||||||
}
|
|
||||||
const operation = msg.operation;
|
|
||||||
if (typeof operation !== "string") {
|
|
||||||
logger.error("RPC operation must be string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handleRequest(operation, id, req).catch((e) => {
|
|
||||||
logger.error("Error while handling crypto request:", e);
|
logger.error("Error while handling crypto request:", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -14,19 +14,26 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imports.
|
||||||
|
*/
|
||||||
import { Logger } from "@gnu-taler/taler-util";
|
import { Logger } from "@gnu-taler/taler-util";
|
||||||
import { getErrorDetailFromException } from "../../errors.js";
|
|
||||||
import {
|
import {
|
||||||
nativeCryptoR,
|
nativeCryptoR,
|
||||||
TalerCryptoInterfaceR,
|
TalerCryptoInterfaceR,
|
||||||
} from "../cryptoImplementation.js";
|
} from "../cryptoImplementation.js";
|
||||||
|
import { CryptoWorker } from "./cryptoWorkerInterface.js";
|
||||||
|
import {
|
||||||
|
processRequestWithImpl,
|
||||||
|
} from "./worker-common.js";
|
||||||
|
|
||||||
const logger = new Logger("synchronousWorker.ts");
|
const logger = new Logger("synchronousWorker.ts");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Worker implementation that uses node subprocesses.
|
* Worker implementation that synchronously executes cryptographic
|
||||||
|
* operations.
|
||||||
*/
|
*/
|
||||||
export class SynchronousCryptoWorker {
|
export class SynchronousCryptoWorker implements CryptoWorker {
|
||||||
/**
|
/**
|
||||||
* Function to be called when we receive a message from the worker thread.
|
* Function to be called when we receive a message from the worker thread.
|
||||||
*/
|
*/
|
||||||
@ -65,61 +72,22 @@ export class SynchronousCryptoWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleRequest(
|
|
||||||
operation: string,
|
|
||||||
id: number,
|
|
||||||
req: unknown,
|
|
||||||
): Promise<void> {
|
|
||||||
const impl = this.cryptoImplR;
|
|
||||||
|
|
||||||
if (!(operation in impl)) {
|
|
||||||
logger.error(`crypto operation '${operation}' not found`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let responseMsg: any;
|
|
||||||
try {
|
|
||||||
const result = await (impl as any)[operation](impl, req);
|
|
||||||
responseMsg = { data: { type: "success", result, id } };
|
|
||||||
} catch (e: any) {
|
|
||||||
logger.error(`error during operation: ${e.stack ?? e.toString()}`);
|
|
||||||
responseMsg = {
|
|
||||||
data: {
|
|
||||||
type: "error",
|
|
||||||
id,
|
|
||||||
error: getErrorDetailFromException(e),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
setTimeout(() => this.dispatchMessage(responseMsg), 0);
|
|
||||||
} catch (e) {
|
|
||||||
logger.error("got error during dispatch", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a message to the worker thread.
|
* Send a message to the worker thread.
|
||||||
*/
|
*/
|
||||||
postMessage(msg: any): void {
|
postMessage(msg: any): void {
|
||||||
const req = msg.req;
|
const handleRequest = async () => {
|
||||||
if (typeof req !== "object") {
|
const responseMsg = await processRequestWithImpl(
|
||||||
logger.error("request must be an object");
|
msg,
|
||||||
return;
|
this.cryptoImplR,
|
||||||
}
|
);
|
||||||
const id = msg.id;
|
try {
|
||||||
if (typeof id !== "number") {
|
setTimeout(() => this.dispatchMessage(responseMsg), 0);
|
||||||
logger.error("RPC id must be number");
|
} catch (e) {
|
||||||
return;
|
logger.error("got error during dispatch", e);
|
||||||
}
|
}
|
||||||
const operation = msg.operation;
|
};
|
||||||
if (typeof operation !== "string") {
|
handleRequest().catch((e) => {
|
||||||
logger.error("RPC operation must be string");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.handleRequest(operation, id, req).catch((e) => {
|
|
||||||
logger.error("Error while handling crypto request:", e);
|
logger.error("Error while handling crypto request:", e);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,9 @@ export interface DetailsMap {
|
|||||||
[TalerErrorCode.WALLET_CRYPTO_WORKER_ERROR]: {
|
[TalerErrorCode.WALLET_CRYPTO_WORKER_ERROR]: {
|
||||||
innerError: TalerErrorDetail;
|
innerError: TalerErrorDetail;
|
||||||
};
|
};
|
||||||
|
[TalerErrorCode.WALLET_CRYPTO_WORKER_BAD_REQUEST]: {
|
||||||
|
detail: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type ErrBody<Y> = Y extends keyof DetailsMap ? DetailsMap[Y] : never;
|
type ErrBody<Y> = Y extends keyof DetailsMap ? DetailsMap[Y] : never;
|
||||||
|
@ -92,6 +92,7 @@ export enum WalletApiOperation {
|
|||||||
WithdrawTestBalance = "withdrawTestBalance",
|
WithdrawTestBalance = "withdrawTestBalance",
|
||||||
PreparePayForUri = "preparePayForUri",
|
PreparePayForUri = "preparePayForUri",
|
||||||
RunIntegrationTest = "runIntegrationTest",
|
RunIntegrationTest = "runIntegrationTest",
|
||||||
|
CryptoTest = "cryptoTest",
|
||||||
TestPay = "testPay",
|
TestPay = "testPay",
|
||||||
AddExchange = "addExchange",
|
AddExchange = "addExchange",
|
||||||
GetTransactions = "getTransactions",
|
GetTransactions = "getTransactions",
|
||||||
@ -524,6 +525,15 @@ export type RunIntegrationTestOp = {
|
|||||||
response: {};
|
response: {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test crypto worker.
|
||||||
|
*/
|
||||||
|
export type CryptoTestOp = {
|
||||||
|
op: WalletApiOperation.CryptoTest;
|
||||||
|
request: {};
|
||||||
|
response: any;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make withdrawal on a test deployment of the exchange
|
* Make withdrawal on a test deployment of the exchange
|
||||||
* and merchant.
|
* and merchant.
|
||||||
@ -639,6 +649,7 @@ export type WalletOperations = {
|
|||||||
[WalletApiOperation.AddBackupProvider]: AddBackupProviderOp;
|
[WalletApiOperation.AddBackupProvider]: AddBackupProviderOp;
|
||||||
[WalletApiOperation.GetBackupInfo]: GetBackupInfoOp;
|
[WalletApiOperation.GetBackupInfo]: GetBackupInfoOp;
|
||||||
[WalletApiOperation.RunIntegrationTest]: RunIntegrationTestOp;
|
[WalletApiOperation.RunIntegrationTest]: RunIntegrationTestOp;
|
||||||
|
[WalletApiOperation.CryptoTest]: CryptoTestOp;
|
||||||
[WalletApiOperation.WithdrawTestBalance]: WithdrawTestBalanceOp;
|
[WalletApiOperation.WithdrawTestBalance]: WithdrawTestBalanceOp;
|
||||||
[WalletApiOperation.TestPay]: TestPayOp;
|
[WalletApiOperation.TestPay]: TestPayOp;
|
||||||
[WalletApiOperation.ExportDb]: ExportDbOp;
|
[WalletApiOperation.ExportDb]: ExportDbOp;
|
||||||
|
@ -1445,6 +1445,9 @@ async function dispatchRequestInternal(
|
|||||||
logger.info(`started fakebank withdrawal: ${j2s(fbResp)}`);
|
logger.info(`started fakebank withdrawal: ${j2s(fbResp)}`);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
case "testCrypto": {
|
||||||
|
return await ws.cryptoApi.hashString({ str: "hello world" });
|
||||||
|
}
|
||||||
case "clearDb":
|
case "clearDb":
|
||||||
await clearDatabase(ws.db.idbHandle());
|
await clearDatabase(ws.db.idbHandle());
|
||||||
return {};
|
return {};
|
||||||
|
@ -28,6 +28,8 @@ export class BrowserCryptoWorkerFactory implements CryptoWorkerFactory {
|
|||||||
startWorker(): CryptoWorker {
|
startWorker(): CryptoWorker {
|
||||||
const workerCtor = Worker;
|
const workerCtor = Worker;
|
||||||
const workerPath = "/dist/browserWorkerEntry.js";
|
const workerPath = "/dist/browserWorkerEntry.js";
|
||||||
|
// FIXME: This is not really the same interface as the crypto worker!
|
||||||
|
// We need to wrap it.
|
||||||
return new workerCtor(workerPath) as CryptoWorker;
|
return new workerCtor(workerPath) as CryptoWorker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +217,8 @@ async function reinitWallet(): Promise<void> {
|
|||||||
timer = new SetTimeoutTimerAPI();
|
timer = new SetTimeoutTimerAPI();
|
||||||
} else {
|
} else {
|
||||||
httpLib = new BrowserHttpLib();
|
httpLib = new BrowserHttpLib();
|
||||||
|
// We could (should?) use the BrowserCryptoWorkerFactory here,
|
||||||
|
// but right now we don't, to have less platform differences.
|
||||||
cryptoWorker = new SynchronousCryptoWorkerFactory();
|
cryptoWorker = new SynchronousCryptoWorkerFactory();
|
||||||
timer = new SetTimeoutTimerAPI();
|
timer = new SetTimeoutTimerAPI();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user