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

chore: use new JS packages in integration tests #2938

Merged
merged 7 commits into from
Oct 2, 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
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 @@ -454,7 +440,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 @@ -4550,7 +4536,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