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: add execute method to Noir class #3081

Merged
merged 6 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 4 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 @@ -5,6 +5,7 @@ import * as TOML from 'smol-toml';
import { initializeResolver } from '@noir-lang/source-resolver';
import newCompiler, { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm';
import { Noir } from '@noir-lang/noir_js';
import { InputMap } from '@noir-lang/noirc_abi';
import { BarretenbergBackend } from '@noir-lang/backend_barretenberg';

import { getFile } from './utils.js';
Expand Down Expand Up @@ -64,7 +65,7 @@ test_cases.forEach((testInfo) => {
const program = new Noir(noir_program, backend);

const prover_toml = await getFile(`${base_relative_path}/${test_case}/Prover.toml`);
const inputs = TOML.parse(prover_toml);
const inputs: InputMap = TOML.parse(prover_toml) as InputMap;

// JS Proving

Expand Down
6 changes: 3 additions & 3 deletions compiler/integration-tests/test/browser/recursion.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { TEST_LOG_LEVEL } from '../environment.js';
import { Logger } from 'tslog';
import { initializeResolver } from '@noir-lang/source-resolver';
import newCompiler, { compile, init_log_level as compilerLogLevel } from '@noir-lang/noir_wasm';
import { acvm, abi, generateWitness } from '@noir-lang/noir_js';
import { acvm, abi, Noir } from '@noir-lang/noir_js';

import * as TOML from 'smol-toml';
import { BarretenbergBackend } from '@noir-lang/backend_barretenberg';
Expand Down Expand Up @@ -55,7 +55,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object.

const main_backend = new BarretenbergBackend(main_program);

const main_witnessUint8Array = await generateWitness(main_program, main_inputs);
const { witness: main_witnessUint8Array } = await new Noir(main_program).execute(main_inputs);

const main_proof = await main_backend.generateIntermediateProof(main_witnessUint8Array);
const main_verification = await main_backend.verifyIntermediateProof(main_proof);
Expand Down Expand Up @@ -84,7 +84,7 @@ describe('It compiles noir program code, receiving circuit bytes and abi object.

const recursion_backend = new BarretenbergBackend(recursion_program);

const recursion_witnessUint8Array = await generateWitness(recursion_program, recursion_inputs);
const { witness: recursion_witnessUint8Array } = await new Noir(recursion_program).execute(recursion_inputs);

const recursion_proof = await recursion_backend.generateFinalProof(recursion_witnessUint8Array);

Expand Down
1 change: 0 additions & 1 deletion tooling/noir_js/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import * as abi from '@noir-lang/noirc_abi';

export { acvm, abi };

export { generateWitness } from './witness_generation.js';
export { acirToUint8Array, witnessMapToUint8Array } from './serialize.js';

export { Noir } from './program.js';
25 changes: 19 additions & 6 deletions tooling/noir_js/src/program.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { Backend, CompiledCircuit, ProofData } from '@noir-lang/types';
import { generateWitness } from './witness_generation.js';
import initAbi from '@noir-lang/noirc_abi';
import initAbi, { abiDecode, InputMap, InputValue } from '@noir-lang/noirc_abi';
import initACVM from '@noir-lang/acvm_js';
import { witnessMapToUint8Array } from './serialize.js';

export class Noir {
constructor(
private circuit: CompiledCircuit,
private backend: Backend,
private backend?: Backend,
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
) {}

async init(): Promise<void> {
Expand All @@ -19,14 +20,26 @@ export class Noir {
}
}

private getBackend(): Backend {
if (this.backend === undefined) throw new Error('Operation requires a backend but none was provided');
kevaundray marked this conversation as resolved.
Show resolved Hide resolved
return this.backend;
}

// Initial inputs to your program
async generateFinalProof(inputs: any): Promise<ProofData> {
async execute(inputs: InputMap): Promise<{ witness: Uint8Array; returnValue: InputValue }> {
await this.init();
const serializedWitness = await generateWitness(this.circuit, inputs);
return this.backend.generateFinalProof(serializedWitness);
const witness = await generateWitness(this.circuit, inputs);
const { return_value: returnValue } = abiDecode(this.circuit.abi, witness);
return { witness: witnessMapToUint8Array(witness), returnValue };
}

// Initial inputs to your program
async generateFinalProof(inputs: InputMap): Promise<ProofData> {
const { witness } = await this.execute(inputs);
return this.getBackend().generateFinalProof(witness);
}

async verifyFinalProof(proofData: ProofData): Promise<boolean> {
return this.backend.verifyFinalProof(proofData);
return this.getBackend().verifyFinalProof(proofData);
}
}
7 changes: 3 additions & 4 deletions tooling/noir_js/src/witness_generation.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { abiEncode, InputMap } from '@noir-lang/noirc_abi';
import { base64Decode } from './base64_decode.js';
import { executeCircuit } from '@noir-lang/acvm_js';
import { witnessMapToUint8Array } from './serialize.js';
import { executeCircuit, WitnessMap } from '@noir-lang/acvm_js';
import { CompiledCircuit } from '@noir-lang/types';

// Generates the witnesses needed to feed into the chosen proving system
export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap): Promise<Uint8Array> {
export async function generateWitness(compiledProgram: CompiledCircuit, inputs: InputMap): Promise<WitnessMap> {
// Throws on ABI encoding error
const witnessMap = abiEncode(compiledProgram.abi, inputs);

Expand All @@ -15,7 +14,7 @@ export async function generateWitness(compiledProgram: CompiledCircuit, inputs:
const solvedWitness = await executeCircuit(base64Decode(compiledProgram.bytecode), witnessMap, () => {
throw Error('unexpected oracle during execution');
});
return witnessMapToUint8Array(solvedWitness);
return solvedWitness;
} catch (err) {
throw new Error(`Circuit execution failed: ${err}`);
}
Expand Down
32 changes: 22 additions & 10 deletions tooling/noir_js/test/node/e2e.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' };
import { Noir, generateWitness } from '@noir-lang/noir_js';
import { Noir } from '@noir-lang/noir_js';
import { BarretenbergBackend as Backend } from '@noir-lang/backend_barretenberg';
import { CompiledCircuit } from '@noir-lang/types';

Expand All @@ -12,13 +12,16 @@ it('end-to-end proof creation and verification (outer)', async () => {
x: '2',
y: '3',
};
const serializedWitness = await generateWitness(assert_lt_program, inputs);

const program = new Noir(assert_lt_program);

const { witness } = await program.execute(inputs);

// bb.js part
//
// Proof creation
const prover = new Backend(assert_lt_program);
const proof = await prover.generateFinalProof(serializedWitness);
const proof = await prover.generateFinalProof(witness);

// Proof verification
const isValid = await prover.verifyFinalProof(proof);
Expand Down Expand Up @@ -50,13 +53,16 @@ it('end-to-end proof creation and verification (inner)', async () => {
x: '2',
y: '3',
};
const serializedWitness = await generateWitness(assert_lt_program, inputs);

const program = new Noir(assert_lt_program);

const { witness } = await program.execute(inputs);

// bb.js part
//
// Proof creation
const prover = new Backend(assert_lt_program);
const proof = await prover.generateIntermediateProof(serializedWitness);
const proof = await prover.generateIntermediateProof(witness);

// Proof verification
const isValid = await prover.verifyIntermediateProof(proof);
Expand All @@ -81,12 +87,15 @@ it('[BUG] -- bb.js null function or function signature mismatch (different insta
x: '2',
y: '3',
};
const serializedWitness = await generateWitness(assert_lt_program, inputs);

const program = new Noir(assert_lt_program);

const { witness } = await program.execute(inputs);

// bb.js part
const prover = new Backend(assert_lt_program);

const proof = await prover.generateFinalProof(serializedWitness);
const proof = await prover.generateFinalProof(witness);

try {
const verifier = new Backend(assert_lt_program);
Expand All @@ -113,7 +122,10 @@ it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ',
x: '2',
y: '3',
};
const serializedWitness = await generateWitness(assert_lt_program, inputs);

const program = new Noir(assert_lt_program);

const { witness } = await program.execute(inputs);

// bb.js part
//
Expand All @@ -122,8 +134,8 @@ it('[BUG] -- bb.js null function or function signature mismatch (outer-inner) ',
const prover = new Backend(assert_lt_program);
// Create a proof using both proving systems, the majority of the time
// one would only use outer proofs.
const proofOuter = await prover.generateFinalProof(serializedWitness);
const _proofInner = await prover.generateIntermediateProof(serializedWitness);
const proofOuter = await prover.generateFinalProof(witness);
const _proofInner = await prover.generateIntermediateProof(witness);

// Proof verification
//
Expand Down
16 changes: 16 additions & 0 deletions tooling/noir_js/test/node/execute.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import assert_lt_json from '../noir_compiled_examples/assert_lt/target/assert_lt.json' assert { type: 'json' };
import { Noir } from '../../src/program.js';
import { CompiledCircuit } from '@noir-lang/types';
import { expect } from 'chai';

const assert_lt_program = assert_lt_json as CompiledCircuit;

it('returns the return value of the circuit', async () => {
const inputs = {
x: '2',
y: '3',
};
const { returnValue } = await new Noir(assert_lt_program).execute(inputs);

expect(returnValue).to.be.eq('0x05');
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
fn main(x : u64, y : pub u64) {
fn main(x : u64, y : pub u64) -> pub u64 {
assert(x < y);
}
x + y
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":null,"return_witnesses":[]},"bytecode":"H4sIAAAAAAAA/81WXW7DIAw20BJl0noWE6CBt6k3WbT0/kfYooJm0bQPxZZqKXKw4PPPB5Y/AOATbqL+Pl30F1nrsqaiiq52j+cQ1nlanXffOOUlRQxxOSeXXEzxZ0rerymkOS95xuyCX901Zn/Fm5jXsbDBcobE9yxm7BNn+LCQxnvY+dfEZoq2AjlB46et42nHxupcgqSDAO4R+C6/VN5Hfo6QQIrWFDvFwP9DoaKZY1aM90C/HpdrDTupvyP2nS/a6GzRA7GNhEfd7Nu4qJxvb/5CzimiFcG4kDN7e9QDnJHY6vkTiQX4aoICjR5FG3mdHCwp5rYe4H6SMAK+Kxbng+zFGkGmCbf1652eLGPOAyOvHfV72sC4J1nLyPOjptXKL8ADXjPGCwAA"}
{"hash":7965745029883743051,"backend":"acvm-backend-barretenberg","abi":{"parameters":[{"name":"x","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"private"},{"name":"y","type":{"kind":"integer","sign":"unsigned","width":64},"visibility":"public"}],"param_witnesses":{"x":[1],"y":[2]},"return_type":{"kind":"integer","sign":"unsigned","width":64},"return_witnesses":[12]},"bytecode":"H4sIAAAAAAAA/+1WXW6DMAw2oVAGqNqedg2HQAlv1W4yNHr/I2yoieRmlIfGZpNaS8jBCl/8F/O9AcA7XCT5eZTTJ/Ku3DuVxGlvN3hs26lvJm30JzbDaDtsu/FotdWd7b4aa8xkW9sP49DjoFsz6XM3mDNeJL0fCwMsnRL/1nzGONEpHxZSf3cLa0VsqdO5QEwQnBPm8bBgYz1cokg7AdwM+JpfKu6Mv0ZIIEVzipEyx08vjRfF7HPC2Afqfr90aFgInQ2b5jV3ek9sGekPv3e+gx/wu3cSslZuj1rZk9zAeSE2/73osPLB5cRB5RJxCs5MBc72WJxNF4t1AJlBE+YvliHkjDHvGesakb/VAcDN1nLY5ocS62fB2DNbscqCD+uKVdIB+WSVkZiFSyg3bgn/m1XOcZf8NRJllSWjn3/BKjFOtAKZOkX2wCqrrJyuie2hWGUF16yyhm1ZJcaJ5mSVryDTwNyssmKMuWasBWf+bl0wv6YX9htJ8OlsXBQAAA=="}
Loading