Skip to content
Draft
Show file tree
Hide file tree
Changes from 4 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
2 changes: 2 additions & 0 deletions packages/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would we have simpler check if we check for existence of the input shareStore's polyID in the polyIDList ?
@metallicalfa2

also, should we add check for the inputShareStore that the polyID should be the latest polyID?

Copy link
Contributor

@ieow ieow May 22, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the shareToShareStore won't fix the issue properly.
we should check the if latest share's metadata polynomial has the current tkey latest polynomial.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible scenario,

create 2 tkey instance, InstA, InstB
InstB generate new share E,
input share E to tkey InstA.
shareToShareStore would failed as share E is not expected in InstA metadata


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)
Expand Down
111 changes: 91 additions & 20 deletions packages/default/test/shared.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand All @@ -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) {
Expand All @@ -767,12 +767,13 @@ 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 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);
Expand All @@ -781,7 +782,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");
Expand All @@ -796,7 +797,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) {
Expand All @@ -812,7 +813,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");
Expand All @@ -828,7 +829,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");
Expand All @@ -848,7 +849,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"));
Expand All @@ -857,14 +858,85 @@ export const sharedTestCases = (mode, torusSP, storageLayer) => {
fail("key should be able to be reconstructed");
}
});
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 tb3 = new ThresholdKey({ serviceProvider: customSP, storageLayer: customSL, manualSync: mode });

await tb3.initialize({ neverInitializeNewKey: true });
try {
await tb3.inputShareStoreSafe(resp1.deviceShare, true);
} catch (err) {
throw new Error(err);
}
const reconstructedKey = await tb3.reconstructKey();

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();
// nonce 0

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
Expand Down Expand Up @@ -1066,7 +1138,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 });
Expand All @@ -1085,7 +1157,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);

Expand Down Expand Up @@ -1335,6 +1407,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({
Expand All @@ -1348,8 +1421,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();

Expand Down Expand Up @@ -1544,7 +1615,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();

Expand Down Expand Up @@ -1699,7 +1770,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, {
Expand Down Expand Up @@ -1737,7 +1808,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");
Expand All @@ -1764,7 +1835,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");
Expand All @@ -1774,7 +1845,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);
}
Expand Down Expand Up @@ -1919,7 +1990,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"));
Expand Down