Skip to content

Commit

Permalink
Add ritual initialization to client (#233)
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec authored Jul 12, 2023
2 parents a1a1a65 + 2d1aa90 commit 49fa8ab
Show file tree
Hide file tree
Showing 16 changed files with 410 additions and 115 deletions.
72 changes: 66 additions & 6 deletions src/agents/coordinator.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { SessionStaticKey } from '@nucypher/nucypher-core';
import { SessionStaticKey, Transcript } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';

import {
Coordinator,
Coordinator__factory,
} from '../../types/ethers-contracts';
import { BLS12381 } from '../../types/ethers-contracts/Coordinator';
import { ChecksumAddress } from '../types';
import { fromHexString } from '../utils';

import { getContract } from './contracts';
import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';

export interface CoordinatorRitual {
initiator: string;
Expand All @@ -24,12 +25,22 @@ export interface CoordinatorRitual {
export type DkgParticipant = {
provider: string;
aggregated: boolean;
transcript: Transcript;
decryptionRequestStaticKey: SessionStaticKey;
};

export enum DkgRitualState {
NON_INITIATED,
AWAITING_TRANSCRIPTS,
AWAITING_AGGREGATIONS,
TIMEOUT,
INVALID,
FINALIZED,
}

export class DkgCoordinatorAgent {
public static async getParticipants(
provider: ethers.providers.Provider,
provider: ethers.providers.Web3Provider,
ritualId: number
): Promise<DkgParticipant[]> {
const Coordinator = await this.connectReadOnly(provider);
Expand All @@ -39,27 +50,76 @@ export class DkgCoordinatorAgent {
return {
provider: participant.provider,
aggregated: participant.aggregated,
transcript: Transcript.fromBytes(fromHexString(participant.transcript)),
decryptionRequestStaticKey: SessionStaticKey.fromBytes(
fromHexString(participant.decryptionRequestStaticKey)
),
};
});
}

public static async initializeRitual(
provider: ethers.providers.Web3Provider,
providers: ChecksumAddress[]
): Promise<number> {
const Coordinator = await this.connectReadWrite(provider);
const tx = await Coordinator.initiateRitual(providers);
const txReceipt = await tx.wait(DEFAULT_WAIT_N_CONFIRMATIONS);
const [ritualStartEvent] = txReceipt.events ?? [];
if (!ritualStartEvent) {
throw new Error('Ritual start event not found');
}
return ritualStartEvent.args?.ritualId;
}

public static async getRitual(
provider: ethers.providers.Provider,
provider: ethers.providers.Web3Provider,
ritualId: number
): Promise<CoordinatorRitual> {
const Coordinator = await this.connectReadOnly(provider);
return Coordinator.rituals(ritualId);
}

private static async connectReadOnly(provider: ethers.providers.Provider) {
public static async getRitualState(
provider: ethers.providers.Web3Provider,
ritualId: number
): Promise<DkgRitualState> {
const Coordinator = await this.connectReadOnly(provider);
return await Coordinator.getRitualState(ritualId);
}

public static async onRitualEndEvent(
provider: ethers.providers.Web3Provider,
ritualId: number,
callback: (successful: boolean) => void
): Promise<void> {
const Coordinator = await this.connectReadOnly(provider);
// We leave `initiator` undefined because we don't care who the initiator is
// We leave `successful` undefined because we don't care if the ritual was successful
const eventFilter = Coordinator.filters.EndRitual(
ritualId,
undefined,
undefined
);
Coordinator.once(eventFilter, (_ritualId, _initiator, successful) => {
callback(successful);
});
}

private static async connectReadOnly(
provider: ethers.providers.Web3Provider
) {
return await this.connect(provider);
}

private static async connectReadWrite(
web3Provider: ethers.providers.Web3Provider
) {
return await this.connect(web3Provider, web3Provider.getSigner());
}

private static async connect(
provider: ethers.providers.Provider,
provider: ethers.providers.Web3Provider,
signer?: ethers.providers.JsonRpcSigner
): Promise<Coordinator> {
const network = await provider.getNetwork();
Expand Down
8 changes: 5 additions & 3 deletions src/agents/subscription-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class PreSubscriptionManagerAgent {
}

public static async getPolicyCost(
provider: ethers.providers.Provider,
provider: ethers.providers.Web3Provider,
size: number,
startTimestamp: number,
endTimestamp: number
Expand All @@ -61,7 +61,9 @@ export class PreSubscriptionManagerAgent {
);
}

private static async connectReadOnly(provider: ethers.providers.Provider) {
private static async connectReadOnly(
provider: ethers.providers.Web3Provider
) {
return await this.connect(provider);
}

Expand All @@ -72,7 +74,7 @@ export class PreSubscriptionManagerAgent {
}

private static async connect(
provider: ethers.providers.Provider,
provider: ethers.providers.Web3Provider,
signer?: ethers.providers.JsonRpcSigner
): Promise<SubscriptionManager> {
const network = await provider.getNetwork();
Expand Down
46 changes: 38 additions & 8 deletions src/characters/cbd-recipient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ import {
} from '@nucypher/nucypher-core';
import { ethers } from 'ethers';

import { DkgCoordinatorAgent, DkgParticipant } from '../agents/coordinator';
import {
DkgCoordinatorAgent,
DkgParticipant,
DkgRitualState,
} from '../agents/coordinator';
import { ConditionExpression } from '../conditions';
import {
DkgClient,
DkgRitual,
FerveoVariant,
getCombineDecryptionSharesFunction,
Expand Down Expand Up @@ -43,7 +48,7 @@ export class CbdTDecDecrypter {
return new CbdTDecDecrypter(
new Porter(porterUri),
dkgRitual.id,
dkgRitual.threshold
dkgRitual.dkgParams.threshold
);
}

Expand All @@ -52,13 +57,15 @@ export class CbdTDecDecrypter {
provider: ethers.providers.Web3Provider,
conditionExpr: ConditionExpression,
variant: FerveoVariant,
ciphertext: Ciphertext
ciphertext: Ciphertext,
verifyRitual = true
): Promise<Uint8Array> {
const decryptionShares = await this.retrieve(
provider,
conditionExpr,
variant,
ciphertext
ciphertext,
verifyRitual
);

const combineDecryptionSharesFn =
Expand All @@ -73,16 +80,39 @@ export class CbdTDecDecrypter {

// Retrieve decryption shares
public async retrieve(
provider: ethers.providers.Web3Provider,
web3Provider: ethers.providers.Web3Provider,
conditionExpr: ConditionExpression,
variant: number,
ciphertext: Ciphertext
ciphertext: Ciphertext,
verifyRitual = true
): Promise<DecryptionSharePrecomputed[] | DecryptionShareSimple[]> {
const ritualState = await DkgCoordinatorAgent.getRitualState(
web3Provider,
this.ritualId
);
if (ritualState !== DkgRitualState.FINALIZED) {
throw new Error(
`Ritual with id ${this.ritualId} is not finalized. Ritual state is ${ritualState}.`
);
}

if (verifyRitual) {
const isLocallyVerified = await DkgClient.verifyRitual(
web3Provider,
this.ritualId
);
if (!isLocallyVerified) {
throw new Error(
`Ritual with id ${this.ritualId} has failed local verification.`
);
}
}

const dkgParticipants = await DkgCoordinatorAgent.getParticipants(
provider,
web3Provider,
this.ritualId
);
const contextStr = await conditionExpr.buildContext(provider).toJson();
const contextStr = await conditionExpr.buildContext(web3Provider).toJson();
const { sharedSecrets, encryptedRequests } = this.makeDecryptionRequests(
this.ritualId,
variant,
Expand Down
Loading

1 comment on commit 49fa8ab

@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/policies: 19.53 KB
build/module/src/characters: 93.75 KB
build/module/src/agents: 39.06 KB
build/module/src/sdk/strategy: 31.25 KB
build/module/src/sdk: 46.88 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: 449.22 KB
build/module/test: 46.88 KB
build/module: 707.03 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/policies: 19.53 KB
build/main/src/characters: 93.75 KB
build/main/src/agents: 39.06 KB
build/main/src/sdk/strategy: 31.25 KB
build/main/src/sdk: 46.88 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: 453.13 KB
build/main/test: 46.88 KB
build/main: 710.94 KB
build: 1.39 MB

Please sign in to comment.