Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update deps and minor cleanup #74

Merged
merged 12 commits into from
Oct 14, 2024
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "node_modules/lerna/schemas/lerna-schema.json",
"npmClient": "npm",
"version": "3.0.0",
"version": "independent",
"packages": ["packages/tss-*"]
}
15,917 changes: 7,689 additions & 8,228 deletions package-lock.json

Large diffs are not rendered by default.

43 changes: 22 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,38 @@
"pack:lerna": "lerna exec -- 'npm pack'",
"publish:lerna": "npm run clean && npm install && npm run build && lerna publish",
"just:publish:lerna": "lerna publish",
"serve:local": "cd packages/web-example && webpack serve:local",
"serve:devnet": "cd packages/web-example && webpack serve:devnet",
"serve:local": "cd packages/web-example && npm run serve:local",
"serve:devnet": "cd packages/web-example && npm run serve:devnet",
"test:devnet": "node scripts/e2e.js 1 web-example serve:devnet 0"
},
"keywords": [],
"author": "Web3Auth",
"license": "ISC",
"devDependencies": {
"@babel/core": "~7.23.2",
"@babel/core": "7.25.2",
"@babel/register": "^7.25.7",
"@babel/plugin-syntax-bigint": "^7.8.3",
"@babel/plugin-transform-class-properties": "^7.23.3",
"@babel/plugin-transform-object-rest-spread": "^7.23.4",
"@babel/plugin-transform-runtime": "~7.23.2",
"@babel/preset-env": "^7.23.2",
"@babel/preset-typescript": "^7.23.2",
"@babel/runtime": "~7.23.2",
"@toruslabs/config": "^2.0.2",
"@toruslabs/eslint-config-typescript": "^3.0.1",
"@toruslabs/torus-scripts": "^5.3.1",
"@types/elliptic": "^6.4.16",
"babel-loader": "^9.1.3",
"chromedriver": "^126.0.1",
"@babel/plugin-transform-class-properties": "^7.25.7",
"@babel/plugin-transform-object-rest-spread": "^7.25.7",
"@babel/plugin-transform-runtime": "~7.25.7",
"@babel/preset-env": "^7.25.7",
"@babel/preset-typescript": "^7.25.7",
"@babel/runtime": "~7.25.7",
"@toruslabs/config": "^2.2.0",
"@toruslabs/eslint-config-typescript": "^3.3.3",
"@toruslabs/torus-scripts": "^6.1.2",
"@types/elliptic": "^6.4.18",
"babel-loader": "^9.2.1",
"chromedriver": "^128",
"find-process": "^1.4.7",
"husky": "^8.0.3",
"lerna": "^8.0.2",
"lint-staged": "^15.0.2",
"prettier": "^3.0.3",
"selenium-webdriver": "^4.16.0",
"ts-node": "^10.9.1",
"lerna": "^8.1.8",
"lint-staged": "^15.2.10",
"prettier": "^3.3.3",
"selenium-webdriver": "^4.25.0",
"ts-node": "^10.9.2",
"tsconfig-paths-webpack-plugin": "^4.1.0",
"typescript": "^5.2.2",
"typescript": "^5.6.3",
"wait-on": "^7.0.1"
}
}
20 changes: 9 additions & 11 deletions packages/tss-client/package.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"name": "@toruslabs/tss-client",
"version": "3.0.0",
"version": "3.1.0",
"description": "Client SDK for MPECDSA signing",
"files": [
"dist"
],
"main": "dist/tssClient.cjs.js",
"module": "dist/tssClient.esm.js",
"main": "dist/lib.cjs/index.js",
"module": "dist/lib.esm/index.js",
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved
"unpkg": "dist/tssClient.umd.min.js",
"jsdelivr": "dist/tssClient.umd.min.js",
"types": "dist/types/index.d.ts",
Expand All @@ -22,17 +22,15 @@
"dependencies": {
"@toruslabs/eccrypto": "^5.0.4",
"bn.js": "^5.2.1",
"elliptic": "^6.5.4",
"ethereum-cryptography": "^2.1.3",
"socket.io-client": "^4.7.4"
"elliptic": "^6.5.7",
"ethereum-cryptography": "^3.0.0",
"socket.io-client": "^4.8.0"
},
"devDependencies": {
"@types/chrome": "^0.0.268",
"@toruslabs/tss-dkls-lib": "^3.0.0",
"@types/bn.js": "^5.1.5",
"@types/elliptic": "^6.4.18",
"rimraf": "^5.0.5",
"rollup-plugin-web-worker-loader": "^1.6.1"
"@toruslabs/tss-dkls-lib": "^4.0.0",
"@types/bn.js": "^5.1.6",
"@types/elliptic": "^6.4.18"
},
"publishConfig": {
"access": "public"
Expand Down
170 changes: 85 additions & 85 deletions packages/tss-client/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,14 @@
/* eslint-disable no-console */
import { generatePrivate } from "@toruslabs/eccrypto";
import type TssLib from "@toruslabs/tss-dkls-lib";
import type { WasmLib } from "@toruslabs/tss-dkls-lib";
import BN from "bn.js";
import { keccak256 } from "ethereum-cryptography/keccak";
import { Socket } from "socket.io-client";
import type { Socket } from "socket.io-client";

import { DELIMITERS, WEB3_SESSION_HEADER_KEY } from "./constants";
import { Msg } from "./interfaces";
import { getEc } from "./utils";

// TODO: create namespace for globals
if (globalThis.tss_clients === undefined) {
// Cleanup leads to memory leaks with just an object. Should use a map instead.
// TODO: This should be singular
globalThis.tss_clients = new Map();
}

if (globalThis.js_read_msg === undefined) {
globalThis.js_read_msg = async function (session: string, self_index: number, party: number, msg_type: string) {
const tss_client = globalThis.tss_clients.get(session) as Client;
tss_client.log(`reading msg, ${msg_type}`);
if (msg_type === "ga1_worker_support") {
return "unsupported";
}
const mm = tss_client.msgQueue.find((m) => m.sender === party && m.recipient === self_index && m.msg_type === msg_type);
if (!mm) {
// It is very important that this promise can reject, since it is passed through to dkls library and awaited internally. If it cannot reject and a message is lost,
// it will never resolve and hang indefinitely with no possibility of recovery.
return new Promise((resolve, reject) => {
let counter = 0;
const timer = setInterval(() => {
const found = tss_client.msgQueue.find((m) => m.sender === party && m.recipient === self_index && m.msg_type === msg_type);
if (found !== undefined) {
clearInterval(timer);
resolve(found.msg_data);
}
if (counter >= 1000) {
clearInterval(timer);
// TODO Fix wasm to handle error objects properly and then reject
// with Error instead of string.
//
// eslint-disable-next-line prefer-promise-reject-errors
reject("Message not received in a reasonable time");
}
counter++;
}, 10);
});
}
return mm.msg_data;
};
}

if (globalThis.js_send_msg === undefined) {
globalThis.js_send_msg = async function (session: string, self_index: number, party: number, msg_type: string, msg_data?: string) {
const tss_client = globalThis.tss_clients.get(session) as Client;
tss_client.log(`sending msg, ${msg_type}`);
if (msg_type.indexOf("ga1_data_unprocessed") > -1) {
throw new Error("ga1_data_unprocessed should not be sent directly");
}

if (tss_client.websocketOnly) {
const socket = tss_client.sockets[party];
socket.emit("send_msg", {
session,
sender: self_index,
recipient: party,
msg_type,
msg_data,
});
} else {
const sid = session.split(DELIMITERS.Delimiter4)[1];
const endpoint = tss_client.lookupEndpoint(session, party);
fetch(`${endpoint}/send`, {
method: "POST",
headers: {
[WEB3_SESSION_HEADER_KEY]: sid,
"Content-Type": "application/json",
},
body: JSON.stringify({
session,
sender: self_index,
recipient: party,
msg_type,
msg_data,
}),
});
}
return true;
};
}

type Log = {
(msg: string): void;
};
Expand All @@ -113,7 +32,7 @@ export class Client {

public websocketOnly: boolean;

public tssLib: typeof TssLib;
public tssLib: WasmLib;

public _startPrecomputeTime: number;

Expand Down Expand Up @@ -154,7 +73,7 @@ export class Client {
_share: string,
_pubKey: string,
_websocketOnly: boolean,
_tssLib: typeof TssLib
_tssLib: WasmLib
) {
if (_parties.length !== _sockets.length) {
throw new Error("parties and sockets length must be equal, add null for client if necessary");
Expand Down Expand Up @@ -473,3 +392,84 @@ export class Client {
);
}
}

// TODO: create namespace for globals
if (globalThis.tss_clients === undefined) {
// Cleanup leads to memory leaks with just an object. Should use a map instead.
// TODO: This should be singular
globalThis.tss_clients = new Map();
}

if (globalThis.js_read_msg === undefined) {
globalThis.js_read_msg = async function (session: string, self_index: number, party: number, msg_type: string) {
const tss_client = globalThis.tss_clients.get(session) as Client;
tss_client.log(`reading msg, ${msg_type}`);
if (msg_type === "ga1_worker_support") {
return "unsupported";
}
const mm = tss_client.msgQueue.find((m) => m.sender === party && m.recipient === self_index && m.msg_type === msg_type);
if (!mm) {
// It is very important that this promise can reject, since it is passed through to dkls library and awaited internally. If it cannot reject and a message is lost,
// it will never resolve and hang indefinitely with no possibility of recovery.
return new Promise((resolve, reject) => {
let counter = 0;
const timer = setInterval(() => {
const found = tss_client.msgQueue.find((m) => m.sender === party && m.recipient === self_index && m.msg_type === msg_type);
if (found !== undefined) {
clearInterval(timer);
resolve(found.msg_data);
}
if (counter >= 1000) {
clearInterval(timer);
// TODO Fix wasm to handle error objects properly and then reject
// with Error instead of string.
//

reject("Message not received in a reasonable time");
}
counter++;
}, 10);
});
}
return mm.msg_data;
};
}

if (globalThis.js_send_msg === undefined) {
globalThis.js_send_msg = async function (session: string, self_index: number, party: number, msg_type: string, msg_data?: string) {
const tss_client = globalThis.tss_clients.get(session) as Client;
tss_client.log(`sending msg, ${msg_type}`);
if (msg_type.indexOf("ga1_data_unprocessed") > -1) {
throw new Error("ga1_data_unprocessed should not be sent directly");
}

if (tss_client.websocketOnly) {
const socket = tss_client.sockets[party];
socket.emit("send_msg", {
session,
sender: self_index,
recipient: party,
msg_type,
msg_data,
});
} else {
const sid = session.split(DELIMITERS.Delimiter4)[1];
const endpoint = tss_client.lookupEndpoint(session, party);
fetch(`${endpoint}/send`, {
method: "POST",
headers: {
[WEB3_SESSION_HEADER_KEY]: sid,
"Content-Type": "application/json",
},
body: JSON.stringify({
session,
sender: self_index,
recipient: party,
msg_type,
msg_data,
}),
});
}
return true;
};
}
matthiasgeihs marked this conversation as resolved.
Show resolved Hide resolved
1 change: 0 additions & 1 deletion packages/tss-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from "./client";
export * from "./constants";
export * from "./db";
export * from "./interfaces";
export * from "./utils";
10 changes: 0 additions & 10 deletions packages/tss-client/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ export interface Msg {
msg_data: string;
}

export interface TssWorker {
work: <T>(method: string, args: string[]) => Promise<T>;
}

export interface DB {
get: (key: string) => Promise<string>;
set: (key: string, value: string) => Promise<void>;
delete: (key: string) => Promise<void>;
}

export type PointHex = {
x: string;
y: string;
Expand Down
35 changes: 14 additions & 21 deletions packages/tss-client/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ export const getDKLSCoeff = (isUser: boolean, participatingServerIndexes: number
return coeff;
};

export const createSockets = async (wsEndpoints: string[], sessionId: string): Promise<Socket[]> => {
export const createSockets = async (wsEndpoints: string[], sessionId: string, socketPath = "/tss/socket.io"): Promise<Socket[]> => {
return wsEndpoints.map((wsEndpoint) => {
if (wsEndpoint === null || wsEndpoint === undefined) {
return null;
}
return io(wsEndpoint, {
path: "/tss/socket.io",
path: socketPath,
query: { sessionId },
transports: ["websocket", "polling"],
withCredentials: true,
Expand All @@ -112,10 +112,11 @@ export function getTSSPubKey(dkgPubKey: PointHex, userSharePubKey: key, userTSSI
return serverTerm.add(userTerm);
}

export const generateEndpoints = (parties: number, clientIndex: number, tssEndpoints: string[], wsEndpoints: string[], nodeIndexes: number[]) => {
const endpoints = [];
const tssWSEndpoints = [];
const partyIndexes = [];
export const generateEndpoints = (tssNodeEndpoints: string[], parties: number, clientIndex: number, nodeIndexes: number[]) => {
metalurgical marked this conversation as resolved.
Show resolved Hide resolved
const endpoints: (string | null)[] = [];
const tssWSEndpoints: (string | null)[] = [];
const partyIndexes: number[] = [];
const nodeIndexesReturned: number[] = [];

for (let i = 0; i < parties; i++) {
partyIndexes.push(i);
Expand All @@ -124,25 +125,17 @@ export const generateEndpoints = (parties: number, clientIndex: number, tssEndpo
endpoints.push(null);
tssWSEndpoints.push(null);
} else {
endpoints.push(tssEndpoints[nodeIndexes[i] ? nodeIndexes[i] - 1 : i]);
let wsEndpoint = wsEndpoints[nodeIndexes[i] ? nodeIndexes[i] - 1 : i];
if (wsEndpoint) {
const urlObject = new URL(wsEndpoint);
wsEndpoint = urlObject.origin;
}
tssWSEndpoints.push(wsEndpoint);
const targetNodeIndex = nodeIndexes[i] - 1;
endpoints.push(tssNodeEndpoints[targetNodeIndex]);
tssWSEndpoints.push(new URL(tssNodeEndpoints[targetNodeIndex]).origin);
nodeIndexesReturned.push(nodeIndexes[i]);
}
}

return {
endpoints,
tssWSEndpoints,
partyIndexes,
};
return { endpoints, tssWSEndpoints, partyIndexes, nodeIndexesReturned };
};

export const setupSockets = async (tssWSEndpoints: string[], sessionId: string) => {
const sockets = await createSockets(tssWSEndpoints, sessionId);
export const setupSockets = async (tssWSEndpoints: string[], sessionId: string, socketPath = "/tss/socket.io") => {
const sockets = await createSockets(tssWSEndpoints, sessionId, socketPath);
// wait for websockets to be connected
await new Promise((resolve) => {
const checkConnectionTimer = setInterval(() => {
Expand Down
Loading