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);