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

fix: update generate endpoints function #70

Merged
merged 9 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dist
pkg/dist
pkg/*.tgz
types/*
.vscode
.vscode
lerna-debug.log
8 changes: 0 additions & 8 deletions lerna-debug.log

This file was deleted.

18,124 changes: 8,783 additions & 9,341 deletions package-lock.json

Large diffs are not rendered by default.

37 changes: 19 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,29 +23,30 @@
"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",
"@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"
}
}
21 changes: 9 additions & 12 deletions packages/tss-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"files": [
"dist"
],
"main": "dist/tssClient.cjs.js",
"module": "dist/tssClient.esm.js",
"main": "dist/lib.cjs/index.js",
"module": "dist/lib.esm/index.js",
"unpkg": "dist/tssClient.umd.min.js",
"jsdelivr": "dist/tssClient.umd.min.js",
"types": "dist/types/index.d.ts",
Expand All @@ -20,20 +20,17 @@
"author": "Web3Auth",
"license": "ISC",
"dependencies": {
"@toruslabs/eccrypto": "^4.0.0",
"@types/chrome": "^0.0.268",
"@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": "^4.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",
"workerize-loader": "^2.0.2"
"@types/bn.js": "^5.1.6",
"@types/elliptic": "^6.4.18"
},
"publishConfig": {
"access": "public"
Expand Down
164 changes: 82 additions & 82 deletions packages/tss-client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,93 +3,12 @@ import { generatePrivate } from "@toruslabs/eccrypto";
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 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;
};
}
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
21 changes: 13 additions & 8 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,25 +112,30 @@ export function getTSSPubKey(dkgPubKey: PointHex, userSharePubKey: key, userTSSI
return serverTerm.add(userTerm);
}

export const generateEndpoints = (parties: number, clientIndex: number) => {
export const generateEndpoints = (tssNodeEndpoints: string[], parties: number, clientIndex: number, nodeIndexes: number[]) => {
const endpoints: (string | null)[] = [];
const tssWSEndpoints: (string | null)[] = [];
const partyIndexes: number[] = [];
const nodeIndexesReturned: number[] = [];

for (let i = 0; i < parties; i++) {
partyIndexes.push(i);

if (i === clientIndex) {
endpoints.push(null);
tssWSEndpoints.push(null);
} else {
endpoints.push(`https://sapphire-${i + 1}.auth.network/tss`);
tssWSEndpoints.push(`https://sapphire-${i + 1}.auth.network`);
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
2 changes: 1 addition & 1 deletion packages/tss-client/torus.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
...require("@toruslabs/config/torus.config"),
...require("@toruslabs/config/torus.config")
};
2 changes: 2 additions & 0 deletions packages/tss-lib/torus.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
module.exports = {
...require("@toruslabs/config/torus.config"),
esm: false,
libEsm: false,
libCjs: false,
};
2 changes: 1 addition & 1 deletion packages/tss-lib/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ const cfg = {

module.exports = {
umdConfig: cfg,
cjsConfig: cfg,
cjsConfig: cfg
};
10 changes: 0 additions & 10 deletions packages/web-example/.eslintrc.json

This file was deleted.

Loading