Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/plonk #47

Merged
merged 17 commits into from
Nov 7, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,034 changes: 1,060 additions & 1,974 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@solarity/hardhat-zkit",
"version": "0.4.12",
"version": "0.5.0-rc.0",
"description": "The ultimate TypeScript environment for Circom development",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down Expand Up @@ -59,8 +59,8 @@
},
"dependencies": {
"@distributedlab/circom-parser": "0.2.0",
"@solarity/zkit": "0.2.6",
"@solarity/zktype": "0.3.1",
"@solarity/zkit": "0.3.0",
"@solarity/zktype": "0.4.0-rc.0",
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
"@wasmer/wasi": "0.12.0",
"chalk": "4.1.2",
"cli-progress": "3.12.0",
Expand Down
72 changes: 58 additions & 14 deletions src/artifacts/CircuitArtifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import { replaceBackslashes } from "hardhat/utils/source-names";
import { ERRORS } from "hardhat/internal/core/errors-list";
import { HardhatError, NomicLabsHardhatPluginError } from "hardhat/internal/core/errors";

import { ProvingSystemType } from "@solarity/zkit";

import { HardhatZKitError } from "../errors";
import { CIRCUIT_ARTIFACTS_SUFFIX } from "../constants";
import { Reporter } from "../reporter";
Expand Down Expand Up @@ -34,6 +36,22 @@ export class CircuitArtifacts implements ICircuitArtifacts {

constructor(private readonly _artifactsPath: string) {}

/**
* Generates a unique artifact file key using the specified {@link ArtifactsFileType | fileType}
* and {@link ProvingSystemType | provingSystem}
*
* @param fileType The type of the artifact file
* @param provingSystem The type of the proving system
* @returns A generated key for the artifact file
*/
public static getArtifactOutputFileKey(fileType: ArtifactsFileType, provingSystem: ProvingSystemType): string {
if (fileType === "zkey" || fileType === "vkey") {
return `${provingSystem}.${fileType}`;
}

return fileType;
}

/**
* Retrieves a {@link CircuitArtifact} object based on the provided short name or fully qualified name
*
Expand Down Expand Up @@ -141,18 +159,25 @@ export class CircuitArtifacts implements ICircuitArtifacts {

/**
* Constructs and returns the full path for a specific artifact file based on the provided
* {@link CircuitArtifact} object and the specified {@link ArtifactsFileType | file type}
* {@link CircuitArtifact} object, the specified {@link ArtifactsFileType | file type}
* and {@link ProvingSystemType | proving system type}.
*
* The {@link ProvingSystemType | provingSystem} parameter has `groth16` value by default
*
* @param circuitArtifact The {@link CircuitArtifact} object representing the artifact
* @param fileType The {@link ArtifactsFileType | file type} indicating the type of artifact file
* for which to retrieve the path
* @returns The full path of the specified artifact file associated with the provided {@link CircuitArtifact} object
*/
public getCircuitArtifactFileFullPath(circuitArtifact: CircuitArtifact, fileType: ArtifactsFileType): string {
public getCircuitArtifactFileFullPath(
circuitArtifact: CircuitArtifact,
fileType: ArtifactsFileType,
provingSystem: ProvingSystemType = "groth16",
): string {
return path.join(
this._artifactsPath,
circuitArtifact.circuitSourceName,
this._getOutputFileSourcePath(circuitArtifact.circuitTemplateName, fileType),
this._getOutputFileSourcePath(circuitArtifact.circuitTemplateName, fileType, provingSystem),
);
}

Expand All @@ -162,24 +187,39 @@ export class CircuitArtifacts implements ICircuitArtifacts {
* @param circuitArtifact The {@link CircuitArtifact} object to be saved
* @param updatedFileTypes An array of {@link ArtifactsFileType | file types} that have been modified
* during the most recent session, such as during compilation
* @param provingSystems An array of {@link ProvingSystemType | proving systems} that have been added
* during the most recent session
* @returns A promise that resolves once the save operation is complete
*/
public async saveCircuitArtifact(circuitArtifact: CircuitArtifact, updatedFileTypes: ArtifactsFileType[]) {
public async saveCircuitArtifact(
circuitArtifact: CircuitArtifact,
updatedFileTypes: ArtifactsFileType[],
provingSystems: ProvingSystemType[],
) {
const fullyQualifiedName = this.getCircuitFullyQualifiedName(
circuitArtifact.circuitSourceName,
circuitArtifact.circuitTemplateName,
);

const artifactPath = this.formCircuitArtifactPathFromFullyQualifiedName(fullyQualifiedName);

// Updates the data for files that have been recently modified
for (const fileType of updatedFileTypes) {
const fileSourcePath: string = this.getCircuitArtifactFileFullPath(circuitArtifact, fileType);
const allArtifactProvingSystems = new Set<ProvingSystemType>([
...circuitArtifact.baseCircuitInfo.protocol,
...provingSystems,
]);

circuitArtifact.compilerOutputFiles[fileType] = {
fileSourcePath,
fileHash: getFileHash(fileSourcePath),
};
circuitArtifact.baseCircuitInfo.protocol = [...allArtifactProvingSystems];

// Updates the data for files that have been recently modified
for (const provingSystem of provingSystems) {
for (const fileType of updatedFileTypes) {
const fileSourcePath: string = this.getCircuitArtifactFileFullPath(circuitArtifact, fileType, provingSystem);

circuitArtifact.compilerOutputFiles[CircuitArtifacts.getArtifactOutputFileKey(fileType, provingSystem)] = {
fileSourcePath,
fileHash: getFileHash(fileSourcePath),
};
}
}

Reporter!.verboseLog("circuit-artifacts", "Saving circuit artifact: %o", [circuitArtifact]);
Expand Down Expand Up @@ -291,7 +331,11 @@ export class CircuitArtifacts implements ICircuitArtifacts {
return this.getCircuitFullyQualifiedName(sourceName, circuitName);
}

private _getOutputFileSourcePath(circuitTemplateName: string, fileType: ArtifactsFileType): string {
private _getOutputFileSourcePath(
circuitTemplateName: string,
fileType: ArtifactsFileType,
provingSystem: ProvingSystemType,
): string {
switch (fileType) {
case "wasm":
return path.join(`${circuitTemplateName}_js`, `${circuitTemplateName}.wasm`);
Expand All @@ -304,9 +348,9 @@ export class CircuitArtifacts implements ICircuitArtifacts {
case "json":
return `${circuitTemplateName}_constraints.json`;
case "vkey":
return `${circuitTemplateName}.vkey.json`;
return `${circuitTemplateName}.${provingSystem}.vkey.json`;
case "zkey":
return `${circuitTemplateName}.zkey`;
return `${circuitTemplateName}.${provingSystem}.zkey`;

default:
throw new HardhatZKitError(`Invalid artifacts file type ${fileType}`);
Expand Down
41 changes: 27 additions & 14 deletions src/cache/CircuitsSetupCache.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { isEqual } from "lodash";
import { ProvingSystemType } from "@solarity/zkit";

import { SetupCacheSchema } from "./schemas";
import { CIRCUIT_SETUP_CACHE_VERSION } from "../constants";

import { BaseCache } from "../cache/BaseCache";

import { SetupCacheEntry } from "../types/cache";
import { ContributionSettings } from "../types/core";
import { ProvingSystemData, SetupCacheEntry } from "../types/cache";
import { SetupContributionSettings } from "../types/core";

/**
* Class that implements the caching logic for setting up circuits.
Expand All @@ -31,29 +31,42 @@ class BaseCircuitsSetupCache extends BaseCache<SetupCacheEntry> {
*
* @param artifactAbsolutePath The absolute path of the artifact file to check
* @param r1csContentHash The content hash of the R1CS file to compare
* @param contributionSettings The contribution settings to compare
* @returns True if the file has changed, false otherwise.
* @param contributionSettings The setup contribution settings to compare
* @returns An array of {@link ProvingSystemType | proving systems} that were modified or required for setup
*/
public hasFileChanged(
artifactAbsolutePath: string,
r1csContentHash: string,
contributionSettings: ContributionSettings,
): boolean {
contributionSettings: SetupContributionSettings,
): ProvingSystemType[] {
const cacheEntry = this.getEntry(artifactAbsolutePath);

if (cacheEntry === undefined) {
return true;
return contributionSettings.provingSystems;
}

if (cacheEntry.r1csContentHash !== r1csContentHash) {
return true;
}
const obsoleteProvingSystems: ProvingSystemType[] = [];

for (const provingSystem of contributionSettings.provingSystems) {
const provingSystemData: ProvingSystemData | undefined = cacheEntry.provingSystemsData.find(
(data: ProvingSystemData) => data.provingSystem === provingSystem,
);

if (!provingSystemData) {
obsoleteProvingSystems.push(provingSystem);

continue;
}

if (!isEqual(cacheEntry.contributionSettings, contributionSettings)) {
return true;
if (
provingSystemData.lastR1CSFileHash !== r1csContentHash ||
(provingSystem === "groth16" && cacheEntry.contributionsNumber !== contributionSettings.contributions)
) {
obsoleteProvingSystems.push(provingSystem);
}
}

return false;
return obsoleteProvingSystems;
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/cache/schemas/setup-schemas.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { z } from "zod";

export const ProvingSystemTypeSchema = z.literal("groth16");
export const ProvingSystemTypeSchema = z.literal("groth16").or(z.literal("plonk"));

export const ContributionSettingsSchema = z.object({
export const ProvingSystemDataSchema = z.object({
provingSystem: ProvingSystemTypeSchema,
contributions: z.number(),
lastR1CSFileHash: z.string(),
});

export const SetupCacheEntrySchema = z.object({
circuitSourceName: z.string(),
r1csContentHash: z.string(),
r1csSourcePath: z.string(),
contributionSettings: ContributionSettingsSchema,
provingSystemsData: ProvingSystemDataSchema.array(),
contributionsNumber: z.number(),
});

export const SetupCacheSchema = z.object({
Expand Down
2 changes: 1 addition & 1 deletion src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const defaultConfig: ZKitConfig = {
setupSettings: {
contributionSettings: {
provingSystem: "groth16",
contributions: 1,
contributions: 2,
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
},
ptauDir: undefined,
ptauDownload: true,
Expand Down
5 changes: 5 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export const BYTES_IN_MB = 1048576;
export const MAX_PTAU_ID = 27;
export const PTAU_FILE_REG_EXP = /^(?:.+-|)(\d{1,2}).ptau$/;

export const PROVING_SYSTEM_CONSTRAINTS_MULTIPLIERS: { [key: string]: number } = {
groth16: 1,
plonk: 11,
};

export const CIRCOM_FILE_REG_EXP = /\w+\.circom/;

export const NODE_MODULES_REG_EXP = /^node_modules\//;
Expand Down
26 changes: 15 additions & 11 deletions src/core/compile/CompilationProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { v4 as uuid } from "uuid";

import { HardhatRuntimeEnvironment } from "hardhat/types";

import { CircomCompilerFactory, createCircomCompilerFactory } from "../compiler";
import { ProvingSystemType } from "@solarity/zkit";

import { CircomCompilerFactory, createCircomCompilerFactory, getHighestVersion, isVersionValid } from "../compiler";
import { HardhatZKitError } from "../../errors";
import { CIRCUIT_ARTIFACT_VERSION, NODE_MODULES } from "../../constants";
import { Reporter } from "../../reporter";

import { getHighestVersion, isVersionValid } from "../compiler/versioning";
import { getNormalizedFullPath, renameFilesRecursively, readDirRecursively } from "../../utils/path-utils";

import { ZKitConfig } from "../../types/zkit-config";
Expand Down Expand Up @@ -67,8 +67,9 @@ export class CompilationProcessor {
* 6. Saves the artifact information using {@link ICircuitArtifacts | CircuitArtifacts}
*
* @param filesInfoToCompile Information about circuit files needed for compilation
* @param provingSystems An array of {@link ProvingSystemType | proving systems} from the plugin config
*/
public async compile(filesInfoToCompile: CircomResolvedFileInfo[]) {
public async compile(filesInfoToCompile: CircomResolvedFileInfo[], provingSystems: ProvingSystemType[]) {
Arvolear marked this conversation as resolved.
Show resolved Hide resolved
const tempDir: string = path.join(os.tmpdir(), ".zkit", uuid());

try {
Expand Down Expand Up @@ -109,7 +110,7 @@ export class CompilationProcessor {

await this._moveFromTempDirToArtifacts(compilationInfoArr);

await this._emitArtifacts(compilationInfoArr);
await this._emitArtifacts(compilationInfoArr, provingSystems);

Reporter!.reportCompilationResult(compilationInfoArr);
} finally {
Expand Down Expand Up @@ -167,7 +168,7 @@ export class CompilationProcessor {
}
}

private async _emitArtifacts(compilationInfoArr: CompilationInfo[]) {
private async _emitArtifacts(compilationInfoArr: CompilationInfo[], provingSystems: ProvingSystemType[]) {
for (const info of compilationInfoArr) {
const fullyQualifiedName: string = this._circuitArtifacts.getCircuitFullyQualifiedName(
info.resolvedFile.sourceName,
Expand All @@ -185,6 +186,7 @@ export class CompilationProcessor {
circuitFileName: info.circuitFileName,
circuitSourceName: info.resolvedFile.sourceName,
baseCircuitInfo: {
protocol: [],
constraintsNumber: 0,
signals: [],
},
Expand All @@ -196,12 +198,14 @@ export class CompilationProcessor {
throw new HardhatZKitError("Unable to emit artifacts for resolved file without main component data");
}

circuitArtifact.baseCircuitInfo = {
constraintsNumber: info.constraintsNumber,
signals: info.resolvedFile.fileData.mainComponentData.signals,
};
circuitArtifact.baseCircuitInfo.constraintsNumber = info.constraintsNumber;
circuitArtifact.baseCircuitInfo.signals = info.resolvedFile.fileData.mainComponentData.signals;

await this._circuitArtifacts.saveCircuitArtifact(circuitArtifact, this._getUpdatedArtifactFileTypes());
await this._circuitArtifacts.saveCircuitArtifact(
circuitArtifact,
this._getUpdatedArtifactFileTypes(),
provingSystems,
);
}
}

Expand Down
1 change: 0 additions & 1 deletion src/core/compile/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from "./CompilationFilesResolver";
export * from "./CompilationProcessor";
export * from "./TypeGenerationProcessor";
3 changes: 3 additions & 0 deletions src/core/compiler/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from "./CircomCompiler";
export * from "./CircomCompilerFactory";
export * from "./CircomCompilerDownloader";

export * from "./versioning";
2 changes: 2 additions & 0 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ export * from "./compile";
export * from "./compiler";
export * from "./setup";
export * from "./dependencies";
export * from "./zktype/TypeGenerationProcessor";
export * from "./zkit/CircuitZKitBuilder";
export * from "./utils/PtauDownloader";
Loading
Loading