Skip to content

Commit

Permalink
chore: use new JS packages in integration tests (noir-lang#2938)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomAFrench authored and Sakapoi committed Oct 19, 2023
1 parent 7b6eeaf commit e8e51a1
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 132 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/test-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ name: test-integration
on:
workflow_dispatch:
pull_request:
paths:
- ./compiler/integration-tests/**
merge_group:
schedule:
- cron: "0 2 * * *" # Run nightly at 2 AM UTC

Expand Down Expand Up @@ -222,6 +221,8 @@ jobs:
run: |
yarn workspace @noir-lang/source-resolver build
yarn workspace @noir-lang/acvm_js build
yarn workspace @noir-lang/types build
yarn workspace @noir-lang/backend_barretenberg build
yarn workspace @noir-lang/noir_js build
- name: Run `integration-tests`
Expand Down
2 changes: 1 addition & 1 deletion compiler/integration-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"lint": "NODE_NO_WARNINGS=1 eslint . --ext .ts --ignore-path ./.eslintignore --max-warnings 0"
},
"dependencies": {
"@aztec/bb.js": "^0.7.3",
"@noir-lang/backend_barretenberg": "workspace:*",
"@noir-lang/noir_js": "workspace:*",
"@noir-lang/noir_wasm": "workspace:*",
"@noir-lang/source-resolver": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ 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, acirToUint8Array } from '@noir-lang/noir_js';
import { Barretenberg, RawBuffer, Crs } from '@aztec/bb.js';
import { acvm, abi, Noir } from '@noir-lang/noir_js';
import { BarretenbergBackend } from '@noir-lang/backend_barretenberg';
import { ethers } from 'ethers';
import * as TOML from 'smol-toml';

Expand All @@ -29,39 +29,27 @@ async function getFile(file_path: string): Promise<string> {
return await response.text();
}

const CIRCUIT_SIZE = 2 ** 19;
const FIELD_ELEMENT_BYTES = 32;

const test_cases = [
{
case: 'tooling/nargo_cli/tests/execution_success/1_mul',
compiled: 'foundry-project/out/1_mul.sol/UltraVerifier.json',
deployInformation: 'foundry-project/mul_output.json',
compiled: 'compiler/integration-tests/foundry-project/out/1_mul.sol/UltraVerifier.json',
deployInformation: 'compiler/integration-tests/foundry-project/mul_output.json',
numPublicInputs: 0,
},
{
case: 'compiler/integration-tests/test/circuits/main',
compiled: 'foundry-project/out/main.sol/UltraVerifier.json',
deployInformation: 'foundry-project/main_output.json',
compiled: 'compiler/integration-tests/foundry-project/out/main.sol/UltraVerifier.json',
deployInformation: 'compiler/integration-tests/foundry-project/main_output.json',
numPublicInputs: 1,
},
];

const numberOfThreads = navigator.hardwareConcurrency || 1;

const suite = Mocha.Suite.create(mocha.suite, 'Noir end to end test');

suite.timeout(60 * 20e3); //20mins

const api = await Barretenberg.new(numberOfThreads);
await api.commonInitSlabAllocator(CIRCUIT_SIZE);

// Plus 1 needed!
const crs = await Crs.new(CIRCUIT_SIZE + 1);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));

const acirComposer = await api.acirNewAcirComposer(CIRCUIT_SIZE);

async function getCircuit(noirSource: string) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
initializeResolver((id: string) => {
Expand All @@ -88,18 +76,6 @@ function separatePublicInputsFromProof(
};
}

async function generateProof(base64Bytecode: string, witnessUint8Array: Uint8Array, optimizeForRecursion: boolean) {
const acirUint8Array = acirToUint8Array(base64Bytecode);
// This took ~6.5 minutes!
return api.acirCreateProof(acirComposer, acirUint8Array, witnessUint8Array, optimizeForRecursion);
}

async function verifyProof(proof: Uint8Array, optimizeForRecursion: boolean) {
await api.acirInitVerificationKey(acirComposer);
const verified = await api.acirVerifyProof(acirComposer, proof, optimizeForRecursion);
return verified;
}

test_cases.forEach((testInfo) => {
const test_name = testInfo.case.split('/').pop();
const mochaTest = new Mocha.Test(`${test_name} (Compile, Execute, Prove, Verify)`, async () => {
Expand All @@ -118,25 +94,20 @@ test_cases.forEach((testInfo) => {
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);

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

const witnessArray: Uint8Array = await generateWitness(
{
bytecode: compile_output.circuit,
abi: compile_output.abi,
},
inputs,
);

// JS Proving

const isRecursive = false;
const proofWithPublicInputs = await generateProof(compile_output.circuit, witnessArray, isRecursive);
const proofWithPublicInputs = await program.generateFinalProof(inputs);

// JS verification

const verified = await verifyProof(proofWithPublicInputs, isRecursive);
const verified = await program.verifyFinalProof(proofWithPublicInputs);
expect(verified, 'Proof fails verification in JS').to.be.true;

// Smart contract verification
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@ 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 { decompressSync as gunzip } from 'fflate';
import { acvm, abi, generateWitness } from '@noir-lang/noir_js';

// @ts-ignore
import { Barretenberg, RawBuffer, Crs } from '@aztec/bb.js';

import * as TOML from 'smol-toml';
import { BarretenbergBackend } from '@noir-lang/backend_barretenberg';

const logger = new Logger({ name: 'test', minLevel: TEST_LOG_LEVEL });

Expand All @@ -23,8 +20,6 @@ await initACVM();

compilerLogLevel('INFO');

const numberOfThreads = navigator.hardwareConcurrency || 1;

const base_relative_path = '../../../../..';
const circuit_main = 'compiler/integration-tests/test/circuits/main';
const circuit_recursion = 'compiler/integration-tests/test/circuits/recursion';
Expand All @@ -37,16 +32,6 @@ async function getFile(url: URL): Promise<string> {
return await response.text();
}

const CIRCUIT_SIZE = 2 ** 19;

const api = await Barretenberg.new(numberOfThreads);
await api.commonInitSlabAllocator(CIRCUIT_SIZE);
// Plus 1 needed!
const crs = await Crs.new(CIRCUIT_SIZE + 1);
await api.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));

const acirComposer = await api.acirNewAcirComposer(CIRCUIT_SIZE);

async function getCircuit(noirSource: string) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
initializeResolver((id: string) => {
Expand All @@ -57,17 +42,6 @@ async function getCircuit(noirSource: string) {
return compile({});
}

async function generateProof(acirUint8Array: Uint8Array, witnessUint8Array: Uint8Array, optimizeForRecursion: boolean) {
// This took ~6.5 minutes!
return api.acirCreateProof(acirComposer, acirUint8Array, witnessUint8Array, optimizeForRecursion);
}

async function verifyProof(proof: Uint8Array, optimizeForRecursion: boolean) {
await api.acirInitVerificationKey(acirComposer);
const verified = await api.acirVerifyProof(acirComposer, proof, optimizeForRecursion);
return verified;
}

describe('It compiles noir program code, receiving circuit bytes and abi object.', () => {
let circuit_main_source;
let circuit_main_toml;
Expand All @@ -92,36 +66,24 @@ describe('It compiles noir program code, receiving circuit bytes and abi object.
const { circuit: main_circuit, abi: main_abi } = await getCircuit(circuit_main_source);
const main_inputs = TOML.parse(circuit_main_toml);

const main_witnessUint8Array = await generateWitness(
{
bytecode: main_circuit,
abi: main_abi,
},
main_inputs,
);
const main_compressedByteCode = Uint8Array.from(atob(main_circuit), (c) => c.charCodeAt(0));
const main_acirUint8Array = gunzip(main_compressedByteCode);
const main_program = { bytecode: main_circuit, abi: main_abi };
const main_backend = new BarretenbergBackend(main_program);

const optimizeMainProofForRecursion = true;
const main_witnessUint8Array = await generateWitness(main_program, main_inputs);

const main_proof = await generateProof(main_acirUint8Array, main_witnessUint8Array, optimizeMainProofForRecursion);

const main_verification = await verifyProof(main_proof, optimizeMainProofForRecursion);
const main_proof = await main_backend.generateIntermediateProof(main_witnessUint8Array);
const main_verification = await main_backend.verifyIntermediateProof(main_proof);

logger.debug('main_verification', main_verification);

expect(main_verification).to.be.true;

const numPublicInputs = 1;
const proofAsFields = (await api.acirSerializeProofIntoFields(acirComposer, main_proof, numPublicInputs)).map((p) =>
p.toString(),
const { proofAsFields, vkAsFields, vkHash } = await main_backend.generateIntermediateProofArtifacts(
main_proof,
numPublicInputs,
);

const vk = await api.acirSerializeVerificationKeyIntoFields(acirComposer);

const vkAsFields = vk[0].map((vk) => vk.toString());
const vkHash = vk[1].toString();

const recursion_inputs = {
verification_key: vkAsFields,
proof: proofAsFields,
Expand All @@ -133,36 +95,26 @@ 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_witnessUint8Array = await generateWitness(
{
bytecode: recursion_circuit,
abi: recursion_abi,
},
recursion_inputs,
);

const recursion_compressedByteCode = Uint8Array.from(atob(recursion_circuit), (c) => c.charCodeAt(0));

const recursion_acirUint8Array = gunzip(recursion_compressedByteCode);

const optimizeRecursionProofForRecursion = false;

const recursion_proof = await generateProof(
recursion_acirUint8Array,
recursion_witnessUint8Array,
optimizeRecursionProofForRecursion,
);
const recursion_backend = new BarretenbergBackend(recursion_program);

const recursion_numPublicInputs = 1;
const recursion_witnessUint8Array = await generateWitness(recursion_program, recursion_inputs);

const recursion_proofAsFields = (
await api.acirSerializeProofIntoFields(acirComposer, recursion_proof, recursion_numPublicInputs)
).map((p) => p.toString());
const recursion_proof = await recursion_backend.generateFinalProof(recursion_witnessUint8Array);

logger.debug('recursion_proofAsFields', recursion_proofAsFields);
// Causes an "unreachable" error.
// Due to the fact that it's a non-recursive proof?
//
// const recursion_numPublicInputs = 1;
// const { proofAsFields: recursion_proofAsFields } = await recursion_backend.generateIntermediateProofArtifacts(
// recursion_proof,
// recursion_numPublicInputs,
// );
//
// logger.debug('recursion_proofAsFields', recursion_proofAsFields);

const recursion_verification = await verifyProof(recursion_proof, false);
const recursion_verification = await recursion_backend.verifyFinalProof(recursion_proof);

logger.debug('recursion_verification', recursion_verification);

Expand Down
18 changes: 2 additions & 16 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -57,20 +57,6 @@ __metadata:
languageName: node
linkType: hard

"@aztec/bb.js@npm:^0.7.3":
version: 0.7.3
resolution: "@aztec/bb.js@npm:0.7.3"
dependencies:
comlink: ^4.4.1
commander: ^10.0.1
debug: ^4.3.4
tslib: ^2.4.0
bin:
bb.js: dest/node/main.js
checksum: 4da507d3de83b56c24f074cf61dfa6812b9c37f2047af25f79feac9973a900fd517bedb707ce00de9bf8acffec871f1894385e2bc3b74fd81f2c6b4c41a02293
languageName: node
linkType: hard

"@babel/code-frame@npm:^7.12.11, @babel/code-frame@npm:^7.21.4":
version: 7.22.13
resolution: "@babel/code-frame@npm:7.22.13"
Expand Down Expand Up @@ -459,7 +445,7 @@ __metadata:
languageName: unknown
linkType: soft

"@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg":
"@noir-lang/backend_barretenberg@workspace:*, @noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg":
version: 0.0.0-use.local
resolution: "@noir-lang/backend_barretenberg@workspace:tooling/noir_js_backend_barretenberg"
dependencies:
Expand Down Expand Up @@ -4543,7 +4529,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "integration-tests@workspace:compiler/integration-tests"
dependencies:
"@aztec/bb.js": ^0.7.3
"@noir-lang/backend_barretenberg": "workspace:*"
"@noir-lang/noir_js": "workspace:*"
"@noir-lang/noir_wasm": "workspace:*"
"@noir-lang/source-resolver": "workspace:*"
Expand Down

0 comments on commit e8e51a1

Please sign in to comment.