Skip to content

Commit

Permalink
Versioned Conditions (#229)
Browse files Browse the repository at this point in the history
  • Loading branch information
derekpierre committed Jun 21, 2023
2 parents e39109f + 553f930 commit b67cbc9
Show file tree
Hide file tree
Showing 20 changed files with 594 additions and 394 deletions.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
"deep-equal": "^2.2.1",
"ethers": "^5.4.1",
"joi": "^17.7.0",
"qs": "^6.10.1"
"qs": "^6.10.1",
"semver": "^7.5.2"
},
"devDependencies": {
"@babel/core": "^7.18.10",
Expand All @@ -67,6 +68,7 @@
"@types/deep-equal": "^1.0.1",
"@types/jest": "^26.0.24",
"@types/qs": "^6.9.7",
"@types/semver": "^7.5.0",
"@typescript-eslint/eslint-plugin": "^4.0.1",
"@typescript-eslint/parser": "^4.0.1",
"cz-conventional-changelog": "^3.0.1",
Expand Down
16 changes: 8 additions & 8 deletions src/characters/cbd-recipient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
import { ethers } from 'ethers';

import { DkgCoordinatorAgent, DkgParticipant } from '../agents/coordinator';
import { ConditionSet } from '../conditions';
import { ConditionExpression } from '../conditions';
import {
DkgRitual,
getCombineDecryptionSharesFunction,
Expand Down Expand Up @@ -54,14 +54,14 @@ export class CbdTDecDecrypter {
// Retrieve and decrypt ciphertext using provider and condition set
public async retrieveAndDecrypt(
provider: ethers.providers.Web3Provider,
conditionSet: ConditionSet,
conditionExpr: ConditionExpression,
variant: number,
ciphertext: Ciphertext,
aad: Uint8Array
): Promise<readonly Uint8Array[]> {
const decryptionShares = await this.retrieve(
provider,
conditionSet,
conditionExpr,
variant,
ciphertext
);
Expand All @@ -82,20 +82,20 @@ export class CbdTDecDecrypter {
// Retrieve decryption shares
public async retrieve(
provider: ethers.providers.Web3Provider,
conditionSet: ConditionSet,
conditionExpr: ConditionExpression,
variant: number,
ciphertext: Ciphertext
): Promise<DecryptionSharePrecomputed[] | DecryptionShareSimple[]> {
const dkgParticipants = await DkgCoordinatorAgent.getParticipants(
provider,
this.ritualId
);
const contextStr = await conditionSet.buildContext(provider).toJson();
const contextStr = await conditionExpr.buildContext(provider).toJson();
const { sharedSecrets, encryptedRequests } = this.makeDecryptionRequests(
this.ritualId,
variant,
ciphertext,
conditionSet,
conditionExpr,
contextStr,
dkgParticipants
);
Expand Down Expand Up @@ -150,7 +150,7 @@ export class CbdTDecDecrypter {
ritualId: number,
variant: number,
ciphertext: Ciphertext,
conditionSet: ConditionSet,
conditionExpr: ConditionExpression,
contextStr: string,
dkgParticipants: Array<DkgParticipant>
): {
Expand All @@ -161,7 +161,7 @@ export class CbdTDecDecrypter {
ritualId,
variant,
ciphertext,
conditionSet.toWASMConditions(),
conditionExpr.toWASMConditions(),
new Context(contextStr)
);

Expand Down
10 changes: 5 additions & 5 deletions src/characters/enrico.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ import {
SecretKey,
} from '@nucypher/nucypher-core';

import { ConditionSet } from '../conditions';
import { ConditionExpression } from '../conditions';
import { Keyring } from '../keyring';
import { toBytes } from '../utils';

export class Enrico {
public readonly encryptingKey: PublicKey | DkgPublicKey;
private readonly keyring: Keyring;
public conditions?: ConditionSet;
public conditions?: ConditionExpression;

constructor(
encryptingKey: PublicKey | DkgPublicKey,
verifyingKey?: SecretKey,
conditions?: ConditionSet
conditions?: ConditionExpression
) {
this.encryptingKey = encryptingKey;
this.keyring = new Keyring(verifyingKey ?? SecretKey.random());
Expand All @@ -32,7 +32,7 @@ export class Enrico {

public encryptMessagePre(
plaintext: Uint8Array | string,
withConditions?: ConditionSet
withConditions?: ConditionExpression
): MessageKit {
if (!withConditions) {
withConditions = this.conditions;
Expand All @@ -51,7 +51,7 @@ export class Enrico {

public encryptMessageCbd(
plaintext: Uint8Array | string,
withConditions?: ConditionSet
withConditions?: ConditionExpression
): { ciphertext: Ciphertext; aad: Uint8Array } {
if (!withConditions) {
withConditions = this.conditions;
Expand Down
File renamed without changes.
5 changes: 4 additions & 1 deletion src/conditions/base/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import Joi from 'joi';
import { SUPPORTED_CHAINS } from '../const';

import { Condition } from './condition';
import { ethAddressOrUserAddressSchema, returnValueTestSchema } from './schema';
import {
ethAddressOrUserAddressSchema,
returnValueTestSchema,
} from './return-value';

const rpcMethodSchemas: Record<string, Joi.Schema> = {
eth_getBalance: Joi.array().items(ethAddressOrUserAddressSchema).required(),
Expand Down
99 changes: 99 additions & 0 deletions src/conditions/condition-expr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { Conditions as WASMConditions } from '@nucypher/nucypher-core';
import { ethers } from 'ethers';
import { SemVer } from 'semver';

import { objectEquals, toJSON } from '../utils';

import {
Condition,
ContractCondition,
RpcCondition,
TimeCondition,
} from './base';
import { BLOCKTIME_METHOD } from './base/time';
import { CompoundCondition } from './compound-condition';
import { ConditionContext } from './context';

export type ConditionExpressionJSON = {
version: string;
condition: Record<string, unknown>;
};

export class ConditionExpression {
static VERSION = '1.0.0';

constructor(
public readonly condition: Condition,
public readonly version: string = ConditionExpression.VERSION
) {}

public toObj(): ConditionExpressionJSON {
const conditionData = this.condition.toObj();
return {
version: this.version,
condition: conditionData,
};
}

public static fromObj(obj: ConditionExpressionJSON): ConditionExpression {
const receivedVersion = new SemVer(obj.version);
const currentVersion = new SemVer(ConditionExpression.VERSION);
if (receivedVersion.major > currentVersion.major) {
throw new Error(
`Version provided, ${obj.version}, is incompatible with current version, ${ConditionExpression.VERSION}`
);
}

const underlyingConditionData = obj.condition;
let condition: Condition | undefined;

if (underlyingConditionData.operator) {
condition = new CompoundCondition(underlyingConditionData);
} else if (underlyingConditionData.method) {
if (underlyingConditionData.method === BLOCKTIME_METHOD) {
condition = new TimeCondition(underlyingConditionData);
} else if (underlyingConditionData.contractAddress) {
condition = new ContractCondition(underlyingConditionData);
} else if (
(underlyingConditionData.method as string).startsWith('eth_')
) {
condition = new RpcCondition(underlyingConditionData);
}
}

if (!condition) {
throw new Error(
`Invalid condition: unrecognized condition data ${JSON.stringify(
underlyingConditionData
)}`
);
}

return new ConditionExpression(condition, obj.version);
}

public toJson(): string {
return toJSON(this.toObj());
}

public static fromJSON(json: string): ConditionExpression {
return ConditionExpression.fromObj(JSON.parse(json));
}

public toWASMConditions(): WASMConditions {
return new WASMConditions(toJSON(this.toObj()));
}

public buildContext(
provider: ethers.providers.Web3Provider
): ConditionContext {
return new ConditionContext([this.condition], provider);
}

public equals(other: ConditionExpression): boolean {
return (
this.version === other.version &&
objectEquals(this.condition.toObj(), other.condition.toObj())
);
}
}
75 changes: 0 additions & 75 deletions src/conditions/condition-set.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/conditions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import * as predefined from './predefined';

export { predefined, base };
export { Condition } from './base/condition';
export type { ConditionSetJSON } from './condition-set';
export { ConditionSet } from './condition-set';
export type { ConditionExpressionJSON } from './condition-expr';
export { ConditionExpression } from './condition-expr';
export { CompoundCondition } from './compound-condition';
export type { CustomContextParam } from './context';
export { ConditionContext } from './context';
8 changes: 4 additions & 4 deletions src/sdk/strategy/cbd-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import {
CbdTDecDecrypterJSON,
} from '../../characters/cbd-recipient';
import { Enrico } from '../../characters/enrico';
import { ConditionSet, ConditionSetJSON } from '../../conditions';
import { ConditionExpression, ConditionExpressionJSON } from '../../conditions';
import { DkgClient, DkgRitual } from '../../dkg';
import { fromJSON, toJSON } from '../../utils';
import { Cohort, CohortJSON } from '../cohort';

export type CbdStrategyJSON = {
cohort: CohortJSON;
conditionSet?: ConditionSetJSON | undefined;
conditionExpr?: ConditionExpressionJSON | undefined;
};

export type DeployedStrategyJSON = {
Expand Down Expand Up @@ -81,8 +81,8 @@ export class DeployedCbdStrategy {
return new DeployedCbdStrategy(decrypter, dkgRitual.dkgPublicKey);
}

public makeEncrypter(conditionSet: ConditionSet): Enrico {
return new Enrico(this.dkgPublicKey, undefined, conditionSet);
public makeEncrypter(conditionExpr: ConditionExpression): Enrico {
return new Enrico(this.dkgPublicKey, undefined, conditionExpr);
}

public static fromJSON(json: string) {
Expand Down
6 changes: 3 additions & 3 deletions src/sdk/strategy/pre-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
PreTDecDecrypter,
PreTDecDecrypterJSON,
} from '../../characters/pre-recipient';
import { ConditionSet } from '../../conditions';
import { ConditionExpression } from '../../conditions';
import { EnactedPolicy } from '../../policies/policy';
import { base64ToU8Receiver, bytesEquals, toJSON } from '../../utils';
import { Cohort, CohortJSON } from '../cohort';
Expand Down Expand Up @@ -165,8 +165,8 @@ export class DeployedPreStrategy {
return new DeployedPreStrategy(cohort, decrypter, policy.policyKey);
}

public makeEncrypter(conditionSet: ConditionSet): Enrico {
return new Enrico(this.policyKey, undefined, conditionSet);
public makeEncrypter(conditionExpr: ConditionExpression): Enrico {
return new Enrico(this.policyKey, undefined, conditionExpr);
}

public static fromJSON(json: string) {
Expand Down
Loading

1 comment on commit b67cbc9

@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/main/src/kits: 19.53 KB
build/main/src/characters: 89.84 KB
build/main/src/policies: 19.53 KB
build/main/src/sdk/strategy: 35.16 KB
build/main/src/sdk: 50.78 KB
build/main/src/conditions/predefined: 19.53 KB
build/main/src/conditions/base: 54.69 KB
build/main/src/conditions/context: 42.97 KB
build/main/src/conditions: 156.25 KB
build/main/src/agents: 31.25 KB
build/main/src: 437.50 KB
build/main/types/ethers-contracts/factories: 82.03 KB
build/main/types/ethers-contracts: 156.25 KB
build/main/types: 160.16 KB
build/main/test: 46.88 KB
build/main: 699.22 KB
build/module/src/kits: 19.53 KB
build/module/src/characters: 89.84 KB
build/module/src/policies: 19.53 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/base: 54.69 KB
build/module/src/conditions/context: 42.97 KB
build/module/src/conditions: 156.25 KB
build/module/src/agents: 31.25 KB
build/module/src: 429.69 KB
build/module/types/ethers-contracts/factories: 82.03 KB
build/module/types/ethers-contracts: 156.25 KB
build/module/types: 160.16 KB
build/module/test: 42.97 KB
build/module: 687.50 KB
build: 1.36 MB

Please sign in to comment.