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

feat: noir_wasm compilation of noir programs #3272

Merged
merged 42 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
41413c5
stop committing artifacts
dan-aztec Nov 6, 2023
b2c5741
undo box artifact changes
dan-aztec Nov 6, 2023
9abd0ff
compile non-contract package types with noir-wasm-compiler.ts
dan-aztec Nov 6, 2023
b51c19a
revert "binary" to "bin"
dan-aztec Nov 6, 2023
e44955d
bin
dan-aztec Nov 6, 2023
fa43b73
revert to nargo for compiler
dan-aztec Nov 6, 2023
27c62b2
use types, still broken
dan-aztec Nov 6, 2023
ae7ef52
remove src/target from git
dan-aztec Nov 6, 2023
94d6399
handle non-contract return type
dan-aztec Nov 6, 2023
1473663
generate types
dan-aztec Nov 6, 2023
3a9bd7e
handle program differently from contract
dan-aztec Nov 7, 2023
d62887e
handle program and contract separately
dan-aztec Nov 7, 2023
cde221e
update test
dan-aztec Nov 7, 2023
d26d6ac
stop logging
dan-aztec Nov 7, 2023
d1b1d4e
fix type
dan-aztec Nov 7, 2023
c34bb69
switch command name to compile
dan-aztec Nov 7, 2023
c79086e
readd src/target for testing
dan-aztec Nov 7, 2023
d1f1ecb
point outdir to src/target
dan-aztec Nov 7, 2023
e655751
single build, and absoltue path to /src/target
dan-aztec Nov 7, 2023
7ebbf5d
merge conflicts
dan-aztec Nov 8, 2023
452b858
checkout origin/master barretenberg?
dan-aztec Nov 8, 2023
c635a05
fetch
dan-aztec Nov 8, 2023
e2c70da
Revert "checkout origin/master barretenberg?"
dan-aztec Nov 8, 2023
eae79ec
revert noir-protocol-circuits changes
dan-aztec Nov 8, 2023
cf82db1
origin not local
dan-aztec Nov 8, 2023
1f38e39
revert more protocol circuits changes
dan-aztec Nov 8, 2023
71ba52f
rename to compileNoir
dan-aztec Nov 14, 2023
0911592
Merge branch 'master' into dan/build-artifacts-ci-merge-conflicgt
dan-aztec Nov 14, 2023
955417e
update yarn command to compile
dan-aztec Nov 14, 2023
8efa75a
revert formatting
dan-aztec Nov 14, 2023
47b8c2b
Merge branch 'master' into dan/build-artifacts-ci-merge-conflicgt
dan-aztec Nov 16, 2023
af5832f
update compileContract name
dan-aztec Nov 16, 2023
eb6f46e
Merge branch 'master' into dan/build-artifacts-ci-merge-conflicgt
dan-aztec Nov 17, 2023
d7abdb5
merge conflict
dan-aztec Nov 18, 2023
c2659eb
small change to output json data
dan-aztec Nov 18, 2023
857101e
move generateTypescript logic out of noir-protocol-circuits
dan-aztec Nov 18, 2023
d3a51cc
write program types to ../types/
dan-aztec Nov 18, 2023
2dde02d
remove formatted deleted code
dan-aztec Nov 21, 2023
d2af58d
revert cpp format
dan-aztec Nov 21, 2023
d5ada69
revert package.json change
dan-aztec Nov 21, 2023
ac66988
formatting
dan-aztec Nov 21, 2023
b0be295
formatting
dan-aztec Nov 21, 2023
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
4 changes: 2 additions & 2 deletions yarn-project/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { JsonStringify } from '@aztec/foundation/json-rpc';
import { DebugLogger, LogFn } from '@aztec/foundation/log';
import { sleep } from '@aztec/foundation/sleep';
import { fileURLToPath } from '@aztec/foundation/url';
import { compileContract, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli';
import { compileNoir, generateNoirInterface, generateTypescriptInterface } from '@aztec/noir-compiler/cli';
import { CompleteAddress, ContractData, ExtendedNote, LogFilter } from '@aztec/types';

import { createSecp256k1PeerId } from '@libp2p/peer-id-factory';
Expand Down Expand Up @@ -740,7 +740,7 @@ export function getProgram(log: LogFn, debugLogger: DebugLogger): Command {
await update(projectPath, contract, options.rpcUrl, options.sandboxVersion, log, debugLogger);
});

compileContract(program, 'compile', log);
compileNoir(program, 'compile', log);
generateTypescriptInterface(program, 'generate-typescript', log);
generateNoirInterface(program, 'generate-noir-interface', log);

Expand Down
4 changes: 2 additions & 2 deletions yarn-project/noir-compiler/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createConsoleLogger } from '@aztec/foundation/log';

import { Command } from 'commander';

import { compileContract } from './cli/contract.js';
import { compileNoir } from './cli/compileNoir.js';
import { generateNoirInterface } from './cli/noir-interface.js';
import { generateTypescriptInterface } from './cli/typescript.js';

Expand All @@ -12,7 +12,7 @@ const log = createConsoleLogger('aztec:compiler-cli');

const main = async () => {
program.name('aztec-compile');
compileContract(program, 'contract', log);
compileNoir(program, 'compile', log);
generateTypescriptInterface(program, 'typescript', log);
generateNoirInterface(program, 'interface', log);
await program.parseAsync(process.argv);
Expand Down
145 changes: 145 additions & 0 deletions yarn-project/noir-compiler/src/cli/compileNoir.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { ContractArtifact } from '@aztec/foundation/abi';
import { LogFn } from '@aztec/foundation/log';

import { Command } from 'commander';
import { mkdirSync, writeFileSync } from 'fs';
import { mkdirpSync } from 'fs-extra';
import path, { resolve } from 'path';

import {
ProgramArtifact,
compileUsingNargo,
compileUsingNoirWasm,
generateNoirContractInterface,
generateTypescriptContractInterface,
generateTypescriptProgramInterface,
} from '../index.js';

/**
* CLI options for configuring behavior
*/
interface Options {
// eslint-disable-next-line jsdoc/require-jsdoc
outdir: string;
// eslint-disable-next-line jsdoc/require-jsdoc
typescript: string | undefined;
// eslint-disable-next-line jsdoc/require-jsdoc
interface: string | undefined;
// eslint-disable-next-line jsdoc/require-jsdoc
compiler: string | undefined;
}
/**
* Registers a 'contract' command on the given commander program that compiles an Aztec.nr contract project.
* @param program - Commander program.
* @param log - Optional logging function.
* @returns The program with the command registered.
*/
export function compileNoir(program: Command, name = 'compile', log: LogFn = () => {}): Command {
return program
.command(name)
.argument('<project-path>', 'Path to the bin or Aztec.nr project to compile')
.option('-o, --outdir <path>', 'Output folder for the binary artifacts, relative to the project path', 'target')
.option('-ts, --typescript <path>', 'Optional output folder for generating typescript wrappers', undefined)
.option('-i, --interface <path>', 'Optional output folder for generating an Aztec.nr contract interface', undefined)
.option('-c --compiler <string>', 'Which compiler to use. Either nargo or wasm. Defaults to nargo', 'wasm')
.description('Compiles the Noir Source in the target project')

.action(async (projectPath: string, options: Options) => {
const { compiler } = options;
if (typeof projectPath !== 'string') {
throw new Error(`Missing project path argument`);
}
if (compiler !== 'nargo' && compiler !== 'wasm') {
throw new Error(`Invalid compiler: ${compiler}`);
}

const compile = compiler === 'wasm' ? compileUsingNoirWasm : compileUsingNargo;
log(`Compiling ${projectPath} with ${compiler} backend...`);
const results = await compile(projectPath, { log });
for (const result of results) {
generateOutput(projectPath, result, options, log);
}
});
}

/**
*
* @param contract - output from compiler, to serialize locally. branch based on Contract vs Program
*/
function generateOutput(
projectPath: string,
_result: ContractArtifact | ProgramArtifact,
options: Options,
log: LogFn,
) {
const contract = _result as ContractArtifact;
if (contract.name) {
Comment on lines +75 to +76
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this (and the if statement after it) could use the helper method isNoirContractCompilationArtifacts from noir_artifacts.ts

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ahh i just tried, the types are actually slightly different... got bogged down converting ContractArtifact | ProgramArtifact type into NoirContractCompilationArtifacts | NoirProgramCompilationArtifacts

return generateContractOutput(projectPath, contract, options, log);
} else {
const program = _result as ProgramArtifact;
if (program.abi) {
return generateProgramOutput(projectPath, program, options, log);
}
}
}
/**
*
* @param program - output from compiler, to serialize locally
*/
function generateProgramOutput(projectPath: string, program: ProgramArtifact, options: Options, log: LogFn) {
const currentDir = process.cwd();
const { outdir, typescript, interface: noirInterface } = options;
const artifactPath = resolve(projectPath, outdir, `${program.name ? program.name : 'main'}.json`);
log(`Writing ${program.name} artifact to ${path.relative(currentDir, artifactPath)}`);
mkdirSync(path.dirname(artifactPath), { recursive: true });
writeFileSync(artifactPath, JSON.stringify(program, null, 2));

if (noirInterface) {
log(`noirInterface generation not implemented for programs`);
// not implemented
}

if (typescript) {
// just need type definitions, since a lib has just one entry point
const tsPath = resolve(projectPath, typescript, `../types/${program.name}_types.ts`);
log(`Writing ${program.name} typescript types to ${path.relative(currentDir, tsPath)}`);
const tsWrapper = generateTypescriptProgramInterface(program.abi);
mkdirpSync(path.dirname(tsPath));
writeFileSync(tsPath, tsWrapper);
}
}

/**
*
* @param contract - output from compiler, to serialize locally
*/
function generateContractOutput(projectPath: string, contract: ContractArtifact, options: Options, log: LogFn) {
const currentDir = process.cwd();
const { outdir, typescript, interface: noirInterface } = options;
const artifactPath = resolve(projectPath, outdir, `${contract.name}.json`);
log(`Writing ${contract.name} artifact to ${path.relative(currentDir, artifactPath)}`);
mkdirSync(path.dirname(artifactPath), { recursive: true });
writeFileSync(artifactPath, JSON.stringify(contract, null, 2));

if (noirInterface) {
const noirInterfacePath = resolve(projectPath, noirInterface, `${contract.name}_interface.nr`);
log(`Writing ${contract.name} Aztec.nr external interface to ${path.relative(currentDir, noirInterfacePath)}`);
const noirWrapper = generateNoirContractInterface(contract);
mkdirpSync(path.dirname(noirInterfacePath));
writeFileSync(noirInterfacePath, noirWrapper);
}

if (typescript) {
const tsPath = resolve(projectPath, typescript, `${contract.name}.ts`);
log(`Writing ${contract.name} typescript interface to ${path.relative(currentDir, tsPath)}`);
let relativeArtifactPath = path.relative(path.dirname(tsPath), artifactPath);
if (relativeArtifactPath === `${contract.name}.json`) {
// relative path edge case, prepending ./ for local import - the above logic just does
// `${contract.name}.json`, which is not a valid import for a file in the same directory
relativeArtifactPath = `./${contract.name}.json`;
}
const tsWrapper = generateTypescriptContractInterface(contract, relativeArtifactPath);
mkdirpSync(path.dirname(tsPath));
writeFileSync(tsPath, tsWrapper);
}
}
88 changes: 0 additions & 88 deletions yarn-project/noir-compiler/src/cli/contract.ts

This file was deleted.

2 changes: 1 addition & 1 deletion yarn-project/noir-compiler/src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { compileContract } from './contract.js';
export { compileNoir } from './compileNoir.js';
export { generateNoirInterface } from './noir-interface.js';
export { generateTypescriptInterface } from './typescript.js';
6 changes: 3 additions & 3 deletions yarn-project/noir-compiler/src/compile/nargo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { emptyDirSync } from 'fs-extra';
import path from 'path';

import { NoirCommit, NoirTag } from '../index.js';
import { NoirCompilationArtifacts, NoirCompiledContract, NoirDebugMetadata } from '../noir_artifact.js';
import { NoirCompiledContract, NoirContractCompilationArtifacts, NoirDebugMetadata } from '../noir_artifact.js';

/** Compilation options */
export type CompileOpts = {
Expand All @@ -31,7 +31,7 @@ export class NargoContractCompiler {
* Compiles the contracts in projectPath and returns the Aztec.nr artifact.
* @returns Aztec.nr artifact of the compiled contracts.
*/
public compile(): Promise<NoirCompilationArtifacts[]> {
public compile(): Promise<NoirContractCompilationArtifacts[]> {
const stdio = this.opts.quiet ? 'ignore' : 'inherit';
const nargoBin = this.opts.nargoBin ?? 'nargo';
const version = execSync(`${nargoBin} --version`, { cwd: this.projectPath, stdio: 'pipe' }).toString();
Expand All @@ -51,7 +51,7 @@ export class NargoContractCompiler {
}
}

private collectArtifacts(): NoirCompilationArtifacts[] {
private collectArtifacts(): NoirContractCompilationArtifacts[] {
const contractArtifacts = new Map<string, NoirCompiledContract>();
const debugArtifacts = new Map<string, NoirDebugMetadata>();

Expand Down
Loading