Skip to content

Commit

Permalink
feat! remove porter uri and web3 provider from character constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Jun 29, 2023
1 parent a72e752 commit b1d6a7c
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 51 deletions.
40 changes: 19 additions & 21 deletions src/characters/alice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,9 @@ import { ChecksumAddress } from '../types';
import { RemoteBob } from './bob';

export class Alice {
private readonly porter: PorterClient;
private readonly keyring: Keyring;

private constructor(
porterUri: string,
secretKey: SecretKey,
public readonly web3Provider: ethers.providers.Web3Provider
) {
this.porter = new PorterClient(porterUri);
private constructor(secretKey: SecretKey) {
this.keyring = new Keyring(secretKey);
}

Expand All @@ -39,43 +33,45 @@ export class Alice {
return this.keyring.signer;
}

public static fromSecretKey(
porterUri: string,
secretKey: SecretKey,
web3Provider: ethers.providers.Web3Provider
): Alice {
return new Alice(porterUri, secretKey, web3Provider);
public static fromSecretKey(secretKey: SecretKey): Alice {
return new Alice(secretKey);
}

public getPolicyEncryptingKeyFromLabel(label: string): PublicKey {
return this.keyring.getPublicKeyFromLabel(label);
}

public async grant(
web3Provider: ethers.providers.Web3Provider,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
excludeUrsulas?: readonly ChecksumAddress[]
): Promise<EnactedPolicy> {
const ursulas = await this.porter.getUrsulas(
const porter = new PorterClient(porterUri);
const ursulas = await porter.getUrsulas(
policyParameters.shares,
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(policyParameters);
return await policy.enact(ursulas);
const policy = await this.createPolicy(web3Provider, policyParameters);
return await policy.enact(web3Provider, ursulas);
}

public async generatePreEnactedPolicy(
web3Provider: ethers.providers.Web3Provider,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
excludeUrsulas?: readonly ChecksumAddress[]
): Promise<PreEnactedPolicy> {
const ursulas = await this.porter.getUrsulas(
const porter = new PorterClient(porterUri);
const ursulas = await porter.getUrsulas(
policyParameters.shares,
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(policyParameters);
const policy = await this.createPolicy(web3Provider, policyParameters);
return await policy.generatePreEnactedPolicy(ursulas);
}

Expand All @@ -98,10 +94,11 @@ export class Alice {
}

private async createPolicy(
web3Provider: ethers.providers.Web3Provider,
rawParameters: BlockchainPolicyParameters
): Promise<BlockchainPolicy> {
const { bob, label, threshold, shares, startDate, endDate } =
await this.validatePolicyParameters(rawParameters);
await this.validatePolicyParameters(web3Provider, rawParameters);
const { delegatingKey, verifiedKFrags } = this.generateKFrags(
bob,
label,
Expand All @@ -122,6 +119,7 @@ export class Alice {
}

private async validatePolicyParameters(
web3Provider: ethers.providers.Web3Provider,
rawParams: BlockchainPolicyParameters
): Promise<BlockchainPolicyParameters> {
const startDate = rawParams.startDate ?? new Date();
Expand All @@ -143,8 +141,8 @@ export class Alice {
);
}

const blockNumber = await this.web3Provider.getBlockNumber();
const block = await this.web3Provider.getBlock(blockNumber);
const blockNumber = await web3Provider.getBlockNumber();
const block = await web3Provider.getBlock(blockNumber);
const blockTime = new Date(block.timestamp * 1000);
if (endDate < blockTime) {
throw new Error(
Expand Down
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const PORTER_URIS: Record<Network, string> = {
};

export const getPorterUri = (network: Network): string => {
if (!Object.values(PORTER_URIS).includes(network)) {
const uri = PORTER_URIS[network];
if (!uri) {
throw new Error(`No default Porter URI found for network: ${network}`);
}
return PORTER_URIS[network];
Expand Down
24 changes: 16 additions & 8 deletions src/policies/policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
TreasureMap,
VerifiedKeyFrag,
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';

import { PreSubscriptionManagerAgent } from '../agents/subscription-manager';
import { Alice } from '../characters/alice';
Expand Down Expand Up @@ -40,26 +41,30 @@ export class PreEnactedPolicy implements IPreEnactedPolicy {
public readonly endTimestamp: Date
) {}

public async enact(publisher: Alice): Promise<EnactedPolicy> {
const txHash = await this.publish(publisher);
public async enact(
web3Provider: ethers.providers.Web3Provider
): Promise<EnactedPolicy> {
const txHash = await this.publish(web3Provider);
return {
...this,
txHash,
};
}

private async publish(publisher: Alice): Promise<string> {
private async publish(
web3Provider: ethers.providers.Web3Provider
): Promise<string> {
const startTimestamp = toEpoch(this.startTimestamp);
const endTimestamp = toEpoch(this.endTimestamp);
const ownerAddress = await publisher.web3Provider.getSigner().getAddress();
const ownerAddress = await web3Provider.getSigner().getAddress();
const value = await PreSubscriptionManagerAgent.getPolicyCost(
publisher.web3Provider,
web3Provider,
this.size,
startTimestamp,
endTimestamp
);
const tx = await PreSubscriptionManagerAgent.createPolicy(
publisher.web3Provider,
web3Provider,
value,
this.id.toBytes(),
this.size,
Expand Down Expand Up @@ -101,9 +106,12 @@ export class BlockchainPolicy {
);
}

public async enact(ursulas: readonly Ursula[]): Promise<EnactedPolicy> {
public async enact(
web3Provider: ethers.providers.Web3Provider,
ursulas: readonly Ursula[]
): Promise<EnactedPolicy> {
const preEnacted = await this.generatePreEnactedPolicy(ursulas);
return await preEnacted.enact(this.publisher);
return await preEnacted.enact(web3Provider);
}

public async generatePreEnactedPolicy(
Expand Down
17 changes: 10 additions & 7 deletions src/sdk/strategy/pre-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,19 @@ export class PreStrategy {
}

public async deploy(
provider: ethers.providers.Web3Provider,
web3Provider: ethers.providers.Web3Provider,
label: string,
threshold?: number,
shares?: number
threshold = Math.floor(this.cohort.numUrsulas / 2) + 1,
shares = this.cohort.numUrsulas
): Promise<DeployedPreStrategy> {
shares = shares || this.cohort.numUrsulas;
threshold = threshold || Math.floor(shares / 2) + 1;
if (shares > this.cohort.numUrsulas) {
throw new Error(
`Threshold ${threshold} cannot be greater than the number of Ursulas in the cohort ${this.cohort.numUrsulas}`
);
}

const porterUri = this.cohort.porterUri;
const alice = Alice.fromSecretKey(porterUri, this.aliceSecretKey, provider);
const alice = Alice.fromSecretKey(this.aliceSecretKey);
const bob = new Bob(porterUri, this.bobSecretKey);
const policyParams = {
bob,
Expand All @@ -86,7 +84,12 @@ export class PreStrategy {
startDate: this.startDate,
endDate: this.endDate,
};
const policy = await alice.grant(policyParams, this.cohort.ursulaAddresses);
const policy = await alice.grant(
web3Provider,
porterUri,
policyParams,
this.cohort.ursulaAddresses
);
return DeployedPreStrategy.create(this.cohort, policy, this.bobSecretKey);
}

Expand Down
5 changes: 4 additions & 1 deletion test/acceptance/alice-grants.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ import {
bytesEqual,
fakeAlice,
fakeBob,
fakePorterUri,
fakeRemoteBob,
fakeUrsulas,
fakeWeb3Provider,
fromBytes,
mockEncryptTreasureMap,
mockGenerateKFrags,
Expand All @@ -32,6 +34,7 @@ describe('story: alice shares message with bob through policy', () => {
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000);
const mockedUrsulas = fakeUrsulas().slice(0, shares);
const web3Provider = fakeWeb3Provider();

// Intermediate variables used for mocking
let encryptedTreasureMap: EncryptedTreasureMap;
Expand Down Expand Up @@ -62,7 +65,7 @@ describe('story: alice shares message with bob through policy', () => {
startDate,
endDate,
};
policy = await alice.grant(policyParams);
policy = await alice.grant(web3Provider, fakePorterUri, policyParams);

expect(
bytesEqual(
Expand Down
16 changes: 10 additions & 6 deletions test/acceptance/delay-enact.test.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import {
bytesEqual,
fakeAlice,
fakePorterUri,
fakeRemoteBob,
fakeUrsulas,
fakeWeb3Provider,
mockEncryptTreasureMap,
mockGenerateKFrags,
mockGetUrsulas,
mockPublishToBlockchain,
} from '../utils';

describe('story: alice1 creates a policy but alice2 enacts it', () => {
describe('story: alice creates a policy but someone else enacts it', () => {
const threshold = 2;
const shares = 3;
const startDate = new Date();
const endDate = new Date(Date.now() + 60 * 1000); // 60s later
const mockedUrsulas = fakeUrsulas().slice(0, shares);
const label = 'fake-data-label';
const web3Provider = fakeWeb3Provider();

it('alice generates a new policy', async () => {
const getUrsulasSpy = mockGetUrsulas(mockedUrsulas);
const generateKFragsSpy = mockGenerateKFrags();
const publishToBlockchainSpy = mockPublishToBlockchain();
const encryptTreasureMapSpy = mockEncryptTreasureMap();

const alice1 = fakeAlice('fake-secret-key-32-bytes-alice-1');
const alice2 = fakeAlice('fake-secret-key-32-bytes-alice-2');
const alice = fakeAlice('fake-secret-key-32-bytes-alice-1');
const bob = fakeRemoteBob();
const policyParams = {
bob,
Expand All @@ -35,18 +37,20 @@ describe('story: alice1 creates a policy but alice2 enacts it', () => {
endDate,
};

const preEnactedPolicy = await alice1.generatePreEnactedPolicy(
const preEnactedPolicy = await alice.generatePreEnactedPolicy(
web3Provider,
fakePorterUri,
policyParams
);
expect(
bytesEqual(
preEnactedPolicy.aliceVerifyingKey.toCompressedBytes(),
alice1.verifyingKey.toCompressedBytes()
alice.verifyingKey.toCompressedBytes()
)
).toBeTruthy();
expect(preEnactedPolicy.label).toBe(label);

const enacted = await preEnactedPolicy.enact(alice2);
const enacted = await preEnactedPolicy.enact(web3Provider);
expect(enacted.txHash).toBeDefined();

expect(getUrsulasSpy).toHaveBeenCalled();
Expand Down
10 changes: 8 additions & 2 deletions test/docs/cbd.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { MessageKit, VerifiedKeyFrag } from '@nucypher/nucypher-core';
import { providers } from 'ethers';

import { Cohort, conditions, PreStrategy, SecretKey } from '../../src';
import {
Cohort,
conditions,
getPorterUri,
PreStrategy,
SecretKey,
} from '../../src';
import { Ursula } from '../../src/porter';
import { toBytes } from '../../src/utils';
import {
Expand Down Expand Up @@ -60,7 +66,7 @@ describe('Get Started (CBD PoC)', () => {
//

// 2. Build a Cohort
const porterUri = 'https://porter-tapir.nucypher.community';
const porterUri = getPorterUri('tapir');
const numUrsulas = 5;
const newCohort = await Cohort.create(porterUri, numUrsulas);

Expand Down
9 changes: 4 additions & 5 deletions test/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ export const bytesEqual = (first: Uint8Array, second: Uint8Array): boolean =>
export const fromBytes = (bytes: Uint8Array): string =>
new TextDecoder().decode(bytes);

const porterUri = 'https://_this_should_crash.com/';
export const fakePorterUri = 'https://_this_should_crash.com/';

export const fakeBob = (): Bob => {
const secretKey = SecretKey.fromBEBytes(
toBytes('fake-secret-key-32-bytes-bob-xxx')
);
return Bob.fromSecretKey(porterUri, secretKey);
return Bob.fromSecretKey(fakePorterUri, secretKey);
};

export const fakeRemoteBob = (): RemoteBob => {
Expand All @@ -75,12 +75,11 @@ export const fakeRemoteBob = (): RemoteBob => {

export const fakeAlice = (aliceKey = 'fake-secret-key-32-bytes-alice-x') => {
const secretKey = SecretKey.fromBEBytes(toBytes(aliceKey));
const provider = fakeWeb3Provider(secretKey.toBEBytes());
return Alice.fromSecretKey(porterUri, secretKey, provider);
return Alice.fromSecretKey(secretKey);
};

export const fakeWeb3Provider = (
secretKeyBytes: Uint8Array,
secretKeyBytes = SecretKey.random().toBEBytes(),
blockNumber?: number,
blockTimestamp?: number
): ethers.providers.Web3Provider => {
Expand Down

1 comment on commit b1d6a7c

@github-actions
Copy link

Choose a reason for hiding this comment

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

Bundled size for the package is listed below:

build/module/types/ethers-contracts/factories: 82.03 KB
build/module/types/ethers-contracts: 152.34 KB
build/module/types: 156.25 KB
build/module/src/conditions/predefined: 19.53 KB
build/module/src/conditions/context: 42.97 KB
build/module/src/conditions/base: 54.69 KB
build/module/src/conditions: 156.25 KB
build/module/src/kits: 19.53 KB
build/module/src/agents: 35.16 KB
build/module/src/characters: 74.22 KB
build/module/src/policies: 19.53 KB
build/module/src/sdk/strategy: 35.16 KB
build/module/src/sdk: 46.88 KB
build/module/src: 433.59 KB
build/module/test: 42.97 KB
build/module: 687.50 KB
build/main/types/ethers-contracts/factories: 82.03 KB
build/main/types/ethers-contracts: 152.34 KB
build/main/types: 156.25 KB
build/main/src/conditions/predefined: 19.53 KB
build/main/src/conditions/context: 42.97 KB
build/main/src/conditions/base: 54.69 KB
build/main/src/conditions: 156.25 KB
build/main/src/kits: 19.53 KB
build/main/src/agents: 35.16 KB
build/main/src/characters: 74.22 KB
build/main/src/policies: 19.53 KB
build/main/src/sdk/strategy: 35.16 KB
build/main/src/sdk: 46.88 KB
build/main/src: 437.50 KB
build/main/test: 46.88 KB
build/main: 695.31 KB
build: 1.35 MB

Please sign in to comment.