mirror of
https://github.com/logos-messaging/logos-messaging-js.git
synced 2026-05-17 18:19:27 +00:00
chore: use CredentialsManager for rln.ts
This commit is contained in:
parent
9f8fd15ba9
commit
7aaa84a68c
@ -5,5 +5,5 @@ export async function createRLN(): Promise<RLNInstance> {
|
|||||||
// asynchronously. This file does the single async import, so
|
// asynchronously. This file does the single async import, so
|
||||||
// that no one else needs to worry about it again.
|
// that no one else needs to worry about it again.
|
||||||
const rlnModule = await import("./rln.js");
|
const rlnModule = await import("./rln.js");
|
||||||
return rlnModule.create();
|
return rlnModule.RLNInstance.create();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import {
|
|||||||
buildBigIntFromUint8Array,
|
buildBigIntFromUint8Array,
|
||||||
extractMetaMaskSigner
|
extractMetaMaskSigner
|
||||||
} from "./utils/index.js";
|
} from "./utils/index.js";
|
||||||
|
import { Zerokit } from "./zerokit.js";
|
||||||
|
|
||||||
const log = new Logger("waku:credentials");
|
const log = new Logger("waku:credentials");
|
||||||
|
|
||||||
@ -26,27 +27,50 @@ const log = new Logger("waku:credentials");
|
|||||||
* It is used to register membership and generate identity credentials
|
* It is used to register membership and generate identity credentials
|
||||||
*/
|
*/
|
||||||
export class RLNCredentialsManager {
|
export class RLNCredentialsManager {
|
||||||
private started = false;
|
protected started = false;
|
||||||
private starting = false;
|
protected starting = false;
|
||||||
|
|
||||||
private _contract: undefined | RLNBaseContract;
|
private _contract: undefined | RLNBaseContract;
|
||||||
private _signer: undefined | ethers.Signer;
|
private _signer: undefined | ethers.Signer;
|
||||||
|
|
||||||
private keystore = Keystore.create();
|
protected keystore = Keystore.create();
|
||||||
private _credentials: undefined | DecryptedCredentials;
|
private _credentials: undefined | DecryptedCredentials;
|
||||||
|
|
||||||
public constructor() {
|
public zerokit: undefined | Zerokit;
|
||||||
|
|
||||||
|
public constructor(zerokit?: Zerokit) {
|
||||||
log.info("RLNCredentialsManager initialized");
|
log.info("RLNCredentialsManager initialized");
|
||||||
|
this.zerokit = zerokit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get contract(): undefined | RLNBaseContract {
|
public get contract(): undefined | RLNBaseContract {
|
||||||
return this._contract;
|
return this._contract;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set contract(contract: RLNBaseContract | undefined) {
|
||||||
|
this._contract = contract;
|
||||||
|
}
|
||||||
|
|
||||||
public get signer(): undefined | ethers.Signer {
|
public get signer(): undefined | ethers.Signer {
|
||||||
return this._signer;
|
return this._signer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public set signer(signer: ethers.Signer | undefined) {
|
||||||
|
this._signer = signer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get credentials(): undefined | DecryptedCredentials {
|
||||||
|
return this._credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public set credentials(credentials: DecryptedCredentials | undefined) {
|
||||||
|
this._credentials = credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get provider(): undefined | ethers.providers.Provider {
|
||||||
|
return this.contract?.provider;
|
||||||
|
}
|
||||||
|
|
||||||
public async start(options: StartRLNOptions = {}): Promise<void> {
|
public async start(options: StartRLNOptions = {}): Promise<void> {
|
||||||
if (this.started || this.starting) {
|
if (this.started || this.starting) {
|
||||||
log.info("RLNCredentialsManager already started or starting");
|
log.info("RLNCredentialsManager already started or starting");
|
||||||
@ -83,7 +107,7 @@ export class RLNCredentialsManager {
|
|||||||
this._contract = new RLNBaseContract({
|
this._contract = new RLNBaseContract({
|
||||||
address: address!,
|
address: address!,
|
||||||
signer: signer!,
|
signer: signer!,
|
||||||
rateLimit: rateLimit
|
rateLimit: rateLimit ?? this.zerokit?.getRateLimit
|
||||||
});
|
});
|
||||||
|
|
||||||
log.info("RLNCredentialsManager successfully started");
|
log.info("RLNCredentialsManager successfully started");
|
||||||
@ -96,11 +120,7 @@ export class RLNCredentialsManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get credentials(): DecryptedCredentials | undefined {
|
protected async determineStartOptions(
|
||||||
return this._credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async determineStartOptions(
|
|
||||||
options: StartRLNOptions,
|
options: StartRLNOptions,
|
||||||
credentials: KeystoreEntity | undefined
|
credentials: KeystoreEntity | undefined
|
||||||
): Promise<StartRLNOptions> {
|
): Promise<StartRLNOptions> {
|
||||||
@ -134,7 +154,7 @@ export class RLNCredentialsManager {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async decryptCredentialsIfNeeded(
|
protected static async decryptCredentialsIfNeeded(
|
||||||
credentials?: EncryptedCredentials | DecryptedCredentials
|
credentials?: EncryptedCredentials | DecryptedCredentials
|
||||||
): Promise<{ credentials?: DecryptedCredentials; keystore?: Keystore }> {
|
): Promise<{ credentials?: DecryptedCredentials; keystore?: Keystore }> {
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
@ -222,7 +242,15 @@ export class RLNCredentialsManager {
|
|||||||
|
|
||||||
if ("signature" in options) {
|
if ("signature" in options) {
|
||||||
log.info("Generating identity from signature");
|
log.info("Generating identity from signature");
|
||||||
identity = this.generateSeededIdentityCredential(options.signature);
|
if (this.zerokit) {
|
||||||
|
log.info("Using Zerokit to generate identity");
|
||||||
|
identity = this.zerokit.generateSeededIdentityCredential(
|
||||||
|
options.signature
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
log.info("Using local implementation to generate identity");
|
||||||
|
identity = this.generateSeededIdentityCredential(options.signature);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!identity) {
|
if (!identity) {
|
||||||
@ -248,4 +276,31 @@ export class RLNCredentialsManager {
|
|||||||
log.warn("Failed to load credentials");
|
log.warn("Failed to load credentials");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async verifyCredentialsAgainstContract(
|
||||||
|
credentials: KeystoreEntity
|
||||||
|
): Promise<void> {
|
||||||
|
if (!this.contract) {
|
||||||
|
throw Error(
|
||||||
|
"Failed to verify chain coordinates: no contract initialized."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registryAddress = credentials.membership.address;
|
||||||
|
const currentRegistryAddress = this.contract.address;
|
||||||
|
if (registryAddress !== currentRegistryAddress) {
|
||||||
|
throw Error(
|
||||||
|
`Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const chainId = credentials.membership.chainId;
|
||||||
|
const network = await this.contract.provider.getNetwork();
|
||||||
|
const currentChainId = network.chainId;
|
||||||
|
if (chainId !== currentChainId) {
|
||||||
|
throw Error(
|
||||||
|
`Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,6 @@ import type {
|
|||||||
import { Logger } from "@waku/utils";
|
import { Logger } from "@waku/utils";
|
||||||
import init from "@waku/zerokit-rln-wasm";
|
import init from "@waku/zerokit-rln-wasm";
|
||||||
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
import * as zerokitRLN from "@waku/zerokit-rln-wasm";
|
||||||
import { ethers } from "ethers";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createRLNDecoder,
|
createRLNDecoder,
|
||||||
@ -16,234 +15,51 @@ import {
|
|||||||
type RLNEncoder
|
type RLNEncoder
|
||||||
} from "./codec.js";
|
} from "./codec.js";
|
||||||
import { DEFAULT_RATE_LIMIT } from "./contract/constants.js";
|
import { DEFAULT_RATE_LIMIT } from "./contract/constants.js";
|
||||||
import { LINEA_CONTRACT, RLNContract } from "./contract/index.js";
|
import { RLNCredentialsManager } from "./credentials_manager.js";
|
||||||
import { Keystore } from "./keystore/index.js";
|
|
||||||
import type {
|
import type {
|
||||||
DecryptedCredentials,
|
DecryptedCredentials,
|
||||||
EncryptedCredentials
|
EncryptedCredentials
|
||||||
} from "./keystore/index.js";
|
} from "./keystore/index.js";
|
||||||
import { KeystoreEntity, Password } from "./keystore/types.js";
|
|
||||||
import verificationKey from "./resources/verification_key";
|
import verificationKey from "./resources/verification_key";
|
||||||
import * as wc from "./resources/witness_calculator";
|
import * as wc from "./resources/witness_calculator";
|
||||||
import { WitnessCalculator } from "./resources/witness_calculator";
|
import { WitnessCalculator } from "./resources/witness_calculator";
|
||||||
import { RegisterMembershipOptions, StartRLNOptions } from "./types.js";
|
|
||||||
import { extractMetaMaskSigner } from "./utils/index.js";
|
|
||||||
import { Zerokit } from "./zerokit.js";
|
import { Zerokit } from "./zerokit.js";
|
||||||
|
|
||||||
const log = new Logger("waku:rln");
|
const log = new Logger("waku:rln");
|
||||||
|
|
||||||
async function loadWitnessCalculator(): Promise<WitnessCalculator> {
|
|
||||||
try {
|
|
||||||
const url = new URL("./resources/rln.wasm", import.meta.url);
|
|
||||||
const response = await fetch(url);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to fetch witness calculator: ${response.status} ${response.statusText}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await wc.builder(
|
|
||||||
new Uint8Array(await response.arrayBuffer()),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
log.error("Error loading witness calculator:", error);
|
|
||||||
throw new Error(
|
|
||||||
`Failed to load witness calculator: ${error instanceof Error ? error.message : String(error)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function loadZkey(): Promise<Uint8Array> {
|
|
||||||
try {
|
|
||||||
const url = new URL("./resources/rln_final.zkey", import.meta.url);
|
|
||||||
const response = await fetch(url);
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to fetch zkey: ${response.status} ${response.statusText}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Uint8Array(await response.arrayBuffer());
|
|
||||||
} catch (error) {
|
|
||||||
log.error("Error loading zkey:", error);
|
|
||||||
throw new Error(
|
|
||||||
`Failed to load zkey: ${error instanceof Error ? error.message : String(error)}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of RLN
|
|
||||||
* @returns RLNInstance
|
|
||||||
*/
|
|
||||||
export async function create(): Promise<RLNInstance> {
|
|
||||||
try {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
await (init as any)?.();
|
|
||||||
zerokitRLN.init_panic_hook();
|
|
||||||
|
|
||||||
const witnessCalculator = await loadWitnessCalculator();
|
|
||||||
const zkey = await loadZkey();
|
|
||||||
|
|
||||||
const stringEncoder = new TextEncoder();
|
|
||||||
const vkey = stringEncoder.encode(JSON.stringify(verificationKey));
|
|
||||||
|
|
||||||
const DEPTH = 20;
|
|
||||||
const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
|
|
||||||
const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT);
|
|
||||||
|
|
||||||
return new RLNInstance(zerokit);
|
|
||||||
} catch (error) {
|
|
||||||
log.error("Failed to initialize RLN:", error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type WakuRLNEncoderOptions = WakuEncoderOptions & {
|
type WakuRLNEncoderOptions = WakuEncoderOptions & {
|
||||||
credentials: EncryptedCredentials | DecryptedCredentials;
|
credentials: EncryptedCredentials | DecryptedCredentials;
|
||||||
};
|
};
|
||||||
|
|
||||||
export class RLNInstance {
|
export class RLNInstance extends RLNCredentialsManager {
|
||||||
private started = false;
|
|
||||||
private starting = false;
|
|
||||||
|
|
||||||
private _contract: undefined | RLNContract;
|
|
||||||
private _signer: undefined | ethers.Signer;
|
|
||||||
|
|
||||||
private keystore = Keystore.create();
|
|
||||||
private _credentials: undefined | DecryptedCredentials;
|
|
||||||
|
|
||||||
public constructor(public zerokit: Zerokit) {}
|
|
||||||
|
|
||||||
public get contract(): undefined | RLNContract {
|
|
||||||
return this._contract;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get signer(): undefined | ethers.Signer {
|
|
||||||
return this._signer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async start(options: StartRLNOptions = {}): Promise<void> {
|
|
||||||
if (this.started || this.starting) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.starting = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { credentials, keystore } =
|
|
||||||
await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
|
|
||||||
const { signer, address, rateLimit } = await this.determineStartOptions(
|
|
||||||
options,
|
|
||||||
credentials
|
|
||||||
);
|
|
||||||
|
|
||||||
if (keystore) {
|
|
||||||
this.keystore = keystore;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._credentials = credentials;
|
|
||||||
this._signer = signer!;
|
|
||||||
this._contract = await RLNContract.init(this, {
|
|
||||||
address: address!,
|
|
||||||
signer: signer!,
|
|
||||||
rateLimit: rateLimit ?? this.zerokit.getRateLimit
|
|
||||||
});
|
|
||||||
this.started = true;
|
|
||||||
} finally {
|
|
||||||
this.starting = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private async determineStartOptions(
|
|
||||||
options: StartRLNOptions,
|
|
||||||
credentials: KeystoreEntity | undefined
|
|
||||||
): Promise<StartRLNOptions> {
|
|
||||||
let chainId = credentials?.membership.chainId;
|
|
||||||
const address =
|
|
||||||
credentials?.membership.address ||
|
|
||||||
options.address ||
|
|
||||||
LINEA_CONTRACT.address;
|
|
||||||
|
|
||||||
if (address === LINEA_CONTRACT.address) {
|
|
||||||
chainId = LINEA_CONTRACT.chainId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const signer = options.signer || (await extractMetaMaskSigner());
|
|
||||||
const currentChainId = await signer.getChainId();
|
|
||||||
|
|
||||||
if (chainId && chainId !== currentChainId) {
|
|
||||||
throw Error(
|
|
||||||
`Failed to start RLN contract, chain ID of contract is different from current one: contract-${chainId}, current network-${currentChainId}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
signer,
|
|
||||||
address
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async decryptCredentialsIfNeeded(
|
|
||||||
credentials?: EncryptedCredentials | DecryptedCredentials
|
|
||||||
): Promise<{ credentials?: DecryptedCredentials; keystore?: Keystore }> {
|
|
||||||
if (!credentials) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("identity" in credentials) {
|
|
||||||
return { credentials };
|
|
||||||
}
|
|
||||||
|
|
||||||
const keystore = Keystore.fromString(credentials.keystore);
|
|
||||||
|
|
||||||
if (!keystore) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const decryptedCredentials = await keystore.readCredential(
|
|
||||||
credentials.id,
|
|
||||||
credentials.password
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
keystore,
|
|
||||||
credentials: decryptedCredentials
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async registerMembership(
|
|
||||||
options: RegisterMembershipOptions
|
|
||||||
): Promise<undefined | DecryptedCredentials> {
|
|
||||||
if (!this.contract) {
|
|
||||||
throw Error("RLN Contract is not initialized.");
|
|
||||||
}
|
|
||||||
|
|
||||||
let identity = "identity" in options && options.identity;
|
|
||||||
|
|
||||||
if ("signature" in options) {
|
|
||||||
identity = this.zerokit.generateSeededIdentityCredential(
|
|
||||||
options.signature
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!identity) {
|
|
||||||
throw Error("Missing signature or identity to register membership.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.contract.registerWithIdentity(identity);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes credentials in use by relying on provided Keystore earlier in rln.start
|
* Create an instance of RLN
|
||||||
* @param id: string, hash of credentials to select from Keystore
|
* @returns RLNInstance
|
||||||
* @param password: string or bytes to use to decrypt credentials from Keystore
|
|
||||||
*/
|
*/
|
||||||
public async useCredentials(id: string, password: Password): Promise<void> {
|
public static async create(): Promise<RLNInstance> {
|
||||||
this._credentials = await this.keystore?.readCredential(id, password);
|
try {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
await (init as any)?.();
|
||||||
|
zerokitRLN.init_panic_hook();
|
||||||
|
|
||||||
|
const witnessCalculator = await RLNInstance.loadWitnessCalculator();
|
||||||
|
const zkey = await RLNInstance.loadZkey();
|
||||||
|
|
||||||
|
const stringEncoder = new TextEncoder();
|
||||||
|
const vkey = stringEncoder.encode(JSON.stringify(verificationKey));
|
||||||
|
|
||||||
|
const DEPTH = 20;
|
||||||
|
const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
|
||||||
|
const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT);
|
||||||
|
|
||||||
|
return new RLNInstance(zerokit);
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Failed to initialize RLN:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private constructor(public zerokit: Zerokit) {
|
||||||
|
super(zerokit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createEncoder(
|
public async createEncoder(
|
||||||
@ -251,7 +67,7 @@ export class RLNInstance {
|
|||||||
): Promise<RLNEncoder> {
|
): Promise<RLNEncoder> {
|
||||||
const { credentials: decryptedCredentials } =
|
const { credentials: decryptedCredentials } =
|
||||||
await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
|
await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
|
||||||
const credentials = decryptedCredentials || this._credentials;
|
const credentials = decryptedCredentials || this.credentials;
|
||||||
|
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
throw Error(
|
throw Error(
|
||||||
@ -269,33 +85,6 @@ export class RLNInstance {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async verifyCredentialsAgainstContract(
|
|
||||||
credentials: KeystoreEntity
|
|
||||||
): Promise<void> {
|
|
||||||
if (!this._contract) {
|
|
||||||
throw Error(
|
|
||||||
"Failed to verify chain coordinates: no contract initialized."
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const registryAddress = credentials.membership.address;
|
|
||||||
const currentRegistryAddress = this._contract.address;
|
|
||||||
if (registryAddress !== currentRegistryAddress) {
|
|
||||||
throw Error(
|
|
||||||
`Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const chainId = credentials.membership.chainId;
|
|
||||||
const network = await this._contract.provider.getNetwork();
|
|
||||||
const currentChainId = network.chainId;
|
|
||||||
if (chainId !== currentChainId) {
|
|
||||||
throw Error(
|
|
||||||
`Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public createDecoder(
|
public createDecoder(
|
||||||
contentTopic: ContentTopic
|
contentTopic: ContentTopic
|
||||||
): RLNDecoder<IDecodedMessage> {
|
): RLNDecoder<IDecodedMessage> {
|
||||||
@ -304,4 +93,47 @@ export class RLNInstance {
|
|||||||
decoder: createDecoder(contentTopic)
|
decoder: createDecoder(contentTopic)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async loadWitnessCalculator(): Promise<WitnessCalculator> {
|
||||||
|
try {
|
||||||
|
const url = new URL("./resources/rln.wasm", import.meta.url);
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to fetch witness calculator: ${response.status} ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await wc.builder(
|
||||||
|
new Uint8Array(await response.arrayBuffer()),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Error loading witness calculator:", error);
|
||||||
|
throw new Error(
|
||||||
|
`Failed to load witness calculator: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static async loadZkey(): Promise<Uint8Array> {
|
||||||
|
try {
|
||||||
|
const url = new URL("./resources/rln_final.zkey", import.meta.url);
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Failed to fetch zkey: ${response.status} ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Uint8Array(await response.arrayBuffer());
|
||||||
|
} catch (error) {
|
||||||
|
log.error("Error loading zkey:", error);
|
||||||
|
throw new Error(
|
||||||
|
`Failed to load zkey: ${error instanceof Error ? error.message : String(error)}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user