Skip to content
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
3 changes: 1 addition & 2 deletions yarn-project/aztec.js/src/contract/batch_call.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { ExecutionPayload } from '@aztec/entrypoints/payload';
import { mergeExecutionPayloads } from '@aztec/entrypoints/payload';
import { ExecutionPayload, mergeExecutionPayloads } from '@aztec/entrypoints/payload';
import { type FunctionCall, FunctionType, decodeFromAbi } from '@aztec/stdlib/abi';
import type { TxExecutionRequest } from '@aztec/stdlib/tx';

Expand Down
18 changes: 11 additions & 7 deletions yarn-project/bb-prover/src/prover/bb_private_kernel_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
convertPrivateKernelTailInputsToWitnessMapWithAbi,
convertPrivateKernelTailOutputsFromWitnessMapWithAbi,
convertPrivateKernelTailToPublicInputsToWitnessMapWithAbi,
foreignCallHandler,
getPrivateKernelResetArtifactName,
updateResetCircuitSampleInputs,
} from '@aztec/noir-protocol-circuits-types/client';
Expand All @@ -28,7 +29,7 @@ import type {
PrivateKernelTailCircuitPrivateInputs,
PrivateKernelTailCircuitPublicInputs,
} from '@aztec/stdlib/kernel';
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
import type { NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
import type { ClientIvcProof } from '@aztec/stdlib/proofs';
import type { CircuitSimulationStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats';

Expand Down Expand Up @@ -159,15 +160,14 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver {
convertInputs: (inputs: I, abi: Abi) => WitnessMap,
convertOutputs: (outputs: WitnessMap, abi: Abi) => O,
): Promise<PrivateKernelSimulateOutput<O>> {
const compiledCircuit: NoirCompiledCircuit = await this.artifactProvider.getSimulatedClientCircuitArtifactByName(
circuitType,
);
const compiledCircuit: NoirCompiledCircuitWithName =
await this.artifactProvider.getSimulatedClientCircuitArtifactByName(circuitType);

const witnessMap = convertInputs(inputs, compiledCircuit.abi);

const timer = new Timer();
const outputWitness = await this.simulationProvider
.executeProtocolCircuit(witnessMap, compiledCircuit)
.executeProtocolCircuit(witnessMap, compiledCircuit, foreignCallHandler)
.catch((err: Error) => {
this.log.debug(`Failed to simulate ${circuitType}`, {
circuitName: mapProtocolArtifactNameToCircuitName(circuitType),
Expand Down Expand Up @@ -198,13 +198,17 @@ export abstract class BBPrivateKernelProver implements PrivateKernelProver {
convertOutputs: (outputs: WitnessMap, abi: Abi) => O,
): Promise<PrivateKernelSimulateOutput<O>> {
this.log.debug(`Generating witness for ${circuitType}`);
const compiledCircuit: NoirCompiledCircuit = await this.artifactProvider.getClientCircuitArtifactByName(
const compiledCircuit: NoirCompiledCircuitWithName = await this.artifactProvider.getClientCircuitArtifactByName(
circuitType,
);

const witnessMap = convertInputs(inputs, compiledCircuit.abi);
const timer = new Timer();
const outputWitness = await this.simulationProvider.executeProtocolCircuit(witnessMap, compiledCircuit);
const outputWitness = await this.simulationProvider.executeProtocolCircuit(
witnessMap,
compiledCircuit,
foreignCallHandler,
);
const output = convertOutputs(outputWitness, compiledCircuit.abi);

this.log.debug(`Generated witness for ${circuitType}`, {
Expand Down
7 changes: 4 additions & 3 deletions yarn-project/bb-prover/src/prover/bb_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { createLogger } from '@aztec/foundation/log';
import { BufferReader } from '@aztec/foundation/serialize';
import { Timer } from '@aztec/foundation/timer';
import {
ServerCircuitArtifacts,
type ServerProtocolArtifact,
convertBaseParityInputsToWitnessMap,
convertBaseParityOutputsFromWitnessMap,
Expand All @@ -36,6 +35,7 @@ import {
convertRootRollupOutputsFromWitnessMap,
convertSingleTxBlockRootRollupInputsToWitnessMap,
convertSingleTxBlockRootRollupOutputsFromWitnessMap,
getServerCircuitArtifact,
} from '@aztec/noir-protocol-circuits-types/server';
import { ServerCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
import type { WitnessMap } from '@aztec/noir-types';
Expand Down Expand Up @@ -411,13 +411,14 @@ export class BBNativeRollupProver implements ServerCircuitProver {
outputWitnessFile,
);

const artifact = ServerCircuitArtifacts[circuitType];
const artifact = getServerCircuitArtifact(circuitType);

logger.debug(`Generating witness data for ${circuitType}`);

const inputWitness = convertInput(input);
const timer = new Timer();
const outputWitness = await simulator.executeProtocolCircuit(inputWitness, artifact);
const foreignCallHandler = undefined; // We don't handle foreign calls in the native ACVM simulator
const outputWitness = await simulator.executeProtocolCircuit(inputWitness, artifact, foreignCallHandler);
const output = convertOutput(outputWitness);

const circuitName = mapProtocolArtifactNameToCircuitName(circuitType);
Expand Down
31 changes: 21 additions & 10 deletions yarn-project/bb-prover/src/test/test_circuit_prover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { sleep } from '@aztec/foundation/sleep';
import { Timer } from '@aztec/foundation/timer';
import {
type ServerProtocolArtifact,
SimulatedServerCircuitArtifacts,
convertBaseParityInputsToWitnessMap,
convertBaseParityOutputsFromWitnessMap,
convertBlockMergeRollupInputsToWitnessMap,
Expand All @@ -32,6 +31,8 @@ import {
convertSimulatedPublicBaseRollupOutputsFromWitnessMap,
convertSimulatedSingleTxBlockRootRollupInputsToWitnessMap,
convertSimulatedSingleTxBlockRootRollupOutputsFromWitnessMap,
foreignCallHandler,
getSimulatedServerCircuitArtifact,
} from '@aztec/noir-protocol-circuits-types/server';
import { ProtocolCircuitVks } from '@aztec/noir-protocol-circuits-types/server/vks';
import type { WitnessMap } from '@aztec/noir-types';
Expand Down Expand Up @@ -347,16 +348,26 @@ export class TestCircuitProver implements ServerCircuitProver {
const witnessMap = convertInput(input);
const circuitName = mapProtocolArtifactNameToCircuitName(artifactName);

let simulationProvider = this.simulationProvider ?? this.wasmSimulator;
if (['BlockRootRollupArtifact', 'SingleTxBlockRootRollupArtifact'].includes(artifactName)) {
// TODO(#10323): temporarily force block root to use wasm while we simulate
// the blob operations with an oracle. Appears to be no way to provide nativeACVM with a foreign call hander.
simulationProvider = this.wasmSimulator;
let witness: WitnessMap;
if (
['BlockRootRollupArtifact', 'SingleTxBlockRootRollupArtifact'].includes(artifactName) ||
this.simulationProvider == undefined
) {
// TODO(#10323): Native ACVM simulator does not support foreign call handler so we use the wasm simulator
// when simulating block root rollup and single tx block root rollup circuits or when the native ACVM simulator
// is not provided.
witness = await this.wasmSimulator.executeProtocolCircuit(
witnessMap,
getSimulatedServerCircuitArtifact(artifactName),
foreignCallHandler,
);
} else {
witness = await this.simulationProvider.executeProtocolCircuit(
witnessMap,
getSimulatedServerCircuitArtifact(artifactName),
undefined, // Native ACM simulator does not support foreign call handler
);
}
const witness = await simulationProvider.executeProtocolCircuit(
witnessMap,
SimulatedServerCircuitArtifacts[artifactName],
);

const result = convertOutput(witness);

Expand Down
3 changes: 3 additions & 0 deletions yarn-project/end-to-end/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ function test_cmds {
echo "$prefix simple e2e_token_contract/transfer_to_public"
echo "$prefix simple e2e_token_contract/transfer.test"

# circuit_recorder sub-tests
echo "$prefix simple e2e_circuit_recorder"

# compose-based tests (use running sandbox)
echo "$prefix compose composed/docs_examples"
echo "$prefix compose composed/e2e_pxe"
Expand Down
69 changes: 69 additions & 0 deletions yarn-project/end-to-end/src/e2e_circuit_recorder.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import fs from 'fs/promises';
import path from 'path';

import { setup } from './fixtures/utils.js';

/**
* Tests the circuit recorder is working as expected. To read more about it, check JSDoc of CircuitRecorder class.
*/
describe('Circuit Recorder', () => {
const RECORD_DIR = './circuit_recordings';

it('records circuit execution', async () => {
// Set recording directory env var - this will activate the circuit recorder
process.env.CIRCUIT_RECORD_DIR = RECORD_DIR;

// Run setup which deploys an account contract and runs kernels
const { teardown } = await setup(1);

// Check recording directory exists
const dirExists = await fs.stat(RECORD_DIR).then(
stats => stats.isDirectory(),
() => false,
);
expect(dirExists).toBe(true);

// Check recording file of a user circuit (contract circuit) exists and has expected content
{
const files = await fs.readdir(RECORD_DIR);
expect(files.length).toBeGreaterThan(0);

const recordingFile = files.find(f => f.startsWith('SchnorrAccount_constructor'));
expect(recordingFile).toBeDefined();

const recordingContent = await fs.readFile(path.join(RECORD_DIR, recordingFile!), 'utf8');
const recording = JSON.parse(recordingContent);

expect(recording).toMatchObject({
circuitName: 'SchnorrAccount',
functionName: 'constructor',
inputs: expect.any(Object),
oracleCalls: expect.any(Array),
});
}

// Then we'll do the same for a protocol circuit
{
const files = await fs.readdir(RECORD_DIR);
expect(files.length).toBeGreaterThan(0);

const recordingFile = files.find(f => f.startsWith('PrivateKernelInit_main'));
expect(recordingFile).toBeDefined();

const recordingContent = await fs.readFile(path.join(RECORD_DIR, recordingFile!), 'utf8');
const recording = JSON.parse(recordingContent);

expect(recording).toMatchObject({
circuitName: 'PrivateKernelInit',
functionName: 'main',
inputs: expect.any(Object),
oracleCalls: expect.any(Array),
});
}

// Cleanup
await fs.rm(RECORD_DIR, { recursive: true, force: true });
delete process.env.CIRCUIT_RECORD_DIR;
await teardown();
}, 20_000);
});
24 changes: 17 additions & 7 deletions yarn-project/end-to-end/src/fixtures/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import {
} from '@aztec/aztec.js';
import { deployInstance, registerContractClass } from '@aztec/aztec.js/deployment';
import { AnvilTestWatcher, CheatCodes } from '@aztec/aztec.js/testing';
import type { BBNativePrivateKernelProver } from '@aztec/bb-prover';
import { createBlobSinkClient } from '@aztec/blob-sink/client';
import { type BlobSinkServer, createBlobSinkServer } from '@aztec/blob-sink/server';
import { FEE_JUICE_INITIAL_MINT, GENESIS_ARCHIVE_ROOT, GENESIS_BLOCK_HASH } from '@aztec/constants';
Expand All @@ -52,9 +51,16 @@ import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice';
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
import { ProtocolContractAddress, protocolContractTreeRoot } from '@aztec/protocol-contracts';
import { type ProverNode, type ProverNodeConfig, createProverNode } from '@aztec/prover-node';
import { type PXEService, type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe/server';
import {
type PXEService,
type PXEServiceConfig,
createPXEServiceWithSimulationProvider,
getPXEServiceConfig,
} from '@aztec/pxe/server';
import type { SequencerClient } from '@aztec/sequencer-client';
import type { TestSequencerClient } from '@aztec/sequencer-client/test';
import { WASMSimulator } from '@aztec/simulator/client';
import { SimulationProviderRecorderWrapper } from '@aztec/simulator/testing';
import { getContractClassFromArtifact } from '@aztec/stdlib/contract';
import { Gas } from '@aztec/stdlib/gas';
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
Expand Down Expand Up @@ -135,18 +141,15 @@ export const setupL1Contracts = async (
* Sets up Private eXecution Environment (PXE).
* @param aztecNode - An instance of Aztec Node.
* @param opts - Partial configuration for the PXE service.
* @param firstPrivKey - The private key of the first account to be created.
* @param logger - The logger to be used.
* @param useLogSuffix - Whether to add a randomly generated suffix to the PXE debug logs.
* @param proofCreator - An optional proof creator to use
* @returns Private eXecution Environment (PXE), accounts, wallets and logger.
* @returns Private eXecution Environment (PXE), logger and teardown function.
*/
export async function setupPXEService(
aztecNode: AztecNode,
opts: Partial<PXEServiceConfig> = {},
logger = getLogger(),
useLogSuffix = false,
proofCreator?: BBNativePrivateKernelProver,
): Promise<{
/**
* The PXE instance.
Expand All @@ -169,7 +172,14 @@ export async function setupPXEService(
pxeServiceConfig.dataDirectory = path.join(tmpdir(), randomBytes(8).toString('hex'));
}

const pxe = await createPXEService(aztecNode, pxeServiceConfig, useLogSuffix, proofCreator);
const simulationProvider = new WASMSimulator();
const simulationProviderWithRecorder = new SimulationProviderRecorderWrapper(simulationProvider);
const pxe = await createPXEServiceWithSimulationProvider(
aztecNode,
simulationProviderWithRecorder,
pxeServiceConfig,
useLogSuffix,
);

const teardown = async () => {
if (!configuredDataDirectory) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
import type { NoirCompiledCircuit, NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
import type { VerificationKeyData } from '@aztec/stdlib/vks';

import PrivateKernelInitJson from '../../../artifacts/private_kernel_init.json' assert { type: 'json' };
Expand Down Expand Up @@ -30,12 +30,12 @@ export const SimulatedClientCircuitArtifacts: Record<ClientProtocolArtifact, Noi
};

export class BundleArtifactProvider implements ArtifactProvider {
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit> {
return Promise.resolve(ClientCircuitArtifacts[artifact]);
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName> {
return Promise.resolve({ ...ClientCircuitArtifacts[artifact], name: artifact.replace('Artifact', '') });
}

getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit> {
return Promise.resolve(SimulatedClientCircuitArtifacts[artifact]);
getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName> {
return Promise.resolve({ ...SimulatedClientCircuitArtifacts[artifact], name: artifact.replace('Artifact', '') });
}

getCircuitVkByName(artifact: ClientProtocolArtifact): Promise<VerificationKeyData> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
import type { NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
import type { VerificationKeyData } from '@aztec/stdlib/vks';

import {
Expand All @@ -9,11 +9,11 @@ import {
import type { ArtifactProvider, ClientProtocolArtifact } from '../types.js';

export class LazyArtifactProvider implements ArtifactProvider {
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit> {
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName> {
return getClientCircuitArtifact(ClientCircuitArtifactNames[artifact], false);
}

getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit> {
getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName> {
return getClientCircuitArtifact(ClientCircuitArtifactNames[artifact], true);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
import type { NoirCompiledCircuit, NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';

import BaseParityJson from '../../artifacts/parity_base.json' assert { type: 'json' };
import RootParityJson from '../../artifacts/parity_root.json' assert { type: 'json' };
Expand Down Expand Up @@ -41,3 +41,17 @@ export const SimulatedServerCircuitArtifacts: Record<ServerProtocolArtifact, Noi
BlockMergeRollupArtifact: BlockMergeRollupJson as NoirCompiledCircuit,
RootRollupArtifact: RootRollupJson as NoirCompiledCircuit,
};

export function getServerCircuitArtifact(name: ServerProtocolArtifact): NoirCompiledCircuitWithName {
return {
...ServerCircuitArtifacts[name],
name,
};
}

export function getSimulatedServerCircuitArtifact(name: ServerProtocolArtifact): NoirCompiledCircuitWithName {
return {
...SimulatedServerCircuitArtifacts[name],
name,
};
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
import type { NoirCompiledCircuitWithName } from '@aztec/stdlib/noir';
import type { VerificationKeyData } from '@aztec/stdlib/vks';

import type { PrivateResetArtifact } from '../private_kernel_reset_types.js';
Expand Down Expand Up @@ -26,7 +26,7 @@ export type ServerProtocolArtifact =
export type ProtocolArtifact = ServerProtocolArtifact | ClientProtocolArtifact;

export interface ArtifactProvider {
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit>;
getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuit>;
getClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName>;
getSimulatedClientCircuitArtifactByName(artifact: ClientProtocolArtifact): Promise<NoirCompiledCircuitWithName>;
getCircuitVkByName(artifact: ClientProtocolArtifact): Promise<VerificationKeyData>;
}
Loading
Loading