Skip to content

Commit

Permalink
feat(wasm)!: update wasm artifacts to match cli artifacts (#2973)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored Oct 3, 2023
1 parent 4f86031 commit ce16c0b
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 32 deletions.
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

0 comments on commit ce16c0b

Please sign in to comment.