From f51355c6332e182077791d9b868a94491a25af6e Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Fri, 12 May 2023 11:47:01 +0530 Subject: [PATCH 1/6] fix: input share store unrelated share inputs --- packages/core/src/core.ts | 2 + packages/default/test/shared.js | 91 +++++++++++++++++++++++++-------- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 6517335f..fa84efb2 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -1216,6 +1216,8 @@ class ThresholdKey implements ITKey { } else { throw CoreError.default("can only add type ShareStore into shares"); } + ss = this.metadata.shareToShareStore(ss.share.share as BN); + const latestShareRes = await this.catchupToLatestShare({ shareStore: ss, includeLocalMetadataTransitions: true }); // if not in poly id list, metadata is probably outdated // is !this.metadata.polyIDList.includes(latestShareRes.latestShare.polynomialID) diff --git a/packages/default/test/shared.js b/packages/default/test/shared.js index 3859729b..4030ca97 100644 --- a/packages/default/test/shared.js +++ b/packages/default/test/shared.js @@ -105,7 +105,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: sp, storageLayer, manualSync: mode }); await tb2.initialize({ useTSS: true, factorPub }); - tb2.inputShareStore(newShare.newShareStores[newShare.newShareIndex.toString("hex")]); + await tb2.inputShareStoreSafe(newShare.newShareStores[newShare.newShareIndex.toString("hex")]); await tb2.reconstructKey(); const { tssShare: retrievedTSS, tssIndex: retrievedTSSIndex } = await tb2.getTSSShare(factorKey); const tssCommits = tb2.getTSSCommits(); @@ -739,7 +739,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize({ neverInitializeNewKey: true }); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -753,7 +753,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize(); - tb2.inputShareStore(resp1.userShare); + await tb2.inputShareStoreSafe(resp1.userShare); const reconstructedKey = await tb2.reconstructKey(); // compareBNArray(resp1.privKey, reconstructedKey, "key should be able to be reconstructed"); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { @@ -767,12 +767,30 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); if (importedKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); } }); + // it(`#should be able to guru test, manualSync=${mode}`, async function () { + // const importedKey = new BN(generatePrivate()); + // const resp1 = await tb._initializeNewKey({ importedKey, initializeModules: true }); + // await tb.syncLocalMetadataTransitions(); + + // const importedKey2 = new BN(generatePrivate()); + // const resp2 = await tb._initializeNewKey({ importedKey2, initializeModules: true }); + // await tb.syncLocalMetadataTransitions(); + + // const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + // await tb2.initialize(); + // await tb2.inputShareStoreSafe(resp1.deviceShare); + + // const reconstructedKey = await tb2.reconstructKey(); + // if (importedKey.cmp(reconstructedKey.privKey) !== 0) { + // fail("key should be able to be reconstructed"); + // } + // }); it(`#should be able to reconstruct key when initializing a with a share, manualSync=${mode}`, async function () { let userInput = new BN(keccak256("user answer blublu").slice(2), "hex"); userInput = userInput.umod(ecCurve.curve.n); @@ -781,7 +799,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize({ withShare: resp1.userShare }); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -796,7 +814,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize({ withShare: resp1.userShare }); - tb2.inputShareStore(newShares.newShareStores[newShares.newShareIndex.toString("hex")]); + await tb2.inputShareStoreSafe(newShares.newShareStores[newShares.newShareIndex.toString("hex")]); const reconstructedKey = await tb2.reconstructKey(); // compareBNArray(resp1.privKey, reconstructedKey, "key should be able to be reconstructed"); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { @@ -812,7 +830,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize(); - tb2.inputShareStore(newShares.newShareStores[newShares.newShareIndex.toString("hex")]); + await tb2.inputShareStoreSafe(newShares.newShareStores[newShares.newShareIndex.toString("hex")]); const reconstructedKey = await tb2.reconstructKey(); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -828,7 +846,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { await tb.generateNewShare(); // generate new share to update metadata await tb.syncLocalMetadataTransitions(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare, true); const reconstructedKey = await tb2.reconstructKey(); // reconstruct key with old metadata should work to poly if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -848,7 +866,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize({ neverInitializeNewKey: true }); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); const shareStore = tb2.outputShareStore(newShareIndex); strictEqual(newShareStores[newShareIndex.toString("hex")].share.share.toString("hex"), shareStore.share.share.toString("hex")); @@ -857,6 +875,40 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { fail("key should be able to be reconstructed"); } }); + it(`#should be able to output unavailable share store, manualSync=${mode}`, async function () { + const resp1 = await tb._initializeNewKey({ initializeModules: true }); + const { newShareStores: tbShareStore, newShareIndex: tbShareIndex } = await tb.generateNewShare(); + await tb.syncLocalMetadataTransitions(); + + const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + const resp2 = await tb2._initializeNewKey({ initializeModules: true }); + const { newShareStores, newShareIndex } = await tb2.generateNewShare(); + await tb2.syncLocalMetadataTransitions(); + + const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + + await tb3.initialize({ neverInitializeNewKey: true }); + try { + await tb3.inputShareStoreSafe(resp2.deviceShare, true); + await tb3.inputShareStoreSafe(newShareStores[newShareIndex.toString("hex")], true); + } catch (err) { + throw new Error(err); + } + await rejects(async () => { + await tb3.inputShareStoreSafe(tbShareStore[tbShareIndex.toString("hex")], true); + }, Error); + await rejects(async () => { + await tb3.inputShareStoreSafe(resp1.deviceShare, true); + }, Error); + + const reconstructedKey = await tb3.reconstructKey(); + const shareStore = tb3.outputShareStore(newShareIndex); + strictEqual(newShareStores[newShareIndex.toString("hex")].share.share.toString("hex"), shareStore.share.share.toString("hex")); + + if (resp2.privKey.cmp(reconstructedKey.privKey) !== 0) { + fail("key should be able to be reconstructed"); + } + }); it(`#should be able to update metadata, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); await tb.syncLocalMetadataTransitions(); @@ -864,7 +916,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); await tb2.reconstructKey(); // try creating new shares @@ -1066,7 +1118,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { await tb.syncLocalMetadataTransitions(); const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb3.initialize(); - tb3.inputShareStore(newShareStores[newShareIndex.toString("hex")]); + await tb3.inputShareStoreSafe(newShareStores[newShareIndex.toString("hex")]); const stringified = JSON.stringify(tb3); const tb4 = await ThresholdKey.fromJSON(JSON.parse(stringified), { serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); @@ -1085,7 +1137,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { customSL2.serviceProvider = customSP3; const tb2 = new ThresholdKey({ serviceProvider: customSP2, storageLayer: customSL2, manualSync: mode }); await tb2.initialize({ withShare: resp1.deviceShare }); - tb2.inputShareStore(newShareStores1[newShareIndex1.toString("hex")]); + await tb2.inputShareStoreSafe(newShareStores1[newShareIndex1.toString("hex")]); await tb2.reconstructKey(); const stringified = JSON.stringify(tb2); @@ -1335,6 +1387,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { }); it(`#should be able to transfer share via the module, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); + const result = await tb.generateNewShare(); await tb.syncLocalMetadataTransitions(); const tb2 = new ThresholdKey({ @@ -1348,8 +1401,6 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { // usually should be called in callback, but mocha does not allow const pubkey = await tb2.modules.shareTransfer.requestNewShare(); - const result = await tb.generateNewShare(); - await tb.modules.shareTransfer.approveRequest(pubkey, result.newShareStores[result.newShareIndex.toString("hex")]); await tb.syncLocalMetadataTransitions(); @@ -1544,7 +1595,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { modules: { seedPhrase: new SeedPhraseModule([metamaskSeedPhraseFormat2]) }, }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstuctedKey = await tb2.reconstructKey(); await tb.modules.seedPhrase.getSeedPhrasesWithAccounts(); @@ -1699,7 +1750,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { modules: { seedPhrase: new SeedPhraseModule([metamaskSeedPhraseFormat2]), privateKeyModule: new PrivateKeyModule([secp256k1Format]) }, }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); compareReconstructedKeys(reconstructedKey, { @@ -1737,7 +1788,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, manualSync: mode, storageLayer: customSL }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -1764,7 +1815,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb2 = new ThresholdKey({ serviceProvider: customSP, manualSync: mode, storageLayer: customSL }); await tb2.initialize(); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); const reconstructedKey = await tb2.reconstructKey(); if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); @@ -1774,7 +1825,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { for (let i = 0; i < 5; i += 1) { const temp = new ThresholdKey({ serviceProvider: customSP, manualSync: mode, storageLayer: customSL }); await temp.initialize(); - temp.inputShareStore(resp1.deviceShare); + await temp.inputShareStoreSafe(resp1.deviceShare); await temp.reconstructKey(); alltbs.push(temp); } @@ -1919,7 +1970,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { it(`#should throw error code 1103 if metadata post failed, in manualSync: ${mode}`, async function () { const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb2.initialize({ neverInitializeNewKey: true }); - tb2.inputShareStore(resp1.deviceShare); + await tb2.inputShareStoreSafe(resp1.deviceShare); await tb2.reconstructKey(); await tb2.syncLocalMetadataTransitions(); sandbox.stub(tb2.storageLayer, "setMetadataStream").throws(new Error("failed to set metadata")); From 3a7a61b965dbbf18d6683713b19f118415d142c8 Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Fri, 12 May 2023 13:26:11 +0530 Subject: [PATCH 2/6] fix: input share store unrelated share inputs --- packages/default/test/shared.js | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/packages/default/test/shared.js b/packages/default/test/shared.js index 4030ca97..70b56fa0 100644 --- a/packages/default/test/shared.js +++ b/packages/default/test/shared.js @@ -773,24 +773,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { fail("key should be able to be reconstructed"); } }); - // it(`#should be able to guru test, manualSync=${mode}`, async function () { - // const importedKey = new BN(generatePrivate()); - // const resp1 = await tb._initializeNewKey({ importedKey, initializeModules: true }); - // await tb.syncLocalMetadataTransitions(); - - // const importedKey2 = new BN(generatePrivate()); - // const resp2 = await tb._initializeNewKey({ importedKey2, initializeModules: true }); - // await tb.syncLocalMetadataTransitions(); - - // const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); - // await tb2.initialize(); - // await tb2.inputShareStoreSafe(resp1.deviceShare); - - // const reconstructedKey = await tb2.reconstructKey(); - // if (importedKey.cmp(reconstructedKey.privKey) !== 0) { - // fail("key should be able to be reconstructed"); - // } - // }); + it(`#should be able to reconstruct key when initializing a with a share, manualSync=${mode}`, async function () { let userInput = new BN(keccak256("user answer blublu").slice(2), "hex"); userInput = userInput.umod(ecCurve.curve.n); From b46426d19ca5fc620b5cb8bb1edeee3cc800e907 Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Thu, 18 May 2023 15:31:31 +0530 Subject: [PATCH 3/6] fix: test case name --- packages/default/test/shared.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/default/test/shared.js b/packages/default/test/shared.js index 70b56fa0..d7f50473 100644 --- a/packages/default/test/shared.js +++ b/packages/default/test/shared.js @@ -858,7 +858,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { fail("key should be able to be reconstructed"); } }); - it(`#should be able to output unavailable share store, manualSync=${mode}`, async function () { + it(`#shouldn't be able to insert shares from random threshold key, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); const { newShareStores: tbShareStore, newShareIndex: tbShareIndex } = await tb.generateNewShare(); await tb.syncLocalMetadataTransitions(); From 94f7c55aa5e666dd6a17421a8ba1ec23d9f4c214 Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Mon, 22 May 2023 09:31:39 +0530 Subject: [PATCH 4/6] fix: input share store negative test case --- packages/default/test/shared.js | 71 +++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 17 deletions(-) diff --git a/packages/default/test/shared.js b/packages/default/test/shared.js index d7f50473..3d00a3bc 100644 --- a/packages/default/test/shared.js +++ b/packages/default/test/shared.js @@ -858,40 +858,77 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { fail("key should be able to be reconstructed"); } }); - it(`#shouldn't be able to insert shares from random threshold key, manualSync=${mode}`, async function () { + it(`#should be able to insert shares from existing tkey using _initializeNewKey, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); const { newShareStores: tbShareStore, newShareIndex: tbShareIndex } = await tb.generateNewShare(); await tb.syncLocalMetadataTransitions(); - const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); - const resp2 = await tb2._initializeNewKey({ initializeModules: true }); - const { newShareStores, newShareIndex } = await tb2.generateNewShare(); - await tb2.syncLocalMetadataTransitions(); - const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb3.initialize({ neverInitializeNewKey: true }); try { - await tb3.inputShareStoreSafe(resp2.deviceShare, true); - await tb3.inputShareStoreSafe(newShareStores[newShareIndex.toString("hex")], true); + await tb3.inputShareStoreSafe(resp1.deviceShare, true); } catch (err) { throw new Error(err); } - await rejects(async () => { - await tb3.inputShareStoreSafe(tbShareStore[tbShareIndex.toString("hex")], true); - }, Error); - await rejects(async () => { - await tb3.inputShareStoreSafe(resp1.deviceShare, true); - }, Error); - const reconstructedKey = await tb3.reconstructKey(); - const shareStore = tb3.outputShareStore(newShareIndex); - strictEqual(newShareStores[newShareIndex.toString("hex")].share.share.toString("hex"), shareStore.share.share.toString("hex")); + if (resp1.privKey.cmp(reconstructedKey.privKey) !== 0) { + fail("key should be able to be reconstructed"); + } + const shareStore = tb3.outputShareStore(tbShareIndex); + strictEqual(tbShareStore[tbShareIndex.toString("hex")].share.share.toString("hex"), shareStore.share.share.toString("hex")); + }); + it(`#should be able to insert shares from existing tkey using new TKey Instance, manualSync=${mode}`, async function () { + const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + const resp2 = await tb2._initializeNewKey({ initializeModules: true }); + await tb2.syncLocalMetadataTransitions(); + + const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + + await tb3.initialize({ neverInitializeNewKey: true }); + await tb3.inputShareStoreSafe(resp2.deviceShare, true); + const reconstructedKey = await tb3.reconstructKey(); if (resp2.privKey.cmp(reconstructedKey.privKey) !== 0) { fail("key should be able to be reconstructed"); } }); + it(`#shouldn't be able to insert shares from random threshold key, manualSync=${mode}`, async function () { + // wrong tkey instance + const resp1 = await tb._initializeNewKey({ initializeModules: true }); + const { newShareStores: tbShareStore, newShareIndex: tbShareIndex } = await tb.generateNewShare(); + await tb.syncLocalMetadataTransitions(); + + // tkey instance with correct share stores and index + const tb2 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + const resp2 = await tb2._initializeNewKey({ initializeModules: true }); + await tb2.syncLocalMetadataTransitions(); + + const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); + await tb3.initialize({ neverInitializeNewKey: true }); + + // throws since share doesn't + await rejects( + async () => { + await tb3.inputShareStoreSafe(tbShareStore[tbShareIndex.toString("hex")], true); + }, + (err) => { + strictEqual(err.code, 1307, "CoreError: Share doesn't exist"); + return true; + } + ); + await rejects( + async () => { + await tb3.inputShareStoreSafe(resp1.deviceShare, true); + }, + (err) => { + strictEqual(err.code, 1307, "CoreError: Share doesn't exist"); + return true; + } + ); + // should be able to insert if correct share store and index + await tb3.inputShareStoreSafe(resp2.deviceShare, true); + }); it(`#should be able to update metadata, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); await tb.syncLocalMetadataTransitions(); From be2ee51aa1f2e4650cdc8fa3507a42c341d6b690 Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Wed, 31 May 2023 09:23:20 +0530 Subject: [PATCH 5/6] fix: input share store fix v2 --- packages/core/src/core.ts | 32 +++++++++++++++++++++++++++++++- packages/core/src/util.ts | 10 ++++++++++ packages/default/test/shared.js | 11 +++++++++++ 3 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 packages/core/src/util.ts diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index fa84efb2..291661a0 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -66,6 +66,7 @@ import { lagrangeInterpolation, } from "./lagrangeInterpolatePolynomial"; import Metadata from "./metadata"; +import { eqSet, isSome } from "./util"; // TODO: handle errors for get and set with retries @@ -1216,7 +1217,36 @@ class ThresholdKey implements ITKey { } else { throw CoreError.default("can only add type ShareStore into shares"); } - ss = this.metadata.shareToShareStore(ss.share.share as BN); + + // get current metadata poly id + const existingPolyShares = this.metadata.polyIDList; + const existingPolyIDs = []; + existingPolyShares.map((polyList) => existingPolyIDs.push(polyList[0])); + + // get input metadata's poly id + const newShareMetadata = await this.storageLayer.getMetadata({ privKey: ss.share.share as BN }); + const parseNewMeta = Metadata.fromJSON(JSON.parse(stringify((newShareMetadata as any).data))) as Metadata; + const newPolyIDs = []; + const newShareIndexes = new Set(); + parseNewMeta.polyIDList.map((polyList) => { + newPolyIDs.push(polyList[0]); + return polyList[1].forEach((item) => newShareIndexes.add(item)); + }); + + // check if poly id list is outdated + if (existingPolyIDs.length !== newPolyIDs.length && isSome(existingPolyIDs, newPolyIDs)) { + // catchup to latest tKey + await this.updateSDK(); + } else { + const existingShareIndexes = new Set(); + this.metadata.polyIDList.map((polyList) => polyList[1].forEach((item) => existingShareIndexes.add(item))); + + // make sure share indexes of input share's metadata and existing are same + if (!eqSet(newShareIndexes, existingShareIndexes)) { + // throw error if share index is random + throw CoreError.fromCode(1307); + } + } const latestShareRes = await this.catchupToLatestShare({ shareStore: ss, includeLocalMetadataTransitions: true }); // if not in poly id list, metadata is probably outdated diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts new file mode 100644 index 00000000..33f5c990 --- /dev/null +++ b/packages/core/src/util.ts @@ -0,0 +1,10 @@ +// compare two arrays of string without order +export function isSome(array1: string[], array2: string[]) { + return array1.some(function (element, index) { + return element === array2[index]; + }); +} + +export function eqSet(xs: Set, ys: Set) { + return xs.size === ys.size && [...xs].every((x) => ys.has(x)); +} diff --git a/packages/default/test/shared.js b/packages/default/test/shared.js index 3d00a3bc..ac7d53aa 100644 --- a/packages/default/test/shared.js +++ b/packages/default/test/shared.js @@ -906,6 +906,7 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { const tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode }); await tb3.initialize({ neverInitializeNewKey: true }); + await tb3.syncLocalMetadataTransitions(); // throws since share doesn't await rejects( @@ -928,6 +929,16 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => { ); // should be able to insert if correct share store and index await tb3.inputShareStoreSafe(resp2.deviceShare, true); + await tb3.reconstructKey(); + const { newShareStores: tb3ShareStore, newShareIndex: tb3ShareIndex } = await tb3.generateNewShare(); + await tb3.syncLocalMetadataTransitions(); + await tb3.reconstructKey(); + + await tb2.inputShareStoreSafe(tb3ShareStore[tb3ShareIndex.toString("hex")], true); + const reconstructedKey2 = await tb2.reconstructKey(); + if (resp2.privKey.cmp(reconstructedKey2.privKey) !== 0) { + fail("key should be able to be reconstructed"); + } }); it(`#should be able to update metadata, manualSync=${mode}`, async function () { const resp1 = await tb._initializeNewKey({ initializeModules: true }); From 17ecfdc73c8c9687c89374185bb18bcd87f06291 Mon Sep 17 00:00:00 2001 From: guru-web3 <105355858+guru-web3@users.noreply.github.com> Date: Wed, 31 May 2023 13:07:36 +0530 Subject: [PATCH 6/6] fix: catchuptolateststore v2 --- packages/core/src/core.ts | 59 ++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts index 291661a0..90c9fcb2 100644 --- a/packages/core/src/core.ts +++ b/packages/core/src/core.ts @@ -1219,36 +1219,39 @@ class ThresholdKey implements ITKey { } // get current metadata poly id - const existingPolyShares = this.metadata.polyIDList; - const existingPolyIDs = []; - existingPolyShares.map((polyList) => existingPolyIDs.push(polyList[0])); - - // get input metadata's poly id - const newShareMetadata = await this.storageLayer.getMetadata({ privKey: ss.share.share as BN }); - const parseNewMeta = Metadata.fromJSON(JSON.parse(stringify((newShareMetadata as any).data))) as Metadata; - const newPolyIDs = []; - const newShareIndexes = new Set(); - parseNewMeta.polyIDList.map((polyList) => { - newPolyIDs.push(polyList[0]); - return polyList[1].forEach((item) => newShareIndexes.add(item)); - }); - - // check if poly id list is outdated - if (existingPolyIDs.length !== newPolyIDs.length && isSome(existingPolyIDs, newPolyIDs)) { - // catchup to latest tKey - await this.updateSDK(); - } else { - const existingShareIndexes = new Set(); - this.metadata.polyIDList.map((polyList) => polyList[1].forEach((item) => existingShareIndexes.add(item))); - - // make sure share indexes of input share's metadata and existing are same - if (!eqSet(newShareIndexes, existingShareIndexes)) { - // throw error if share index is random - throw CoreError.fromCode(1307); - } - } + // const existingPolyShares = this.metadata.polyIDList; + // const existingPolyIDs = []; + // existingPolyShares.map((polyList) => existingPolyIDs.push(polyList[0])); + + // // get input metadata's poly id + // const newShareMetadata = await this.storageLayer.getMetadata({ privKey: ss.share.share as BN }); + // const parseNewMeta = Metadata.fromJSON(JSON.parse(stringify((newShareMetadata as any).data))) as Metadata; + // const newPolyIDs = []; + // const newShareIndexes = new Set(); + // parseNewMeta.polyIDList.map((polyList) => { + // newPolyIDs.push(polyList[0]); + // return polyList[1].forEach((item) => newShareIndexes.add(item)); + // }); + + // // check if poly id list is outdated + // if (existingPolyIDs.length !== newPolyIDs.length && isSome(existingPolyIDs, newPolyIDs)) { + // // catchup to latest tKey + // await this.updateSDK(); + // } else { + // const existingShareIndexes = new Set(); + // this.metadata.polyIDList.map((polyList) => polyList[1].forEach((item) => existingShareIndexes.add(item))); + + // // make sure share indexes of input share's metadata and existing are same + // if (!eqSet(newShareIndexes, existingShareIndexes)) { + // // throw error if share index is random + // throw CoreError.fromCode(1307); + // } + // } const latestShareRes = await this.catchupToLatestShare({ shareStore: ss, includeLocalMetadataTransitions: true }); + if (!latestShareRes.shareMetadata.polyIDList.find((tuple) => tuple[0] === this.metadata.getLatestPublicPolynomial().getPolynomialID())) { + throw CoreError.fromCode(1307); + } // if not in poly id list, metadata is probably outdated // is !this.metadata.polyIDList.includes(latestShareRes.latestShare.polynomialID) if (!this.metadata.polyIDList.find((tuple) => tuple[0] === latestShareRes.latestShare.polynomialID)) {