From 561b801afb20d711a309a10745bc815626eaa8e7 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 25 Feb 2025 15:19:30 +0800 Subject: [PATCH 1/4] refactor: validates key type and sig type for TSS Endpoints --- packages/fnd-base/src/endpoints.ts | 44 ++++++++++-------------------- packages/fnd-base/src/utils.ts | 20 ++++++++++++++ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/packages/fnd-base/src/endpoints.ts b/packages/fnd-base/src/endpoints.ts index cf968b0..45c8bdc 100644 --- a/packages/fnd-base/src/endpoints.ts +++ b/packages/fnd-base/src/endpoints.ts @@ -9,6 +9,8 @@ import { WEB3AUTH_SIG_TYPE, } from "@toruslabs/constants"; +import { validateKeyTypeAndSigTypeForTSS } from "./utils"; + export const SAPPHIRE_NETWORK_URLS: Record = { [TORUS_SAPPHIRE_NETWORK.SAPPHIRE_DEVNET]: [ "https://node-1.dev-node.web3auth.io", @@ -59,41 +61,25 @@ export const getTSSEndpoints = ( sapphireNetwork: TORUS_SAPPHIRE_NETWORK_TYPE, legacyNetwork?: TORUS_LEGACY_NETWORK_TYPE, keyType = KEY_TYPE.SECP256K1 as WEB3AUTH_KEY_TYPE, - sigType?: WEB3AUTH_SIG_TYPE + sigType = SIG_TYPE.ECDSA_SECP256K1 as WEB3AUTH_SIG_TYPE ) => { const endpoints = SAPPHIRE_NETWORK_URLS[sapphireNetwork]; if (!endpoints || endpoints.length === 0) { throw new Error(`Unsupported network: ${sapphireNetwork}`); } - const tssPath = (() => { - const dklsPath = "tss"; - const frostPath = "tss-frost"; - if (sigType) { - if (sigType === SIG_TYPE.ECDSA_SECP256K1) { - if (keyType !== KEY_TYPE.SECP256K1) { - throw new Error("Invalid key type for ecdsa-secp256k1"); - } - return dklsPath; - } else if (sigType === SIG_TYPE.ED25519) { - if (keyType !== KEY_TYPE.ED25519) { - throw new Error("Invalid key type for ed25519"); - } - return frostPath; - } else if (sigType === SIG_TYPE.BIP340) { - if (keyType !== KEY_TYPE.SECP256K1) { - throw new Error("Invalid key type for bip340"); - } - return frostPath; - } - throw new Error("Invalid sig type"); - } else if (keyType === KEY_TYPE.SECP256K1) { - return dklsPath; - } else if (keyType === KEY_TYPE.ED25519) { - return frostPath; - } - throw new Error("Invalid key type"); - })(); + validateKeyTypeAndSigTypeForTSS(keyType, sigType); + + let tssPath: "tss" | "tss-frost"; + if (sigType === SIG_TYPE.ECDSA_SECP256K1) { + // we will use dkls for ECDSA Sigs + tssPath = "tss"; + } else if (sigType === SIG_TYPE.ED25519 || sigType === SIG_TYPE.BIP340) { + // we will use frost for Ed25519 and BIP340 Sigs + tssPath = "tss-frost"; + } else { + throw new Error(`Unsupported signature type: ${sigType}`); + } const routeIdentifier = LEGACY_NETWORKS_ROUTE_MAP[legacyNetwork as TORUS_LEGACY_NETWORK_TYPE]; return endpoints.map((e) => { diff --git a/packages/fnd-base/src/utils.ts b/packages/fnd-base/src/utils.ts index a72b729..508850b 100644 --- a/packages/fnd-base/src/utils.ts +++ b/packages/fnd-base/src/utils.ts @@ -1,6 +1,8 @@ import { INodeDetails, + KEY_TYPE, LEGACY_NETWORKS_ROUTE_MAP, + SIG_TYPE, TORUS_LEGACY_NETWORK, TORUS_LEGACY_NETWORK_TYPE, TORUS_NETWORK_TYPE, @@ -12,6 +14,24 @@ import { import { getSapphireNodeDetails } from "./sapphireNetworkConfig"; +export function validateKeyTypeAndSigTypeForTSS(keyType: WEB3AUTH_KEY_TYPE, sigType: WEB3AUTH_SIG_TYPE) { + if (sigType === SIG_TYPE.ECDSA_SECP256K1) { + if (keyType !== KEY_TYPE.SECP256K1) { + throw new Error("Invalid key type for ecdsa-secp256k1"); + } + } else if (sigType === SIG_TYPE.BIP340) { + if (keyType !== KEY_TYPE.SECP256K1) { + throw new Error("Invalid key type for bip340"); + } + } else if (sigType === SIG_TYPE.ED25519) { + if (keyType !== KEY_TYPE.ED25519) { + throw new Error("Invalid key type for ed25519"); + } + } else { + throw new Error(`Invalid signature type, ${sigType}`); + } +} + export function fetchLocalConfig(network: TORUS_NETWORK_TYPE, keyType: WEB3AUTH_KEY_TYPE, sigType?: WEB3AUTH_SIG_TYPE): INodeDetails | undefined { if (Object.values(TORUS_SAPPHIRE_NETWORK).includes(network as TORUS_SAPPHIRE_NETWORK_TYPE)) { return getSapphireNodeDetails(network as TORUS_SAPPHIRE_NETWORK_TYPE, undefined, keyType, sigType); From 17628c1dc52f020303668f7ad5b66a3b372e5006 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 25 Feb 2025 16:58:12 +0800 Subject: [PATCH 2/4] validate sig and key type before making request to fetch TSS node endpoints --- packages/fetch-node-details/src/nodeDetailManager.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/fetch-node-details/src/nodeDetailManager.ts b/packages/fetch-node-details/src/nodeDetailManager.ts index d8bc954..6d66bec 100644 --- a/packages/fetch-node-details/src/nodeDetailManager.ts +++ b/packages/fetch-node-details/src/nodeDetailManager.ts @@ -13,7 +13,7 @@ import { WEB3AUTH_KEY_TYPE, WEB3AUTH_SIG_TYPE, } from "@toruslabs/constants"; -import { fetchLocalConfig } from "@toruslabs/fnd-base"; +import { fetchLocalConfig, validateKeyTypeAndSigTypeForTSS } from "@toruslabs/fnd-base"; import { get } from "@toruslabs/http-helpers"; import logger from "loglevel"; @@ -100,6 +100,9 @@ class NodeDetailManager { const finalKeyType = keyType ?? this._keyType; const finalSigType = sigType ?? this._sigType; + // validate key type and sig type to fetch TSS endpoints + validateKeyTypeAndSigTypeForTSS(finalKeyType, finalSigType); + try { const { nodeDetails } = await get<{ nodeDetails: INodeDetails }>( `${this.fndServerEndpoint}?network=${this.network}&verifier=${verifier}&verifierId=${verifierId}&keyType=${finalKeyType}&sigType=${finalSigType}` From d81f81664319a5d9199fed47fd3d95911af25b08 Mon Sep 17 00:00:00 2001 From: lwin Date: Tue, 25 Feb 2025 17:40:55 +0800 Subject: [PATCH 3/4] updated test to include validation failure case --- .../test/nodeDetail.test.ts | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/packages/fetch-node-details/test/nodeDetail.test.ts b/packages/fetch-node-details/test/nodeDetail.test.ts index 481c017..5d367af 100644 --- a/packages/fetch-node-details/test/nodeDetail.test.ts +++ b/packages/fetch-node-details/test/nodeDetail.test.ts @@ -1,6 +1,6 @@ -import { METADATA_MAP, TORUS_LEGACY_NETWORK, TORUS_NETWORK_TYPE, TORUS_SAPPHIRE_NETWORK } from "@toruslabs/constants"; +import { METADATA_MAP, SIG_TYPE, TORUS_LEGACY_NETWORK, TORUS_NETWORK_TYPE, TORUS_SAPPHIRE_NETWORK } from "@toruslabs/constants"; import { getSapphireNodeDetails } from "@toruslabs/fnd-base"; -import { deepStrictEqual, strictEqual, throws } from "assert"; +import { deepStrictEqual, rejects, strictEqual, throws } from "assert"; import NodeDetailManager from "../src/nodeDetailManager"; @@ -115,6 +115,27 @@ describe("Fetch Node Details", function () { ); }); + it("#should throw error for invalid key type and sig type", async function () { + const nodeDetailManager = new NodeDetailManager({ + network: TORUS_SAPPHIRE_NETWORK.SAPPHIRE_MAINNET, + fndServerEndpoint, + enableLogging: true, + }); + + const sigType = SIG_TYPE.ED25519; + + await rejects( + async () => { + await nodeDetailManager.getNodeDetails({ verifier: "google", verifierId: "hello@tor.us", keyType: "secp256k1", sigType }); + }, + (err) => { + const error = err as Error; + strictEqual(error.message, `Invalid key type for ${sigType}`); + return true; + } + ); + }); + it("#should use default network if not provided", async function () { const nodeDetailManager = new NodeDetailManager({ fndServerEndpoint, From a29b7861bdf03de56882773132d73ec71bbf3728 Mon Sep 17 00:00:00 2001 From: lwin Date: Wed, 26 Feb 2025 01:01:18 +0800 Subject: [PATCH 4/4] refactor: sigAndKeyType validation and getTssPath --- packages/fnd-base/src/endpoints.ts | 19 +++--------- packages/fnd-base/src/index.ts | 27 +++++++++++++++++ packages/fnd-base/src/utils.ts | 48 +++++++++++++----------------- 3 files changed, 52 insertions(+), 42 deletions(-) diff --git a/packages/fnd-base/src/endpoints.ts b/packages/fnd-base/src/endpoints.ts index 45c8bdc..26a282e 100644 --- a/packages/fnd-base/src/endpoints.ts +++ b/packages/fnd-base/src/endpoints.ts @@ -1,7 +1,6 @@ import { KEY_TYPE, LEGACY_NETWORKS_ROUTE_MAP, - SIG_TYPE, TORUS_LEGACY_NETWORK_TYPE, TORUS_SAPPHIRE_NETWORK, TORUS_SAPPHIRE_NETWORK_TYPE, @@ -9,7 +8,7 @@ import { WEB3AUTH_SIG_TYPE, } from "@toruslabs/constants"; -import { validateKeyTypeAndSigTypeForTSS } from "./utils"; +import { validateSigTypeAndGetTSSPath } from "./utils"; export const SAPPHIRE_NETWORK_URLS: Record = { [TORUS_SAPPHIRE_NETWORK.SAPPHIRE_DEVNET]: [ @@ -61,25 +60,15 @@ export const getTSSEndpoints = ( sapphireNetwork: TORUS_SAPPHIRE_NETWORK_TYPE, legacyNetwork?: TORUS_LEGACY_NETWORK_TYPE, keyType = KEY_TYPE.SECP256K1 as WEB3AUTH_KEY_TYPE, - sigType = SIG_TYPE.ECDSA_SECP256K1 as WEB3AUTH_SIG_TYPE + sigType?: WEB3AUTH_SIG_TYPE ) => { const endpoints = SAPPHIRE_NETWORK_URLS[sapphireNetwork]; if (!endpoints || endpoints.length === 0) { throw new Error(`Unsupported network: ${sapphireNetwork}`); } - validateKeyTypeAndSigTypeForTSS(keyType, sigType); - - let tssPath: "tss" | "tss-frost"; - if (sigType === SIG_TYPE.ECDSA_SECP256K1) { - // we will use dkls for ECDSA Sigs - tssPath = "tss"; - } else if (sigType === SIG_TYPE.ED25519 || sigType === SIG_TYPE.BIP340) { - // we will use frost for Ed25519 and BIP340 Sigs - tssPath = "tss-frost"; - } else { - throw new Error(`Unsupported signature type: ${sigType}`); - } + // validate the keyType and sigType and get the relevant tssPath + const tssPath = validateSigTypeAndGetTSSPath(keyType, sigType); const routeIdentifier = LEGACY_NETWORKS_ROUTE_MAP[legacyNetwork as TORUS_LEGACY_NETWORK_TYPE]; return endpoints.map((e) => { diff --git a/packages/fnd-base/src/index.ts b/packages/fnd-base/src/index.ts index eb29e0f..65c5a3f 100644 --- a/packages/fnd-base/src/index.ts +++ b/packages/fnd-base/src/index.ts @@ -1,3 +1,30 @@ +import { + INodeDetails, + LEGACY_NETWORKS_ROUTE_MAP, + TORUS_LEGACY_NETWORK, + TORUS_LEGACY_NETWORK_TYPE, + TORUS_NETWORK_TYPE, + TORUS_SAPPHIRE_NETWORK, + TORUS_SAPPHIRE_NETWORK_TYPE, + WEB3AUTH_KEY_TYPE, + WEB3AUTH_SIG_TYPE, +} from "@toruslabs/constants"; + +import { getSapphireNodeDetails } from "./sapphireNetworkConfig"; + export * from "./endpoints"; export * from "./sapphireNetworkConfig"; export * from "./utils"; + +export function fetchLocalConfig(network: TORUS_NETWORK_TYPE, keyType: WEB3AUTH_KEY_TYPE, sigType?: WEB3AUTH_SIG_TYPE): INodeDetails | undefined { + if (Object.values(TORUS_SAPPHIRE_NETWORK).includes(network as TORUS_SAPPHIRE_NETWORK_TYPE)) { + return getSapphireNodeDetails(network as TORUS_SAPPHIRE_NETWORK_TYPE, undefined, keyType, sigType); + } + + if (Object.values(TORUS_LEGACY_NETWORK).includes(network as TORUS_LEGACY_NETWORK_TYPE)) { + const legacyMap = LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]; + if (legacyMap.migrationCompleted) return getSapphireNodeDetails(legacyMap.networkMigratedTo, network as TORUS_LEGACY_NETWORK_TYPE, keyType); + } + + return undefined; +} diff --git a/packages/fnd-base/src/utils.ts b/packages/fnd-base/src/utils.ts index 508850b..379f09d 100644 --- a/packages/fnd-base/src/utils.ts +++ b/packages/fnd-base/src/utils.ts @@ -1,20 +1,6 @@ -import { - INodeDetails, - KEY_TYPE, - LEGACY_NETWORKS_ROUTE_MAP, - SIG_TYPE, - TORUS_LEGACY_NETWORK, - TORUS_LEGACY_NETWORK_TYPE, - TORUS_NETWORK_TYPE, - TORUS_SAPPHIRE_NETWORK, - TORUS_SAPPHIRE_NETWORK_TYPE, - WEB3AUTH_KEY_TYPE, - WEB3AUTH_SIG_TYPE, -} from "@toruslabs/constants"; +import { KEY_TYPE, SIG_TYPE, WEB3AUTH_KEY_TYPE, WEB3AUTH_SIG_TYPE } from "@toruslabs/constants"; -import { getSapphireNodeDetails } from "./sapphireNetworkConfig"; - -export function validateKeyTypeAndSigTypeForTSS(keyType: WEB3AUTH_KEY_TYPE, sigType: WEB3AUTH_SIG_TYPE) { +export function validateKeyTypeAndSigTypeForTSS(keyType: WEB3AUTH_KEY_TYPE, sigType?: WEB3AUTH_SIG_TYPE) { if (sigType === SIG_TYPE.ECDSA_SECP256K1) { if (keyType !== KEY_TYPE.SECP256K1) { throw new Error("Invalid key type for ecdsa-secp256k1"); @@ -27,20 +13,28 @@ export function validateKeyTypeAndSigTypeForTSS(keyType: WEB3AUTH_KEY_TYPE, sigT if (keyType !== KEY_TYPE.ED25519) { throw new Error("Invalid key type for ed25519"); } - } else { - throw new Error(`Invalid signature type, ${sigType}`); } } -export function fetchLocalConfig(network: TORUS_NETWORK_TYPE, keyType: WEB3AUTH_KEY_TYPE, sigType?: WEB3AUTH_SIG_TYPE): INodeDetails | undefined { - if (Object.values(TORUS_SAPPHIRE_NETWORK).includes(network as TORUS_SAPPHIRE_NETWORK_TYPE)) { - return getSapphireNodeDetails(network as TORUS_SAPPHIRE_NETWORK_TYPE, undefined, keyType, sigType); - } +export function validateSigTypeAndGetTSSPath(keyType: WEB3AUTH_KEY_TYPE, sigType?: WEB3AUTH_SIG_TYPE): "tss" | "tss-frost" { + validateKeyTypeAndSigTypeForTSS(keyType, sigType); - if (Object.values(TORUS_LEGACY_NETWORK).includes(network as TORUS_LEGACY_NETWORK_TYPE)) { - const legacyMap = LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]; - if (legacyMap.migrationCompleted) return getSapphireNodeDetails(legacyMap.networkMigratedTo, network as TORUS_LEGACY_NETWORK_TYPE, keyType); + let tssPath: "tss" | "tss-frost"; + if (!sigType) { + // if sigType is not provided, we will determine the tssPath based on the keyType + if (keyType === KEY_TYPE.SECP256K1) { + tssPath = "tss"; + } else if (keyType === KEY_TYPE.ED25519) { + tssPath = "tss-frost"; + } + } else if (sigType === SIG_TYPE.ECDSA_SECP256K1) { + // we will use dkls for ECDSA Sigs + tssPath = "tss"; + } else if (sigType === SIG_TYPE.ED25519 || sigType === SIG_TYPE.BIP340) { + // we will use frost for Ed25519 and BIP340 Sigs + tssPath = "tss-frost"; + } else { + throw new Error(`Unsupported signature type: ${sigType} for key: ${keyType}`); } - - return undefined; + return tssPath; }