Skip to content

Commit

Permalink
This works (but no logs still?)
Browse files Browse the repository at this point in the history
  • Loading branch information
codygunton committed Nov 3, 2024
1 parent 637c214 commit 51441ff
Show file tree
Hide file tree
Showing 16 changed files with 518 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ WASM_EXPORT void acir_prove_and_verify_aztec_client(uint8_t const* acir_stack,
bool* verified)
{
using Program = acir_format::AcirProgram;
info("about to read witnesses from buffer");
std::vector<std::vector<uint8_t>> witnesses = from_buffer<std::vector<std::vector<uint8_t>>>(witness_stack);
info("read witnesses from buffer");
std::vector<std::vector<uint8_t>> acirs = from_buffer<std::vector<std::vector<uint8_t>>>(acir_stack);
Expand Down
5 changes: 4 additions & 1 deletion barretenberg/cpp/src/barretenberg/srs/c_bind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ WASM_EXPORT void srs_init_srs(uint8_t const* points_buf, uint32_t const* num_poi
*/
WASM_EXPORT void srs_init_grumpkin_srs(uint8_t const* points_buf, uint32_t const* num_points)
{
info("allocating vector of points...");
auto points = std::vector<curve::Grumpkin::AffineElement>(ntohl(*num_points));
info("done. Reading affine elements from buffer...");
srs::IO<curve::Grumpkin>::read_affine_elements_from_buffer(points.data(), (char*)points_buf, points.size() * 64);

info("done. Tnitializing grumpking crs factory...");
bb::srs::init_grumpkin_crs_factory(points);
info("done.");
}
2 changes: 2 additions & 0 deletions barretenberg/ts/scripts/build_wasm.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ mkdir -p ./dest/node/barretenberg_wasm
mkdir -p ./dest/node-cjs/barretenberg_wasm
cp ../cpp/build-wasm-threads-assert/bin/barretenberg.wasm ./dest/node/barretenberg_wasm/barretenberg-threads.wasm
cp ../cpp/build-wasm-threads-assert/bin/barretenberg.wasm ./dest/node-cjs/barretenberg_wasm/barretenberg-threads.wasm
# cp ../cpp/build-wasm-threads-assert/bin/barretenberg.wasm ./src/barretenberg_wasm/barretenberg-threads.wasm
# cp ../cpp/build-wasm-threads-assert/bin/barretenberg.wasm ./src/barretenberg_wasm/barretenberg.wasm
5 changes: 5 additions & 0 deletions barretenberg/ts/src/barretenberg/backend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,15 +256,20 @@ export class AztecClientBackend {

/** @ignore */
async instantiate(): Promise<void> {
console.log("entered instantiate()");
if (!this.api) {
console.log("creating bb.js api object...");
const api = await Barretenberg.new(this.options);
console.log("created bb.js api object");
await api.initSRSClientIVC();
console.log("initialized SRS for CIVC");
this.api = api;
}
}

async proveAndVerify(witnessMsgpack: Uint8Array[]): Promise<boolean> {
await this.instantiate();
console.log("instantiated backend");
return this.api.acirProveAndVerifyAztecClient(this.acirMsgpack, witnessMsgpack);
}

Expand Down
4 changes: 4 additions & 0 deletions barretenberg/ts/src/barretenberg/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,16 @@ export class Barretenberg extends BarretenbergApi {
async initSRSClientIVC(): Promise<void> {
// crsPath can be undefined
const crs = await Crs.new(2 ** 21 + 1, this.options.crsPath);
console.log("created BN crs");
const grumpkinCrs = await GrumpkinCrs.new(2 ** 16 + 1, this.options.crsPath);
console.log("created Grumpkin crs");

// Load CRS into wasm global CRS state.
// TODO: Make RawBuffer be default behavior, and have a specific Vector type for when wanting length prefixed.
await this.srsInitSrs(new RawBuffer(crs.getG1Data()), crs.numPoints, new RawBuffer(crs.getG2Data()));
console.log("initizlied BN crs");
await this.srsInitGrumpkinSrs(new RawBuffer(grumpkinCrs.getG1Data()), grumpkinCrs.numPoints);
console.log("initizlied Grumpkin crs");
}


Expand Down
3 changes: 3 additions & 0 deletions barretenberg/ts/src/barretenberg_api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ export class BarretenbergApi {

async srsInitGrumpkinSrs(pointsBuf: Uint8Array, numPoints: number): Promise<void> {
const inArgs = [pointsBuf, numPoints].map(serializeBufferable);
console.log("serialized pointsBuf and num_points");
const outTypes: OutputType[] = [];
const result = await this.wasm.callWasmExport(
'srs_init_grumpkin_srs',
Expand Down Expand Up @@ -533,7 +534,9 @@ export class BarretenbergApi {
}

async acirProveAndVerifyAztecClient(acirVec: Uint8Array[], witnessVec: Uint8Array[]): Promise<boolean> {
console.log("about to serialize array of arrays to arrays...");
const inArgs = [acirVec, witnessVec].map(serializeBufferable);
console.log("done");
const outTypes: OutputType[] = [BoolDeserializer()];
const result = await this.wasm.callWasmExport(
'acir_prove_and_verify_aztec_client',
Expand Down
1 change: 1 addition & 0 deletions barretenberg/ts/src/barretenberg_wasm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export class BarretenbergWasm extends BarretenbergWasmMain {
const worker = createMainWorker();
const wasm = getRemoteBarretenbergWasm<BarretenbergWasmMainWorker>(worker);
const { module, threads } = await fetchModuleAndThreads(desiredThreads);
console.log("initializing wasm");
await wasm.init(module, threads, proxy(debug));
return { worker, wasm };
}
Expand Down
1 change: 1 addition & 0 deletions barretenberg/ts/src/crs/node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export class GrumpkinCrs {
* @returns The points data.
*/
getG1Data(): Uint8Array {
console.log("about to read grupmkin_g1 data");
return readFileSync(this.path + '/grumpkin_g1.dat');
}
}
16 changes: 12 additions & 4 deletions yarn-project/ivc-integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@
"generate:noir-circuits": "mkdir -p ./artifacts && cp -r ../../noir-projects/mock-protocol-circuits/target/* ./artifacts && node --no-warnings --loader ts-node/esm src/scripts/generate_declaration_files.ts && node --no-warnings --loader ts-node/esm src/scripts/generate_ts_from_abi.ts && run -T prettier -w ./src/types",
"test": "NODE_NO_WARNINGS=1 node --experimental-vm-modules ../node_modules/.bin/jest --passWithNoTests",
"codegen": "yarn noir-codegen",
"build:dev": "tsc -b --watch"
"build:dev": "tsc -b --watch",
"build:browser": "rm -rf dest && webpack",
"serve": "serve -n -L -p 8080 -c ../serve.mt.json dest"
},
"jest": {
"moduleNameMapper": {
Expand Down Expand Up @@ -57,25 +59,31 @@
]
},
"dependencies": {
"@aztec/bb.js": "../../ts",
"@aztec/circuits.js": "workspace:^",
"@aztec/foundation": "workspace:^",
"@aztec/types": "workspace:^",
"@noir-lang/noir_codegen": "portal:../../noir/packages/noir_codegen",
"@noir-lang/noir_js": "file:../../noir/packages/noir_js",
"@noir-lang/noirc_abi": "portal:../../noir/packages/noirc_abi",
"@noir-lang/types": "portal:../../noir/packages/types",
"chalk": "^5.3.0",
"change-case": "^5.4.4",
"pako": "^2.1.0",
"playwright": "^1.48.2",
"puppeteer": "^22.4.1",
"tslib": "^2.4.0"
},
"devDependencies": {
"@aztec/bb-prover": "workspace:^",
"@aztec/bb.js": "../../ts",
"@aztec/simulator": "workspace:^",
"@jest/globals": "^29.5.0",
"@msgpack/msgpack": "^3.0.0-beta2",
"@playwright/test": "^1.48.2",
"@types/jest": "^29.5.0",
"@types/node": "^18.7.23",
"@types/node": "^22.8.1",
"@types/pako": "^2.0.3",
"copy-webpack-plugin": "^12.0.2",
"html-webpack-plugin": "^5.6.0",
"jest": "^29.5.0",
"jest-mock-extended": "^4.0.0-beta1",
Expand All @@ -84,7 +92,7 @@
"resolve-typescript-plugin": "^2.0.1",
"serve": "^14.2.1",
"ts-loader": "^9.5.1",
"ts-node": "^10.9.1",
"ts-node": "^10.9.2",
"typescript": "^5.4.2",
"webpack": "^5.90.3",
"webpack-cli": "^5.1.4",
Expand Down
17 changes: 17 additions & 0 deletions yarn-project/ivc-integration/serve.mt.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"headers": [
{
"source": "**/*",
"headers": [
{
"key": "Cross-Origin-Embedder-Policy",
"value": "require-corp"
},
{
"key": "Cross-Origin-Opener-Policy",
"value": "same-origin"
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import { BB_RESULT, executeBbClientIvcProveAndVerify } from '@aztec/bb-prover';
import { ClientIvcProof } from '@aztec/circuits.js';
import { createDebugLogger } from '@aztec/foundation/log';

import { jest } from '@jest/globals';
import { encode } from '@msgpack/msgpack';
import fs from 'fs/promises';
import os from 'os';
import path from 'path';
import { fileURLToPath } from 'url';
import chalk from 'chalk';
import {
type Browser,
type Page,
chromium,
/* firefox, webkit */
} from 'playwright';

import {
MOCK_MAX_COMMITMENTS_PER_TX,
Expand All @@ -23,64 +22,61 @@ import {
witnessGenMockPrivateKernelResetCircuit,
witnessGenMockPrivateKernelTailCircuit,
witnessGenReaderAppMockCircuit,
proveAndVerifyAztecClient
} from './index.js';

/* eslint-disable camelcase */

const logger = createDebugLogger('aztec:clientivc-integration');
const logger = createDebugLogger('aztec:browser-ivc-test');

jest.setTimeout(120_000);

describe('Client IVC Integration', () => {
let bbWorkingDirectory: string;
let bbBinaryPath: string;

beforeEach(async () => {
// Create a temp working dir
bbWorkingDirectory = await fs.mkdtemp(path.join(os.homedir(), 'bb-tmp/', 'bb-client-ivc-integration-'));
bbBinaryPath = path.join(
path.dirname(fileURLToPath(import.meta.url)),
'../../../barretenberg/ts/dest/node',
'main.js',
);
logger.debug(`bbBinaryPath is ${bbBinaryPath}`);
});
function formatAndPrintLog(message: string): void {
const parts = message.split('%c');
if (parts.length === 1) {
logger.debug(parts[0]);
return;
}
if (!parts[0]) {
parts.shift();
}
const colors = parts[parts.length - 1].split(' color: ');
parts[parts.length - 1] = colors.shift()!;

function uint8ArrayToBase64(uint8Array: Uint8Array): string {
// Convert each byte in the Uint8Array to a character, then join them into a binary string
const binaryString = Array.from(uint8Array)
.map(byte => String.fromCharCode(byte))
.join('');
// logger.debug({ message, parts, colors });

// Encode the binary string to base64
return btoa(binaryString);
}
let formattedMessage = '';
for (let i = 0; i < parts.length; i++) {
const colorValue = colors[i];

async function proveAndVerifyAztecClient(witnessStack: Uint8Array[], bytecodes: string[]): Promise<boolean> {
await fs.writeFile(
path.join(bbWorkingDirectory, 'acir.msgpack.b64'),
uint8ArrayToBase64(encode(bytecodes.map(bytecode => Buffer.from(bytecode, 'base64')))),
);
logger.debug('wrote acir.msgpack.b64');

await fs.writeFile(path.join(bbWorkingDirectory, 'witnesses.msgpack.b64'), uint8ArrayToBase64(encode(witnessStack)));
logger.debug('wrote witnesses.msgpack.b64');

const provingResult = await executeBbClientIvcProveAndVerify(
bbBinaryPath,
bbWorkingDirectory,
path.join(bbWorkingDirectory, 'acir.msgpack.b64'),
path.join(bbWorkingDirectory, 'witnesses.msgpack.b64'),
logger.info,
);

if (provingResult.status === BB_RESULT.FAILURE) {
throw new Error(provingResult.reason);
if (colorValue === 'inherit' || !colorValue) {
formattedMessage += parts[i];
} else if (colorValue.startsWith('#')) {
formattedMessage += chalk.hex(colorValue)(parts[i]);
} else {
return true
formattedMessage += parts[i];
}
}

logger.debug(formattedMessage);
}

describe('Client IVC Integration', () => {
let page: Page;
let browser: Browser;

beforeAll(async () => {
browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
page = await context.newPage();
page.on('console', msg => formatAndPrintLog(msg.text()));
await page.goto('http://localhost:8080');
});

afterAll(async () => {
await browser.close();
});

// This test will verify a client IVC proof of a simple tx:
// 1. Run a mock app that creates two commitments
// 2. Run the init kernel to process the app run
Expand Down Expand Up @@ -114,7 +110,7 @@ describe('Client IVC Integration', () => {
const witnessStack = [appWitnessGenResult.witness, initWitnessGenResult.witness, tailWitnessGenResult.witness];
logger.debug('built witness stack');

const verifyResult = await proveAndVerifyAztecClient(witnessStack, bytecodes);
const verifyResult = await proveAndVerifyAztecClient(page, bytecodes, witnessStack);
logger.debug(`generated and verified proof. result: ${verifyResult}`);

expect(verifyResult).toEqual(true);
Expand Down
9 changes: 9 additions & 0 deletions yarn-project/ivc-integration/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<title>My Test bb.js App</title>
</head>
<body>
<script src="index.js"></script>
</body>
</html>
52 changes: 52 additions & 0 deletions yarn-project/ivc-integration/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { createDebugLogger } from '@aztec/foundation/log';

import { type ForeignCallOutput, Noir } from '@noir-lang/noir_js';
import { ungzip } from 'pako';
import { type Page } from 'playwright';

import MockAppCreatorCircuit from '../artifacts/app_creator.json' assert { type: 'json' };
import MockAppReaderCircuit from '../artifacts/app_reader.json' assert { type: 'json' };
Expand Down Expand Up @@ -30,6 +34,7 @@ export {
MockPrivateKernelResetCircuit,
MockPrivateKernelTailCircuit,
MockPublicKernelCircuit,
proveAndVerifyAztecClient,
};

export const MOCK_MAX_COMMITMENTS_PER_TX = 4;
Expand Down Expand Up @@ -119,3 +124,50 @@ export async function witnessGenMockPublicKernelCircuit(
publicInputs: returnValue as u8,
};
}

const logger = createDebugLogger('browser-ivc-test');

function base64ToUint8Array(base64: string): Uint8Array {
logger.debug('creating Uint8Array from string');
logger.debug('creating Uint8Array from string');
return new Uint8Array(Buffer.from(base64, 'base64'));
}

async function runTest(bytecodes: string[], witnessStack: Uint8Array[], threads?: number) {
logger.debug(`trying to import backend`);
const { AztecClientBackend } = await import('@aztec/bb.js');
logger.debug(`creatingAztecClientBackend`);
const preparedBytecodes = bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr));
logger.debug(`created preparedBytecodes`);
const backend = new AztecClientBackend(preparedBytecodes, { threads });
logger.debug(`calling proveAndVerify on backend`);
const verified = await backend.proveAndVerify(witnessStack.map((arr: Uint8Array) => ungzip(arr)));
logger.debug(`finished running proveAndVerify. result: ${verified}`);

await backend.destroy();
return verified;
}

async function proveAndVerifyAztecClient(
page: Page,
bytecodes: string[],
witnessStack: Uint8Array[],
): Promise<boolean> {
logger.debug('calling proveAndVerifyAztecClient');
// const threads = Math.min(os.cpus().length, 16);
const threads = 8;

await page.exposeFunction('runTest', runTest);

const result: boolean = await page.evaluate(
([acir, witness, numThreads]) => {
console.log('about to call runTest');
(window as any).runTest = runTest;
return (window as any).runTest(acir, witness, numThreads);
},
[bytecodes, witnessStack, threads],
);

logger.debug(`RESULT: ${result}`);
return result;
}
Loading

0 comments on commit 51441ff

Please sign in to comment.