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(wasm)!: update wasm artifacts to match cli artifacts #2973

Merged
merged 3 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ test_cases.forEach((testInfo) => {

const noir_source = await getFile(`${base_relative_path}/${test_case}/src/main.nr`);

let compile_output;
let noir_program;
try {
compile_output = await getCircuit(noir_source);
noir_program = await getCircuit(noir_source);

expect(await compile_output, 'Compile output ').to.be.an('object');
expect(await noir_program, 'Compile output ').to.be.an('object');
} catch (e) {
expect(e, 'Compilation Step').to.not.be.an('error');
throw e;
}

const noir_program = { bytecode: compile_output.circuit, abi: compile_output.abi };
const backend = new BarretenbergBackend(noir_program);
const program = new Noir(noir_program, backend);

Expand Down
6 changes: 2 additions & 4 deletions compiler/integration-tests/test/browser/recursion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@ describe('It compiles noir program code, receiving circuit bytes and abi object.
});

it('Should generate valid inner proof for correct input, then verify proof within a proof', async () => {
const { circuit: main_circuit, abi: main_abi } = await getCircuit(circuit_main_source);
const main_program = await getCircuit(circuit_main_source);
const main_inputs = TOML.parse(circuit_main_toml);

const main_program = { bytecode: main_circuit, abi: main_abi };
const main_backend = new BarretenbergBackend(main_program);

const main_witnessUint8Array = await generateWitness(main_program, main_inputs);
Expand Down Expand Up @@ -79,8 +78,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object.

logger.debug('recursion_inputs', recursion_inputs);

const { circuit: recursion_circuit, abi: recursion_abi } = await getCircuit(circuit_recursion_source);
const recursion_program = { bytecode: recursion_circuit, abi: recursion_abi };
const recursion_program = await getCircuit(circuit_recursion_source);

const recursion_backend = new BarretenbergBackend(recursion_program);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,16 @@ test_cases.forEach((testInfo) => {

const noir_source_path = resolve(`${base_relative_path}/${test_case}/src/main.nr`);

let compile_output;
let noir_program;
try {
compile_output = await getCircuit(noir_source_path);
noir_program = await getCircuit(noir_source_path);

expect(await compile_output, 'Compile output ').to.be.an('object');
expect(await noir_program, 'Compile output ').to.be.an('object');
} catch (e) {
expect(e, 'Compilation Step').to.not.be.an('error');
throw e;
}

const noir_program = { bytecode: compile_output.circuit, abi: compile_output.abi };
const backend = new BarretenbergBackend(noir_program);
const program = new Noir(noir_program, backend);

Expand Down
45 changes: 43 additions & 2 deletions compiler/wasm/src/compile.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
use fm::FileManager;
use gloo_utils::format::JsValueSerdeExt;
use log::debug;
use nargo::artifacts::{
contract::{PreprocessedContract, PreprocessedContractFunction},
program::PreprocessedProgram,
};
use noirc_driver::{
add_dep, compile_contract, compile_main, prepare_crate, prepare_dependency, CompileOptions,
CompiledContract, CompiledProgram,
};
use noirc_frontend::{graph::CrateGraph, hir::Context};
use serde::{Deserialize, Serialize};
use std::path::Path;
use wasm_bindgen::prelude::*;

const BACKEND_IDENTIFIER: &str = "acvm-backend-barretenberg";

#[derive(Debug, Serialize, Deserialize)]
pub struct WASMCompileOptions {
#[serde(default = "default_entry_point")]
Expand Down Expand Up @@ -123,7 +130,9 @@ pub fn compile(args: JsValue) -> JsValue {
nargo::ops::optimize_contract(compiled_contract, np_language, &is_opcode_supported)
.expect("Contract optimization failed");

<JsValue as JsValueSerdeExt>::from_serde(&optimized_contract).unwrap()
let preprocessed_contract = preprocess_contract(optimized_contract);

<JsValue as JsValueSerdeExt>::from_serde(&preprocessed_contract).unwrap()
} else {
let compiled_program =
compile_main(&mut context, crate_id, &options.compile_options, None, true)
Expand All @@ -134,7 +143,39 @@ pub fn compile(args: JsValue) -> JsValue {
nargo::ops::optimize_program(compiled_program, np_language, &is_opcode_supported)
.expect("Program optimization failed");

<JsValue as JsValueSerdeExt>::from_serde(&optimized_program).unwrap()
let preprocessed_program = preprocess_program(optimized_program);

<JsValue as JsValueSerdeExt>::from_serde(&preprocessed_program).unwrap()
}
}

fn preprocess_program(program: CompiledProgram) -> PreprocessedProgram {
PreprocessedProgram {
hash: program.hash,
backend: String::from(BACKEND_IDENTIFIER),
abi: program.abi,
bytecode: program.circuit,
}
}

fn preprocess_contract(contract: CompiledContract) -> PreprocessedContract {
let preprocessed_functions = contract
.functions
.into_iter()
.map(|func| PreprocessedContractFunction {
name: func.name,
function_type: func.function_type,
is_internal: func.is_internal,
abi: func.abi,
bytecode: func.bytecode,
})
.collect();

PreprocessedContract {
name: contract.name,
backend: String::from(BACKEND_IDENTIFIER),
functions: preprocessed_functions,
events: contract.events,
}
}

Expand Down
14 changes: 9 additions & 5 deletions compiler/wasm/test/browser/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,23 @@ async function getSource(): Promise<string> {
return getFileContent(noirSourcePath);
}

async function getPrecompiledSource(): Promise<string> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function getPrecompiledSource(): Promise<any> {
const compiledData = await getFileContent(nargoArtifactPath);
return JSON.parse(compiledData).bytecode;
return JSON.parse(compiledData);
}

describe('noir wasm compilation', () => {
it('matches nargos compilation', async () => {
const source = await getSource();

const wasmCircuitBase64 = await compileNoirSource(source);
const wasmCircuit = await compileNoirSource(source);

const cliCircuitBase64 = await getPrecompiledSource();
const cliCircuit = await getPrecompiledSource();

expect(wasmCircuitBase64).to.equal(cliCircuitBase64);
// We don't expect the hashes to match due to how `noir_wasm` handles dependencies
expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode);
expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi);
expect(wasmCircuit.backend).to.eq(cliCircuit.backend);
}).timeout(20e3); // 20 seconds
});
20 changes: 9 additions & 11 deletions compiler/wasm/test/node/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,23 @@ async function getSource(): Promise<string> {
return getFileContent(noirSourcePath);
}

async function getPrecompiledSource(): Promise<string> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function getPrecompiledSource(): Promise<any> {
const compiledData = await getFileContent(nargoArtifactPath);
return JSON.parse(compiledData).bytecode;
return JSON.parse(compiledData);
}

describe('noir wasm compilation', () => {
it('matches nargos compilation', async () => {
const source = await getSource();

const wasmCircuitBase64 = await compileNoirSource(source);
const wasmCircuit = await compileNoirSource(source);

const cliCircuitBase64 = await getPrecompiledSource();
const cliCircuit = await getPrecompiledSource();

console.log('wasm', wasmCircuitBase64);

console.log('cli', cliCircuitBase64);

console.log('Compilation is a match? ', wasmCircuitBase64 === cliCircuitBase64);

expect(wasmCircuitBase64).to.equal(cliCircuitBase64);
// We don't expect the hashes to match due to how `noir_wasm` handles dependencies
expect(wasmCircuit.bytecode).to.eq(cliCircuit.bytecode);
expect(wasmCircuit.abi).to.deep.eq(cliCircuit.abi);
expect(wasmCircuit.backend).to.eq(cliCircuit.backend);
}).timeout(10e3);
});
5 changes: 3 additions & 2 deletions compiler/wasm/test/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { compile } from '@noir-lang/noir_wasm';
export const noirSourcePath = '../../noir-script/src/main.nr';
export const nargoArtifactPath = '../../noir-script/target/noir_wasm_testing.json';

export async function compileNoirSource(noir_source: string): Promise<unknown> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function compileNoirSource(noir_source: string): Promise<any> {
console.log('Compiling Noir source...');

initializeResolver((id: string) => {
Expand All @@ -24,7 +25,7 @@ export async function compileNoirSource(noir_source: string): Promise<unknown> {

console.log('Noir source compilation done.');

return compiled_noir.circuit;
return compiled_noir;
} catch (e) {
console.log('Error while compiling:', e);
}
Expand Down