Skip to content

Implement zkit wrapper generation for given circuits #4

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

Merged
merged 22 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e65d179
Fixed a bug related to: Array could have any number of dimensions (e.…
KyrylR Jun 25, 2024
041c738
Updated versions and CHANGELOG.md
KyrylR Jun 25, 2024
0cac0c5
Refactored architecture to work as a library
KyrylR Jun 27, 2024
71b1828
Implemented Zkit wrapper generation for given circuits
KyrylR Jun 27, 2024
f153cf8
Moved to node and mocha
KyrylR Jun 28, 2024
ea5a152
Used ejs instead of ts factory to render the wrapper class
KyrylR Jun 28, 2024
6462b15
Added test to check proof generation and verification
KyrylR Jun 28, 2024
e941bca
Updated project structure
KyrylR Jun 28, 2024
0ae192d
Added generation of the hardhat runtime extension file for circuits
KyrylR Jun 28, 2024
a39f3c2
Added a helper function to return the circuit object from given name
KyrylR Jun 28, 2024
aca16d9
Changed the ArtifactGeneratorConfig to accept an array of paths to ci…
KyrylR Jun 28, 2024
04ac182
Updated CHANGELOG.md
KyrylR Jun 28, 2024
80e0b0b
Resolved an issue where inputs could have the wrong number of dimensions
KyrylR Jun 28, 2024
93f0811
Fixed tests
KyrylR Jun 28, 2024
f2455fa
Updated CHANGELOG.md
KyrylR Jun 28, 2024
5a95e88
Updated deps
KyrylR Jun 28, 2024
78c4797
Fixed tests
KyrylR Jun 28, 2024
17a698e
Updated JSDoc
KyrylR Jun 28, 2024
4d42041
Added circuit types Hardhat definition generation of all possible cir…
KyrylR Jul 2, 2024
476683d
Updated package.json
KyrylR Jul 2, 2024
bbee0de
Updated README
KyrylR Jul 2, 2024
603ab9e
Deleted automatic artifacts clean up
KyrylR Jul 2, 2024
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
14 changes: 9 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
# Changelog

All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v0.2.0]

## [Unreleased]
- Resolved an issue where arrays might have multiple dimensions, such as `bigint[][][]`.
- Refactored architecture to work as a library
- Deleted support for standalone run
- Added ability to specify where the circuit's AST files are stored
- Added ability to specify where to put generated artifacts and types
- Implemented Zkit wrapper generation for given circuits

## [v0.1.1]

### Added

- Initial release of the ZKType package
- Support for generating TypeScript bindings for Circom circuits

[Unreleased]: https://github.com/dl-solarity/zktype/compare/master...develop
30 changes: 0 additions & 30 deletions bin/zktype.ts

This file was deleted.

Binary file modified bun.lockb
Binary file not shown.
4 changes: 3 additions & 1 deletion bunfig.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[test]
coverage = true
coverage = false
coverageThreshold = { lines = 0.95, functions = 0.95 }

coverageReporter = ["text", "lcov"]
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
{
"name": "@solarity/zktype",
"version": "0.1.1",
"version": "0.2.0",
"description": "Unleash TypeScript bindings for Circom circuits",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
"bin": "dist/bin/zktype.js",
"engines": {
"node": ">=18"
},
Expand Down Expand Up @@ -41,10 +40,11 @@
"homepage": "https://github.com/dl-solarity/zktype#readme",
"dependencies": {
"@distributedlab/circom2": "0.2.18-rc.2",
"commander": "12.0.0",
"please-upgrade-node": "3.2.0",
"typescript": "5.4.5"
},
"peerDependencies": {
"@solarity/zkit": "^0.2.0"
},
"devDependencies": {
"@types/bun": "^1.0.12",
"circomlib": "^2.0.5",
Expand Down
79 changes: 0 additions & 79 deletions src/cli.ts

This file was deleted.

16 changes: 5 additions & 11 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { CircuitProcessorConfig } from "./types";
import { ZKTypeConfig } from "./types";

export const defaultCircuitProcessorConfig: CircuitProcessorConfig = {
defaultFolder: "circuits",
skip: [],
only: [],
strict: false,
clean: true,
quiet: false,
};

export const defaultCircuitArtifactGeneratorConfig = {
export const defaultCircuitArtifactGeneratorConfig: ZKTypeConfig = {
inputDir: "circuits",
outputArtifactsDir: "artifacts/circuits",
outputTypesDir: "generated-types/circuits",
clean: true,
};
5 changes: 2 additions & 3 deletions src/constants/circom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ export enum SignalVisibilityNames {
Private = "private",
}

// FIXME: Array could have any number of dimensions (e.g. bigint[2][3][4]...)
export enum InternalType {
BigInt = "bigint",
BigIntArray = "bigint[]",
BigInt = "<number-like>",
BigIntArray = "<array-like>",
}
77 changes: 38 additions & 39 deletions src/core/CircuitArtifactGenerator.ts
Original file line number Diff line number Diff line change
@@ -1,86 +1,86 @@
import fs from "fs";
import path from "path";

import CircuitProcessor from "./CircuitProcessor";
import CircuitASTGenerator from "./CircuitASTGenerator";

import { findProjectRoot } from "../utils";

import { defaultCircuitProcessorConfig } from "../config";
import { findCommonPath, findProjectRoot } from "../utils";

import { InternalType, SignalTypeNames, SignalVisibilityNames } from "../constants";
import {
Stmt,
Signal,
Template,
CircuitAST,
SignalType,
Declaration,
CircuitArtifact,
SignalVisibility,
CircomCompilerOutput,
CircuitProcessorConfig,
CircuitArtifactGeneratorConfig,
Template,
ArtifactGeneratorConfig,
} from "../types";

/**
* `CircuitArtifactGenerator` is responsible for generating circuit artifacts based on the ASTs generated by the `CircuitASTGenerator`.
* `CircuitArtifactGenerator` is responsible for generating circuit artifacts based on the AST files.
*
* The artifact is a JSON file which can be used further in the pipeline for type generation, strict typing natively by TypeScript, etc.
* If the format of the artifact changes, the `CURRENT_FORMAT` constant should be updated for backward compatibility.
*
* This class mainly parses and validates the generated AST JSONs. Validation is needed to ensure that the generated AST files meet expectations and necessary
* fields exist.
* @todo Consider using a class for filtering which circuits to compile for caching purposes.
*/
export default class CircuitArtifactGenerator {
/**
* The directory where the generated artifacts will be stored.
*/
public static readonly ARTIFACTS_DIR: string = "artifacts/circuits";

/**
* The current format version of the circuit artifact.
*/
public static readonly CURRENT_FORMAT: string = "zktype-circom-artifact-1";

private readonly _projectRoot: string;
private readonly _circuitArtifactGeneratorConfig: CircuitArtifactGeneratorConfig;

private readonly _circuitPreprocessor: CircuitProcessor;
private readonly _circuitArtifactGeneratorConfig: ArtifactGeneratorConfig;

/**
* Creates an instance of CircuitArtifactGenerator.
* @param {CircuitArtifactGeneratorConfig} circuitArtifactGeneratorConfig - The configuration for the `CircuitArtifactGenerator`.
* @param {CircuitProcessorConfig} [circuitProcessorConfig=defaultCircuitProcessorConfig] - The configuration for the `CircuitProcessor`.
* @param {ArtifactGeneratorConfig} circuitArtifactGeneratorConfig - The configuration for the `CircuitArtifactGenerator`.
*/
constructor(
circuitArtifactGeneratorConfig: CircuitArtifactGeneratorConfig,
circuitProcessorConfig: CircuitProcessorConfig = defaultCircuitProcessorConfig,
) {
constructor(circuitArtifactGeneratorConfig: ArtifactGeneratorConfig) {
this._projectRoot = findProjectRoot(process.cwd());
this._circuitArtifactGeneratorConfig = circuitArtifactGeneratorConfig;

this._circuitPreprocessor = new CircuitProcessor(circuitProcessorConfig);
}

/**
* Generates circuit artifacts based on the ASTs.
*/
public async generateCircuitArtifacts(): Promise<void> {
await this._circuitPreprocessor.processCircuits();

const astFilePaths = this._fetchASTFilePaths();

if (this._circuitArtifactGeneratorConfig.clean) {
this._cleanArtifacts();
}

let commonPath = "";
const artifactsToSave: CircuitArtifact[] = [];

for (const astFilePath of astFilePaths) {
const circuitArtifact = await this._extractArtifact(astFilePath);

this._saveArtifact(circuitArtifact);
artifactsToSave.push(circuitArtifact);

commonPath = findCommonPath(commonPath, circuitArtifact.sourceName);
}

artifactsToSave.forEach((circuitArtifact) =>
this._saveArtifact(
{
...circuitArtifact,
basePath: commonPath,
},
commonPath,
),
);
}

/**
* Returns the configuration of the `CircuitArtifactGenerator`.
*/
public getOutputArtifactsDir(): string {
return this._circuitArtifactGeneratorConfig.outputArtifactsDir ?? "artifacts/circuits";
}

/**
Expand All @@ -91,7 +91,7 @@ export default class CircuitArtifactGenerator {
* @returns {string[]} An array of file paths.
*/
private _fetchASTFilePaths(): string[] {
const files = fs.readdirSync(CircuitASTGenerator.TEMP_DIR, { recursive: true });
const files = fs.readdirSync(this._circuitArtifactGeneratorConfig.inputDir, { recursive: true });

const astFiles: string[] = [];

Expand All @@ -118,7 +118,7 @@ export default class CircuitArtifactGenerator {
*/
private async _extractArtifact(pathToTheAST: string): Promise<CircuitArtifact> {
const ast: CircuitAST = JSON.parse(
fs.readFileSync(path.resolve(CircuitASTGenerator.TEMP_DIR, pathToTheAST), "utf-8"),
fs.readFileSync(path.resolve(this._circuitArtifactGeneratorConfig.inputDir, pathToTheAST), "utf-8"),
);

this._validateCircuitAST(ast);
Expand All @@ -127,6 +127,7 @@ export default class CircuitArtifactGenerator {
_format: CircuitArtifactGenerator.CURRENT_FORMAT,
circuitName: ast.circomCompilerOutput[0].main_component![1].Call.id,
sourceName: ast.sourcePath,
basePath: "",
compilerVersion: ast.circomCompilerOutput[0].compiler_version.join("."),
signals: [],
};
Expand All @@ -147,6 +148,7 @@ export default class CircuitArtifactGenerator {
internalType: this._getInternalType(statement.InitializationBlock.initializations[0].Declaration),
visibility: this._getSignalVisibility(ast.circomCompilerOutput[0], statement),
name: statement.InitializationBlock.initializations[0].Declaration.name,
dimensions: statement.InitializationBlock.initializations[0].Declaration.dimensions.length,
};

circuitArtifact.signals.push(signal);
Expand All @@ -159,14 +161,11 @@ export default class CircuitArtifactGenerator {
* Saves the circuit artifact to a JSON file.
*
* @param {CircuitArtifact} artifact - The circuit artifact to be saved.
* @param commonPath - The common path of the circuit artifacts.
*/
private _saveArtifact(artifact: CircuitArtifact): void {
private _saveArtifact(artifact: CircuitArtifact, commonPath: string = ""): void {
const circuitArtifactPath = path
.join(
this._projectRoot,
CircuitArtifactGenerator.ARTIFACTS_DIR,
artifact.sourceName.replace(this._circuitPreprocessor.getDefaultFolder(), ""),
)
.join(this._projectRoot, this.getOutputArtifactsDir(), artifact.sourceName.replace(commonPath, ""))
.replace(path.extname(artifact.sourceName), ".json");

fs.mkdirSync(circuitArtifactPath.replace(path.basename(circuitArtifactPath), ""), { recursive: true });
Expand All @@ -178,7 +177,7 @@ export default class CircuitArtifactGenerator {
* Cleans the artifacts directory by removing all files and subdirectories.
*/
private _cleanArtifacts(): void {
const artifactsDir = path.join(this._projectRoot, CircuitArtifactGenerator.ARTIFACTS_DIR);
const artifactsDir = path.join(this._projectRoot, this.getOutputArtifactsDir());

if (fs.existsSync(artifactsDir)) {
fs.rmSync(artifactsDir, { recursive: true, force: true });
Expand Down
Loading
Loading