Merge pull request #87 from numtel/custom_templates

Auto-detect pragma custom_templates for main component instantiation
This commit is contained in:
Erhan
2024-08-05 22:47:39 +03:00
committed by GitHub
13 changed files with 76 additions and 13 deletions

5
.gitignore vendored
View File

@@ -112,4 +112,7 @@ dist
# Hardhat files
/cache
/artifacts
/artifacts
# test inputs
input.test.json

View File

@@ -6,6 +6,7 @@ module.exports = {
rootDir: './tests',
globalTeardown: '<rootDir>/hooks/teardown.js',
forceExit: true,
detectOpenHandles: true,
transform: {
'^.+\\.test.(ts|js)$': [
'ts-jest',

View File

@@ -1,6 +1,6 @@
{
"name": "circomkit",
"version": "0.2.1",
"version": "0.2.2",
"description": "A Circom testing & development environment",
"author": "erhant",
"license": "MIT",

View File

@@ -235,6 +235,15 @@ export class Circomkit {
};
}
const circomSource = readFileSync(`${this.config.dirCircuits}/${circuitConfig.file}.circom`, 'utf8');
// TODO: do we need regex here?
const usesCustomTemplates =
circuitConfig.usesCustomTemplates ??
circomSource
.replace(/\/\/.*|\/\*[\s\S]*?\*\//g, '') // remove single and multi-line comments
.includes('pragma custom_templates;');
// directory to output the file
const directory = circuitConfig.dir || 'test';
@@ -246,13 +255,14 @@ export class Circomkit {
file = '../'.repeat(filePrefixMatches.length) + file;
}
const config = {
const config: Required<CircuitConfig> = {
file: file,
template: circuitConfig.template,
version: circuitConfig.version || '2.0.0',
dir: directory,
pubs: circuitConfig.pubs || [],
params: circuitConfig.params || [],
usesCustomTemplates,
};
const targetDir = `${this.config.dirCircuits}/${directory}`;

View File

@@ -67,10 +67,11 @@ export function instantiateCircuit(config: Required<CircuitConfig>, targetDir: s
*
* **Be very careful when editing this file.** */
export function makeCircuit(config: Required<CircuitConfig>) {
const {version, file, pubs, template, params} = config;
const {version, usesCustomTemplates, file, pubs, template, params} = config;
return `// auto-generated by circomkit
pragma circom ${version};
${usesCustomTemplates ? 'pragma custom_templates;\n' : ''}
include "../${file}.circom";
component main${pubs.length === 0 ? '' : ' {public[' + pubs.join(', ') + ']}'} = ${template}(${params.join(', ')});

View File

@@ -44,6 +44,8 @@ export type CircuitConfig = {
pubs?: string[];
/** An array of template parameters, defaults to `[]` */
params?: (number | bigint)[];
/** Include `pragma custom_templates;` in instantiation */
usesCustomTemplates?: boolean;
};
/**

View File

@@ -9,5 +9,9 @@
"template": "Arrays",
"params": [2, 3],
"pubs": ["in1D", "in2D"]
},
"uses_custom_templates": {
"file": "custom_templates",
"template": "MyTest"
}
}

View File

@@ -0,0 +1,15 @@
pragma circom 2.1.0;
pragma custom_templates;
template custom Example() {
// custom template's code
}
template MyTest() {
signal input in;
signal output out;
component example = Example(); // instantiation of the custom template
out <== in * 2;
}

View File

@@ -0,0 +1,7 @@
// auto-generated by circomkit
pragma circom 2.1.0;
pragma custom_templates;
include "../custom_templates.circom";
component main = MyTest();

View File

@@ -0,0 +1,6 @@
// auto-generated by circomkit
pragma circom 2.0.0;
include "../multiplier.circom";
component main = Multiplier(3);

View File

@@ -63,6 +63,6 @@ export function prepareMultiplier(N: number, order: bigint = primes['bn128']) {
return {
signals,
circuit: {name, config, size, exact: true},
inputName: 'test-input',
inputName: 'input.test',
} as PreparedTestCircuit<typeof signals>;
}

View File

@@ -78,6 +78,27 @@ describe('configuring the C witness generator', () => {
});
});
describe('compiling circuits with custom_templates', () => {
const CONFIG = {
verbose: false,
logLevel: 'silent',
dirPtau: './tests/ptau',
dirInputs: './tests/inputs',
dirBuild: './tests/build',
dirCircuits: './tests/circuits',
circuits: './tests/circuits.json',
} as const;
const CIRCUIT_NAME = 'uses_custom_templates';
it('should compile correctly', async () => {
const circomkit = new Circomkit({...CONFIG});
const outPath = await circomkit.compile(CIRCUIT_NAME);
expect(existsSync(`${outPath}/${CIRCUIT_NAME}_js`)).toBe(true);
rmSync(`${outPath}/${CIRCUIT_NAME}_js`, {recursive: true});
});
});
describe('compiling under different directories', () => {
const cases = [
{

View File

@@ -1,7 +0,0 @@
{
"in": [
"13120588690839840455",
"3282839366351600067",
"6893074686771429291"
]
}