Skip to content

Commit

Permalink
draft signer-provider seperation
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-roslaniec committed Aug 23, 2023
1 parent a98cee4 commit 2e7c3be
Show file tree
Hide file tree
Showing 23 changed files with 378 additions and 344 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"@nucypher/nucypher-core": "^0.11.0",
"axios": "^0.21.1",
"deep-equal": "^2.2.1",
"ethers": "^5.4.1",
"ethers": "^5.7.2",
"joi": "^17.7.0",
"qs": "^6.10.1",
"semver": "^7.5.2"
Expand Down
16 changes: 9 additions & 7 deletions src/agents/coordinator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,11 @@ export class DkgCoordinatorAgent {
}

public static async initializeRitual(
provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
signer: ethers.Signer,
providers: ChecksumAddress[]
): Promise<number> {
const Coordinator = await this.connectReadWrite(provider);
const Coordinator = await this.connectReadWrite(provider, signer);
const tx = await Coordinator.initiateRitual(providers);
const txReceipt = await tx.wait(DEFAULT_WAIT_N_CONFIRMATIONS);
const [ritualStartEvent] = txReceipt.events ?? [];
Expand All @@ -79,15 +80,15 @@ export class DkgCoordinatorAgent {
}

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

public static async onRitualEndEvent(
provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
ritualId: number,
callback: (successful: boolean) => void
): Promise<void> {
Expand All @@ -109,14 +110,15 @@ export class DkgCoordinatorAgent {
}

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

private static async connect(
provider: ethers.providers.Provider,
signer?: ethers.providers.JsonRpcSigner
signer: ethers.Signer | undefined = undefined
): Promise<Coordinator> {
const network = await provider.getNetwork();
const contractAddress = getContract(network.chainId, 'COORDINATOR');
Expand Down
12 changes: 7 additions & 5 deletions src/agents/subscription-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,16 @@ import { DEFAULT_WAIT_N_CONFIRMATIONS, getContract } from './contracts';

export class PreSubscriptionManagerAgent {
public static async createPolicy(
web3Provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
signer: ethers.Signer,
valueInWei: BigNumber,
policyId: Uint8Array,
size: number,
startTimestamp: number,
endTimestamp: number,
ownerAddress: ChecksumAddress
): Promise<ContractTransaction> {
const SubscriptionManager = await this.connectReadWrite(web3Provider);
const SubscriptionManager = await this.connectReadWrite(provider, signer);
const overrides = {
value: valueInWei.toString(),
};
Expand Down Expand Up @@ -66,14 +67,15 @@ export class PreSubscriptionManagerAgent {
}

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

private static async connect(
provider: ethers.providers.Provider,
signer?: ethers.providers.JsonRpcSigner
signer?: ethers.Signer
): Promise<SubscriptionManager> {
const network = await provider.getNetwork();
const contractAddress = getContract(
Expand Down
21 changes: 11 additions & 10 deletions src/characters/alice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export class Alice {
}

public async grant(
web3Provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
signer: ethers.Signer,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
Expand All @@ -54,12 +55,12 @@ export class Alice {
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(web3Provider, policyParameters);
return await policy.enact(web3Provider, ursulas);
const policy = await this.createPolicy(provider, policyParameters);
return await policy.enact(provider, signer, ursulas);
}

public async generatePreEnactedPolicy(
web3Provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
porterUri: string,
policyParameters: BlockchainPolicyParameters,
includeUrsulas?: readonly ChecksumAddress[],
Expand All @@ -71,7 +72,7 @@ export class Alice {
excludeUrsulas,
includeUrsulas
);
const policy = await this.createPolicy(web3Provider, policyParameters);
const policy = await this.createPolicy(provider, policyParameters);
return await policy.generatePreEnactedPolicy(ursulas);
}

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

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

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

const blockNumber = await web3Provider.getBlockNumber();
const block = await web3Provider.getBlock(blockNumber);
const blockNumber = await provider.getBlockNumber();
const block = await provider.getBlock(blockNumber);
const blockTime = new Date(block.timestamp * 1000);
if (endDate < blockTime) {
throw new Error(
Expand Down
11 changes: 8 additions & 3 deletions src/characters/cbd-recipient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ export class ThresholdDecrypter {

// Retrieve and decrypt ciphertext using provider and condition expression
public async retrieveAndDecrypt(
provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
signer: ethers.Signer,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
): Promise<Uint8Array> {
const decryptionShares = await this.retrieve(
provider,
signer,
conditionExpr,
ciphertext
);
Expand All @@ -64,15 +66,18 @@ export class ThresholdDecrypter {

// Retrieve decryption shares
public async retrieve(
provider: ethers.providers.Web3Provider,
provider: ethers.providers.Provider,
signer: ethers.Signer,
conditionExpr: ConditionExpression,
ciphertext: Ciphertext
): Promise<DecryptionShareSimple[]> {
const dkgParticipants = await DkgCoordinatorAgent.getParticipants(
provider,
this.ritualId
);
const contextStr = await conditionExpr.buildContext(provider).toJson();
const contextStr = await conditionExpr
.buildContext(provider, signer)
.toJson();
const { sharedSecrets, encryptedRequests } = this.makeDecryptionRequests(
this.ritualId,
ciphertext,
Expand Down
18 changes: 12 additions & 6 deletions src/characters/pre-recipient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,15 @@ export class PreDecrypter {
}

public async retrieveAndDecrypt(
messageKits: readonly MessageKit[],
provider: ethers.providers.Web3Provider
provider: ethers.providers.Provider,
signer: ethers.Signer,
messageKits: readonly MessageKit[]
): Promise<readonly Uint8Array[]> {
const policyMessageKits = await this.retrieve(messageKits, provider);
const policyMessageKits = await this.retrieve(
provider,
signer,
messageKits
);

policyMessageKits.forEach((mk: PolicyMessageKit) => {
if (!mk.isDecryptableByReceiver()) {
Expand All @@ -90,8 +95,9 @@ export class PreDecrypter {
}

public async retrieve(
messageKits: readonly MessageKit[],
provider: ethers.providers.Web3Provider
provider: ethers.providers.Provider,
signer: ethers.Signer,
messageKits: readonly MessageKit[]
): Promise<readonly PolicyMessageKit[]> {
const treasureMap = this.encryptedTreasureMap.decrypt(
this.keyring.secretKey,
Expand All @@ -106,7 +112,7 @@ export class PreDecrypter {
.reduce((acc: ConditionExpression[], val) => acc.concat(val), [])
.map((condExpr: ConditionExpression) => condExpr.condition);

const conditionContext = new ConditionContext(conditions, provider);
const conditionContext = new ConditionContext(provider, signer, conditions);

const policyMessageKits = messageKits.map((mk) =>
PolicyMessageKit.fromMessageKit(
Expand Down
5 changes: 3 additions & 2 deletions src/conditions/condition-expr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,10 @@ export class ConditionExpression {
}

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

public asAad(): Uint8Array {
Expand Down
17 changes: 13 additions & 4 deletions src/conditions/context/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ export class ConditionContext {
private readonly walletAuthProvider: WalletAuthenticationProvider;

constructor(
private readonly conditions: ReadonlyArray<Condition>,
// TODO: We don't always need a web3 provider, only in cases where some specific context parameters are used
// TODO: Consider making this optional or introducing a different pattern to handle that
private readonly web3Provider: ethers.providers.Web3Provider,
private readonly provider: ethers.providers.Provider,
private readonly signer: ethers.Signer,
private readonly conditions: ReadonlyArray<Condition>,
public readonly customParameters: Record<string, CustomContextParam> = {}
) {
Object.keys(customParameters).forEach((key) => {
Expand All @@ -35,7 +36,10 @@ export class ConditionContext {
);
}
});
this.walletAuthProvider = new WalletAuthenticationProvider(web3Provider);
this.walletAuthProvider = new WalletAuthenticationProvider(
provider,
signer
);
}

public toObj = async (): Promise<Record<string, ContextParam>> => {
Expand Down Expand Up @@ -103,6 +107,11 @@ export class ConditionContext {
public withCustomParams = (
params: Record<string, CustomContextParam>
): ConditionContext => {
return new ConditionContext(this.conditions, this.web3Provider, params);
return new ConditionContext(
this.provider,
this.signer,
this.conditions,
params
);
};
}
23 changes: 14 additions & 9 deletions src/conditions/context/providers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { TypedDataSigner } from '@ethersproject/abstract-signer';
import { ethers } from 'ethers';
import { utils as ethersUtils } from 'ethers/lib/ethers';

Expand All @@ -18,10 +19,13 @@ interface ChainData {
export class WalletAuthenticationProvider {
private walletSignature?: Record<string, string>;

constructor(private readonly web3Provider: ethers.providers.Web3Provider) {}
constructor(
private readonly provider: ethers.providers.Provider,
private readonly signer: ethers.Signer
) {}

public async getOrCreateWalletSignature(): Promise<TypedSignature> {
const address = await this.web3Provider.getSigner().getAddress();
const address = await this.signer.getAddress();
const storageKey = `wallet-signature-${address}`;

// If we have a signature in localStorage, return it
Expand Down Expand Up @@ -59,7 +63,7 @@ export class WalletAuthenticationProvider {
private async createWalletSignature(): Promise<TypedSignature> {
// Ensure freshness of the signature
const { blockNumber, blockHash, chainId } = await this.getChainData();
const address = await this.web3Provider.getSigner().getAddress();
const address = await this.signer.getAddress();
const signatureText = `I'm the owner of address ${address} as of block number ${blockNumber}`;
const salt = ethersUtils.hexlify(ethersUtils.randomBytes(32));

Expand All @@ -85,9 +89,10 @@ export class WalletAuthenticationProvider {
blockHash,
},
};
const signature = await this.web3Provider
.getSigner()
._signTypedData(typedData.domain, typedData.types, typedData.message);
// https://github.com/ethers-io/ethers.js/issues/1431#issuecomment-813950552
const signature = await (
this.signer as unknown as TypedDataSigner
)._signTypedData(typedData.domain, typedData.types, typedData.message);

const formattedTypedData: FormattedTypedData = {
...typedData,
Expand Down Expand Up @@ -118,9 +123,9 @@ export class WalletAuthenticationProvider {
}

private async getChainData(): Promise<ChainData> {
const blockNumber = await this.web3Provider.getBlockNumber();
const blockHash = (await this.web3Provider.getBlock(blockNumber)).hash;
const chainId = (await this.web3Provider.getNetwork()).chainId;
const blockNumber = await this.provider.getBlockNumber();
const blockHash = (await this.provider.getBlock(blockNumber)).hash;
const chainId = (await this.provider.getNetwork()).chainId;
return { blockNumber, blockHash, chainId };
}
}
Loading

1 comment on commit 2e7c3be

@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/characters: 74.22 KB
build/main/src/kits: 19.53 KB
build/main/src/conditions/context: 42.97 KB
build/main/src/conditions/predefined: 19.53 KB
build/main/src/conditions/base: 54.69 KB
build/main/src/conditions: 156.25 KB
build/main/src/agents: 39.06 KB
build/main/src/sdk/strategy: 35.16 KB
build/main/src/sdk: 46.88 KB
build/main/src/policies: 19.53 KB
build/main/src: 433.59 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: 644.53 KB
build/module/src/characters: 74.22 KB
build/module/src/kits: 19.53 KB
build/module/src/conditions/context: 42.97 KB
build/module/src/conditions/predefined: 19.53 KB
build/module/src/conditions/base: 54.69 KB
build/module/src/conditions: 156.25 KB
build/module/src/agents: 39.06 KB
build/module/src/sdk/strategy: 31.25 KB
build/module/src/sdk: 42.97 KB
build/module/src/policies: 19.53 KB
build/module/src: 425.78 KB
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: 636.72 KB
build: 1.26 MB

Please sign in to comment.