From 977bd2b9ffdc54c317dcae64c81f4541fe68c630 Mon Sep 17 00:00:00 2001 From: himanshu Date: Mon, 13 May 2024 12:00:51 +0530 Subject: [PATCH 1/3] fetch nonce from metadata server if nodes doesnt return --- src/constants.ts | 2 ++ src/helpers/metadataUtils.ts | 11 +++++++++++ src/helpers/nodeUtils.ts | 25 ++++++++++++++++++++----- src/some.ts | 4 ++-- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 32e57c1..a570fe5 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -4,3 +4,5 @@ export const JRPC_METHODS = { IMPORT_SHARE: "ImportShare", GET_SHARE_OR_KEY_ASSIGN: "GetShareOrKeyAssign", }; + +export const SAPPHIRE_METADATA_URL = "https://node-1.node.web3auth.io/metadata"; diff --git a/src/helpers/metadataUtils.ts b/src/helpers/metadataUtils.ts index 9a9db05..fe1fd9d 100644 --- a/src/helpers/metadataUtils.ts +++ b/src/helpers/metadataUtils.ts @@ -5,6 +5,7 @@ import { ec } from "elliptic"; import stringify from "json-stable-stringify"; import log from "loglevel"; +import { SAPPHIRE_METADATA_URL } from "../constants"; import { EciesHex, GetOrSetNonceResult, MetadataParams } from "../interfaces"; import { encParamsHexToBuf } from "./common"; import { keccak256 } from "./keyUtils"; @@ -90,3 +91,13 @@ export async function getNonce( ): Promise { return getOrSetNonce(legacyMetadataHost, ecCurve, serverTimeOffset, X, Y, privKey, true); } + +export async function getSapphireMetadataNonce(X: string, Y: string): Promise { + const data = { + pub_key_X: X, + pub_key_Y: Y, + key_type: "secp256k1", + set_data: { operation: "get_nonce" }, + }; + return post(`${SAPPHIRE_METADATA_URL}/get_or_set_nonce`, data, undefined, { useAPIKey: true }); +} diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index 9f6e607..e7d1581 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -26,7 +26,7 @@ import { Some } from "../some"; import { calculateMedian, kCombinations, normalizeKeysResult, thresholdSame } from "./common"; import { generateAddressFromPrivKey, generateAddressFromPubKey, keccak256 } from "./keyUtils"; import { lagrangeInterpolation } from "./langrangeInterpolatePoly"; -import { decryptNodeData, getMetadata, getOrSetNonce } from "./metadataUtils"; +import { decryptNodeData, getMetadata, getOrSetNonce, getSapphireMetadataNonce } from "./metadataUtils"; export const GetPubKeyOrKeyAssign = async (params: { endpoints: string[]; @@ -56,7 +56,7 @@ export const GetPubKeyOrKeyAssign = async (params: { let nonceResult: GetOrSetNonceResult | undefined; const nodeIndexes: number[] = []; - const result = await Some, KeyLookupResult>(lookupPromises, (lookupResults) => { + const result = await Some, KeyLookupResult>(lookupPromises, async (lookupResults) => { const lookupPubKeys = lookupResults.filter((x1) => { if (x1 && !x1.error) { return x1; @@ -88,6 +88,15 @@ export const GetPubKeyOrKeyAssign = async (params: { } } } + + // if nonce result is not returned by nodes, fetch directly from metadata + if (!nonceResult) { + const metadataNonceResult = await getSapphireMetadataNonce(keyResult.keys[0].pub_key_X, keyResult.keys[0].pub_key_Y); + // rechecking nonceResult to avoid promise race condition. + if (!nonceResult && metadataNonceResult) { + nonceResult = metadataNonceResult; + } + } } const serverTimeOffsets: number[] = []; @@ -369,9 +378,15 @@ export async function retrieveOrImportShare(params: { // if both thresholdNonceData and extended_verifier_id are not available // then we need to throw other wise address would be incorrect. if (!thresholdNonceData && !verifierParams.extended_verifier_id && !LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]) { - throw new Error( - `invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}` - ); + const metadataNonceResult = await getSapphireMetadataNonce(thresholdPublicKey.X, thresholdPublicKey.Y); + // rechecking nonceResult to avoid promise race condition. + if (metadataNonceResult && !thresholdNonceData) { + thresholdNonceData = metadataNonceResult; + } else { + throw new Error( + `invalid metadata result from nodes, nonce metadata is empty for verifier: ${verifier} and verifierId: ${verifierParams.verifier_id}` + ); + } } const thresholdReqCount = importedShares.length > 0 ? endpoints.length : minThreshold; diff --git a/src/some.ts b/src/some.ts index ca72333..a9995c8 100644 --- a/src/some.ts +++ b/src/some.ts @@ -15,9 +15,9 @@ export class SomeError extends Error { // temp key should not be logged anywhere const message = `Unable to resolve enough promises. errors: ${errors.map((x) => x?.message || x).join(", ")}, + predicate error: ${predicate}, ${responses.length} responses, - responses: ${JSON.stringify(responses)}, - predicate error: ${predicate}`; + responses: ${JSON.stringify(responses)}`; super(message); this.errors = errors; this.responses = responses; From 87f5251ed24dcd995675074e8e5075252b35fe2c Mon Sep 17 00:00:00 2001 From: himanshu Date: Mon, 13 May 2024 12:09:24 +0530 Subject: [PATCH 2/3] fix metadata msg expiry test case --- test/testnet.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/testnet.test.ts b/test/testnet.test.ts index 719c67e..60f183c 100644 --- a/test/testnet.test.ts +++ b/test/testnet.test.ts @@ -258,7 +258,7 @@ describe("torus utils migrated testnet on sapphire", function () { network: TORUS_LEGACY_NETWORK.TESTNET, clientId: "YOUR_CLIENT_ID", enableOneKey: true, - serverTimeOffset: -100, + serverTimeOffset: -700, }); const { torusNodeSSSEndpoints: torusNodeEndpoints, torusIndexes } = await TORUS_NODE_MANAGER.getNodeDetails(verifierDetails); try { From 628bffb05e1efd42ef25651845b507831e2aec7c Mon Sep 17 00:00:00 2001 From: himanshu Date: Mon, 13 May 2024 12:45:56 +0530 Subject: [PATCH 3/3] get or set nonce, instead of just getting --- src/helpers/metadataUtils.ts | 4 ++-- src/helpers/nodeUtils.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/helpers/metadataUtils.ts b/src/helpers/metadataUtils.ts index fe1fd9d..efea217 100644 --- a/src/helpers/metadataUtils.ts +++ b/src/helpers/metadataUtils.ts @@ -92,12 +92,12 @@ export async function getNonce( return getOrSetNonce(legacyMetadataHost, ecCurve, serverTimeOffset, X, Y, privKey, true); } -export async function getSapphireMetadataNonce(X: string, Y: string): Promise { +export async function getOrSetSapphireMetadataNonce(X: string, Y: string): Promise { const data = { pub_key_X: X, pub_key_Y: Y, key_type: "secp256k1", - set_data: { operation: "get_nonce" }, + set_data: { operation: "getOrSetNonce" }, }; return post(`${SAPPHIRE_METADATA_URL}/get_or_set_nonce`, data, undefined, { useAPIKey: true }); } diff --git a/src/helpers/nodeUtils.ts b/src/helpers/nodeUtils.ts index e7d1581..32b8cf5 100644 --- a/src/helpers/nodeUtils.ts +++ b/src/helpers/nodeUtils.ts @@ -26,7 +26,7 @@ import { Some } from "../some"; import { calculateMedian, kCombinations, normalizeKeysResult, thresholdSame } from "./common"; import { generateAddressFromPrivKey, generateAddressFromPubKey, keccak256 } from "./keyUtils"; import { lagrangeInterpolation } from "./langrangeInterpolatePoly"; -import { decryptNodeData, getMetadata, getOrSetNonce, getSapphireMetadataNonce } from "./metadataUtils"; +import { decryptNodeData, getMetadata, getOrSetNonce, getOrSetSapphireMetadataNonce } from "./metadataUtils"; export const GetPubKeyOrKeyAssign = async (params: { endpoints: string[]; @@ -91,7 +91,7 @@ export const GetPubKeyOrKeyAssign = async (params: { // if nonce result is not returned by nodes, fetch directly from metadata if (!nonceResult) { - const metadataNonceResult = await getSapphireMetadataNonce(keyResult.keys[0].pub_key_X, keyResult.keys[0].pub_key_Y); + const metadataNonceResult = await getOrSetSapphireMetadataNonce(keyResult.keys[0].pub_key_X, keyResult.keys[0].pub_key_Y); // rechecking nonceResult to avoid promise race condition. if (!nonceResult && metadataNonceResult) { nonceResult = metadataNonceResult; @@ -378,7 +378,7 @@ export async function retrieveOrImportShare(params: { // if both thresholdNonceData and extended_verifier_id are not available // then we need to throw other wise address would be incorrect. if (!thresholdNonceData && !verifierParams.extended_verifier_id && !LEGACY_NETWORKS_ROUTE_MAP[network as TORUS_LEGACY_NETWORK_TYPE]) { - const metadataNonceResult = await getSapphireMetadataNonce(thresholdPublicKey.X, thresholdPublicKey.Y); + const metadataNonceResult = await getOrSetSapphireMetadataNonce(thresholdPublicKey.X, thresholdPublicKey.Y); // rechecking nonceResult to avoid promise race condition. if (metadataNonceResult && !thresholdNonceData) { thresholdNonceData = metadataNonceResult;