From 2d1aa90d014fd4936340739432a175a98110344e Mon Sep 17 00:00:00 2001 From: Piotr Roslaniec Date: Tue, 11 Jul 2023 15:37:48 +0200 Subject: [PATCH] add feedback from live testing --- src/agents/coordinator.ts | 2 +- src/dkg.ts | 6 +++--- src/policies/policy.ts | 5 +++++ src/sdk/cohort.ts | 9 +++++++++ src/sdk/strategy/cbd-strategy.ts | 19 ++++++++++++++----- test/acceptance/alice-grants.test.ts | 2 +- test/acceptance/delay-enact.test.ts | 2 +- test/docs/cbd.test.ts | 4 ++-- test/integration/pre.test.ts | 2 +- test/unit/cbd-strategy.test.ts | 8 ++++++-- test/unit/cohort.test.ts | 2 +- test/unit/pre-strategy.test.ts | 2 +- test/utils.ts | 17 ++++++++++++----- 13 files changed, 57 insertions(+), 23 deletions(-) diff --git a/src/agents/coordinator.ts b/src/agents/coordinator.ts index ccab3cf26..ca1e41f17 100644 --- a/src/agents/coordinator.ts +++ b/src/agents/coordinator.ts @@ -69,7 +69,7 @@ export class DkgCoordinatorAgent { if (!ritualStartEvent) { throw new Error('Ritual start event not found'); } - return ritualStartEvent.args?.ritualId.toNumber(); + return ritualStartEvent.args?.ritualId; } public static async getRitual( diff --git a/src/dkg.ts b/src/dkg.ts index 5de7ee4cd..ac30ac39a 100644 --- a/src/dkg.ts +++ b/src/dkg.ts @@ -115,10 +115,10 @@ export class DkgClient { web3Provider: ethers.providers.Web3Provider, ursulas: ChecksumAddress[], waitUntilEnd = false - ): Promise { + ): Promise { const ritualId = await DkgCoordinatorAgent.initializeRitual( web3Provider, - ursulas + ursulas.sort() ); if (waitUntilEnd) { @@ -137,7 +137,7 @@ export class DkgClient { } } - return this.getExistingRitual(web3Provider, ritualId); + return ritualId; } private static waitUntilRitualEnd = async ( diff --git a/src/policies/policy.ts b/src/policies/policy.ts index 1ccca6a90..b17d6b81f 100644 --- a/src/policies/policy.ts +++ b/src/policies/policy.ts @@ -118,6 +118,11 @@ export class BlockchainPolicy { public async generatePreEnactedPolicy( ursulas: readonly Ursula[] ): Promise { + if (ursulas.length != this.verifiedKFrags.length) { + throw new Error( + `Number of ursulas must match number of verified kFrags: ${this.verifiedKFrags.length}` + ); + } const treasureMap = this.makeTreasureMap(ursulas, this.verifiedKFrags); const encryptedTreasureMap = this.encryptTreasureMap(treasureMap); // const revocationKit = new RevocationKit(treasureMap, this.publisher.signer); diff --git a/src/sdk/cohort.ts b/src/sdk/cohort.ts index 8571f3816..070027186 100644 --- a/src/sdk/cohort.ts +++ b/src/sdk/cohort.ts @@ -26,6 +26,15 @@ export class Cohort { include: string[] = [], exclude: string[] = [] ) { + if (configuration.threshold > configuration.shares) { + throw new Error('Threshold cannot be greater than the number of shares'); + } + // TODO: Remove this limitation after `nucypher-core@0.11.0` deployment + const isMultipleOf2 = (n: number) => n % 2 === 0; + if (!isMultipleOf2(configuration.shares)) { + throw new Error('Number of shares must be a multiple of 2'); + } + const porter = new Porter(configuration.porterUri); const ursulas = await porter.getUrsulas( configuration.shares, diff --git a/src/sdk/strategy/cbd-strategy.ts b/src/sdk/strategy/cbd-strategy.ts index 2b6887371..dbc2a6766 100644 --- a/src/sdk/strategy/cbd-strategy.ts +++ b/src/sdk/strategy/cbd-strategy.ts @@ -30,12 +30,21 @@ export class CbdStrategy { } public async deploy( - web3Provider: ethers.providers.Web3Provider + web3Provider: ethers.providers.Web3Provider, + ritualId?: number ): Promise { - const dkgRitual = await DkgClient.initializeRitual( - web3Provider, - this.cohort.ursulaAddresses - ); + if (ritualId === undefined) { + ritualId = await DkgClient.initializeRitual( + web3Provider, + this.cohort.ursulaAddresses, + true + ); + } + if (ritualId === undefined) { + // Given that we just initialized the ritual, this should never happen + throw new Error('Ritual ID is undefined'); + } + const dkgRitual = await DkgClient.getExistingRitual(web3Provider, ritualId); return DeployedCbdStrategy.create(this.cohort, dkgRitual); } diff --git a/test/acceptance/alice-grants.test.ts b/test/acceptance/alice-grants.test.ts index a5fce2365..5460d43b3 100644 --- a/test/acceptance/alice-grants.test.ts +++ b/test/acceptance/alice-grants.test.ts @@ -31,7 +31,7 @@ describe('story: alice shares message with bob through policy', () => { const shares = 3; const startDate = new Date(); const endDate = new Date(Date.now() + 60 * 1000); - const mockedUrsulas = fakeUrsulas().slice(0, shares); + const mockedUrsulas = fakeUrsulas(shares); // Intermediate variables used for mocking let encryptedTreasureMap: EncryptedTreasureMap; diff --git a/test/acceptance/delay-enact.test.ts b/test/acceptance/delay-enact.test.ts index 61574df95..857e0e9f0 100644 --- a/test/acceptance/delay-enact.test.ts +++ b/test/acceptance/delay-enact.test.ts @@ -14,7 +14,7 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => { const shares = 3; const startDate = new Date(); const endDate = new Date(Date.now() + 60 * 1000); // 60s later - const mockedUrsulas = fakeUrsulas().slice(0, shares); + const mockedUrsulas = fakeUrsulas(shares); const label = 'fake-data-label'; it('alice generates a new policy', async () => { diff --git a/test/docs/cbd.test.ts b/test/docs/cbd.test.ts index cac579632..7538ba827 100644 --- a/test/docs/cbd.test.ts +++ b/test/docs/cbd.test.ts @@ -61,8 +61,8 @@ describe('Get Started (CBD PoC)', () => { // 2. Build a Cohort const config = { - threshold: 3, - shares: 5, + threshold: 2, + shares: 4, porterUri: 'https://porter-tapir.nucypher.community', }; const newCohort = await Cohort.create(config); diff --git a/test/integration/pre.test.ts b/test/integration/pre.test.ts index e3087e16c..6546228f5 100644 --- a/test/integration/pre.test.ts +++ b/test/integration/pre.test.ts @@ -15,7 +15,7 @@ describe('proxy reencryption', () => { const plaintext = toBytes('plaintext-message'); const threshold = 2; const shares = 3; - const ursulas = fakeUrsulas().slice(0, shares); + const ursulas = fakeUrsulas(shares); const label = 'fake-data-label'; const alice = fakeAlice(); const bob = fakeBob(); diff --git a/test/unit/cbd-strategy.test.ts b/test/unit/cbd-strategy.test.ts index 9723b328d..7f6f5b720 100644 --- a/test/unit/cbd-strategy.test.ts +++ b/test/unit/cbd-strategy.test.ts @@ -14,6 +14,7 @@ import { fakeWeb3Provider, makeCohort, mockCbdDecrypt, + mockGetExistingRitual, mockGetParticipants, mockGetRitualState, mockGetUrsulas, @@ -38,8 +39,9 @@ const ownsNFT = new ERC721Ownership({ chain: 5, }); const conditionExpr = new ConditionExpression(ownsNFT); -const ursulas = fakeUrsulas().slice(0, 3); +const ursulas = fakeUrsulas(); const variant = FerveoVariant.Precomputed; +const ritualId = 0; const makeCbdStrategy = async () => { const cohort = await makeCohort(ursulas); @@ -55,11 +57,13 @@ async function makeDeployedCbdStrategy() { const mockedDkgRitual = fakeDkgRitual(mockedDkg); const web3Provider = fakeWeb3Provider(aliceSecretKey.toBEBytes()); const getUrsulasSpy = mockGetUrsulas(ursulas); - const initializeRitualSpy = mockInitializeRitual(mockedDkgRitual); + const initializeRitualSpy = mockInitializeRitual(ritualId); + const getExistingRitualSpy = mockGetExistingRitual(mockedDkgRitual); const deployedStrategy = await strategy.deploy(web3Provider); expect(getUrsulasSpy).toHaveBeenCalled(); expect(initializeRitualSpy).toHaveBeenCalled(); + expect(getExistingRitualSpy).toHaveBeenCalled(); return { mockedDkg, deployedStrategy }; } diff --git a/test/unit/cohort.test.ts b/test/unit/cohort.test.ts index 40ab18ee8..e041bcad8 100644 --- a/test/unit/cohort.test.ts +++ b/test/unit/cohort.test.ts @@ -2,7 +2,7 @@ import { Cohort } from '../../src'; import { fakeUrsulas, makeCohort } from '../utils'; describe('Cohort', () => { - const mockedUrsulas = fakeUrsulas().slice(0, 3); + const mockedUrsulas = fakeUrsulas(); it('creates a Cohort', async () => { const cohort = await makeCohort(mockedUrsulas); diff --git a/test/unit/pre-strategy.test.ts b/test/unit/pre-strategy.test.ts index 9fa599a22..6a5e6d2f3 100644 --- a/test/unit/pre-strategy.test.ts +++ b/test/unit/pre-strategy.test.ts @@ -38,7 +38,7 @@ const ownsNFT = new ERC721Ownership({ chain: 5, }); const conditionExpr = new ConditionExpression(ownsNFT); -const mockedUrsulas = fakeUrsulas().slice(0, 3); +const mockedUrsulas = fakeUrsulas(); const makePreStrategy = async () => { const cohort = await makeCohort(mockedUrsulas); diff --git a/test/utils.ts b/test/utils.ts index 4ffaa1ba2..694b2f6fc 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -114,11 +114,12 @@ const genChecksumAddress = (i: number) => '0x' + '0'.repeat(40 - i.toString(16).length) + i.toString(16); const genEthAddr = (i: number) => EthereumAddress.fromString(genChecksumAddress(i)); -export const fakeUrsulas = (): readonly Ursula[] => - [0, 1, 2, 3, 4].map((i: number) => ({ +export const fakeUrsulas = (n = 4): Ursula[] => + // 0...n-1 + Array.from(Array(n).keys()).map((i: number) => ({ encryptingKey: SecretKey.random().publicKey(), checksumAddress: genChecksumAddress(i).toLowerCase(), - uri: 'https://example.a.com:9151', + uri: `https://example.${i}.com:9151`, })); export const mockGetUrsulas = (ursulas: readonly Ursula[]) => { @@ -516,8 +517,14 @@ export const fakeDkgRitual = (ritual: { ); }; -export const mockInitializeRitual = (dkgRitual: DkgRitual) => { +export const mockInitializeRitual = (ritualId: number) => { return jest.spyOn(DkgClient, 'initializeRitual').mockImplementation(() => { + return Promise.resolve(ritualId); + }); +}; + +export const mockGetExistingRitual = (dkgRitual: DkgRitual) => { + return jest.spyOn(DkgClient, 'getExistingRitual').mockImplementation(() => { return Promise.resolve(dkgRitual); }); }; @@ -526,7 +533,7 @@ export const makeCohort = async (ursulas: Ursula[]) => { const getUrsulasSpy = mockGetUrsulas(ursulas); const config = { threshold: 2, - shares: 3, + shares: ursulas.length, porterUri: 'https://_this.should.crash', }; const cohort = await Cohort.create(config);