@aztec/ivc-integration 3.0.0-nightly.20251115 → 3.0.0-nightly.20251118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,8 +4,6 @@ import {
4
4
  PUBLIC_INPUTS_FILENAME,
5
5
  type UltraHonkFlavor,
6
6
  VK_FILENAME,
7
- executeBbChonkProof,
8
- extractVkData,
9
7
  generateAvmProof,
10
8
  generateProof,
11
9
  readProofsFromOutputDirectory,
@@ -16,6 +14,7 @@ import {
16
14
  AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
17
15
  AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED,
18
16
  CHONK_PROOF_LENGTH,
17
+ HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE,
19
18
  NESTED_RECURSIVE_PROOF_LENGTH,
20
19
  RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
21
20
  } from '@aztec/constants';
@@ -23,61 +22,33 @@ import { Fr } from '@aztec/foundation/fields';
23
22
  import type { Logger } from '@aztec/foundation/log';
24
23
  import { BufferReader } from '@aztec/foundation/serialize';
25
24
  import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
26
- import { type ProofAndVerificationKey, makeProofAndVerificationKey } from '@aztec/stdlib/interfaces/server';
25
+ import { makeProofAndVerificationKey } from '@aztec/stdlib/interfaces/server';
27
26
  import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
28
- import type { Proof } from '@aztec/stdlib/proofs';
27
+ import { Proof, RecursiveProof } from '@aztec/stdlib/proofs';
29
28
  import { enhanceProofWithPiValidationFlag } from '@aztec/stdlib/rollup';
30
29
  import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks';
31
30
 
32
31
  import * as fs from 'fs/promises';
33
- import { Encoder } from 'msgpackr';
34
32
  import * as path from 'path';
35
33
 
36
- /**
37
- * Converts verification key bytes from a compiled circuit to VerificationKeyData format
38
- * @param vkBytes - The verification key bytes from the circuit
39
- * @returns The verification key data
40
- */
41
- async function convertVkBytesToVkData(vkBytes: Buffer): Promise<VerificationKeyData> {
42
- // Convert binary to field elements (32 bytes per field)
43
- const numFields = vkBytes.length / Fr.SIZE_IN_BYTES;
44
- const reader = BufferReader.asReader(vkBytes);
45
- const fields = reader.readArray(numFields, Fr);
34
+ export async function proofBytesToRecursiveProof(
35
+ proofAsFields: Uint8Array[],
36
+ vkBytes: Uint8Array,
37
+ ): Promise<RecursiveProof<typeof CHONK_PROOF_LENGTH>> {
38
+ const vk = await VerificationKeyAsFields.fromFrBuffer(Buffer.from(vkBytes));
39
+ const numCustomPublicInputs = vk.numPublicInputs - HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE;
40
+ // Convert Uint8Array fields to Fr instances
41
+ const fields = proofAsFields.map(f => Fr.fromBuffer(Buffer.from(f)));
46
42
 
47
- const vkAsFields = await VerificationKeyAsFields.fromKey(fields);
48
- return new VerificationKeyData(vkAsFields, vkBytes);
49
- }
50
-
51
- export async function proveChonk(
52
- bbBinaryPath: string,
53
- bbWorkingDirectory: string,
54
- witnessStack: Uint8Array[],
55
- bytecodes: string[],
56
- vks: string[],
57
- logger: Logger,
58
- ): Promise<ProofAndVerificationKey<typeof CHONK_PROOF_LENGTH>> {
59
- const stepToStruct = (bytecode: string, index: number) => {
60
- return {
61
- bytecode: Buffer.from(bytecode, 'base64'),
62
- witness: witnessStack[index],
63
- vk: Buffer.from(vks[index], 'hex'),
64
- functionName: `unknown_${index}`,
65
- };
66
- };
67
- const encoded = new Encoder({ useRecords: false }).pack(bytecodes.map(stepToStruct));
68
- const ivcInputsPath = path.join(bbWorkingDirectory, 'ivc-inputs.msgpack');
69
- await fs.writeFile(ivcInputsPath, encoded);
43
+ // Slice off custom public inputs from the beginning.
44
+ const fieldsWithoutPublicInputs = fields.slice(numCustomPublicInputs);
70
45
 
71
- const provingResult = await executeBbChonkProof(bbBinaryPath, bbWorkingDirectory, ivcInputsPath, logger.info, true);
46
+ // Convert fields to binary buffer
47
+ const proofBuffer = Buffer.concat(proofAsFields.slice(numCustomPublicInputs));
72
48
 
73
- if (provingResult.status === BB_RESULT.FAILURE) {
74
- throw new Error(provingResult.reason);
75
- }
76
-
77
- const vk = await extractVkData(provingResult.vkDirectoryPath!);
78
- const proof = await readProofsFromOutputDirectory(provingResult.proofPath!, vk, CHONK_PROOF_LENGTH, logger);
79
-
80
- return makeProofAndVerificationKey(proof, vk);
49
+ // Create Proof directly (not using fromBuffer which expects different format)
50
+ const proof = new Proof(proofBuffer, numCustomPublicInputs);
51
+ return new RecursiveProof(fieldsWithoutPublicInputs, proof, true, CHONK_PROOF_LENGTH);
81
52
  }
82
53
 
83
54
  async function verifyProofWithKey(
@@ -130,7 +101,7 @@ async function proveRollupCircuit<T extends UltraHonkFlavor, ProofLength extends
130
101
  throw new Error(`Failed to generate proof for ${name} with flavor ${flavor}`);
131
102
  }
132
103
 
133
- const vk = await convertVkBytesToVkData(vkBuffer);
104
+ const vk = await VerificationKeyData.fromFrBuffer(vkBuffer);
134
105
  const proof = await readProofsFromOutputDirectory(proofResult.proofPath!, vk, proofLength, logger);
135
106
 
136
107
  await verifyProofWithKey(pathToBB, workingDirectory, vk, proof.binaryProof, flavor, logger);
package/src/serve.ts CHANGED
@@ -1,12 +1,27 @@
1
+ import { AztecClientBackend, Barretenberg } from '@aztec/bb.js';
1
2
  import { createLogger } from '@aztec/foundation/log';
2
3
 
3
- import { proveThenVerifyAztecClient } from './prove_wasm.js';
4
- import { generateTestingIVCStack } from './witgen.js';
4
+ import {
5
+ MockAppCreatorCircuit,
6
+ MockHidingCircuit,
7
+ MockPrivateKernelInitCircuit,
8
+ MockPrivateKernelTailCircuit,
9
+ generateTestingIVCStack,
10
+ } from './witgen.js';
5
11
 
6
12
  const logger = createLogger('aztec:ivc-test');
7
13
 
8
14
  /* eslint-disable no-console */
9
15
 
16
+ // Expose APIs on window for browser testing
17
+ (window as any).Barretenberg = Barretenberg;
18
+ (window as any).AztecClientBackend = AztecClientBackend;
19
+ (window as any).generateTestingIVCStack = generateTestingIVCStack;
20
+ (window as any).MockAppCreatorCircuit = MockAppCreatorCircuit;
21
+ (window as any).MockPrivateKernelInitCircuit = MockPrivateKernelInitCircuit;
22
+ (window as any).MockPrivateKernelTailCircuit = MockPrivateKernelTailCircuit;
23
+ (window as any).MockHidingCircuit = MockHidingCircuit;
24
+
10
25
  // Function to set up the output element and redirect all console output
11
26
  function setupConsoleOutput() {
12
27
  const container = document.createElement('div');
@@ -78,20 +93,32 @@ function setupConsoleOutput() {
78
93
  };
79
94
  }
80
95
 
81
- (window as any).proveThenVerifyAztecClient = proveThenVerifyAztecClient;
96
+ // Only set up the interactive UI if this is not being used for automated testing
97
+ if (!document.getElementById('status')) {
98
+ document.addEventListener('DOMContentLoaded', function () {
99
+ setupConsoleOutput(); // Initialize console output capture
100
+
101
+ const button = document.createElement('button');
102
+ button.innerText = 'Run Test';
103
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
104
+ button.addEventListener('click', async () => {
105
+ logger.info(`generating circuit and witness...`);
106
+ const [bytecodes, witnessStack, _publicInputs, precomputedVks] = await generateTestingIVCStack(1, 0);
107
+ logger.info(`done. proving and verifying...`);
108
+
109
+ const barretenberg = await Barretenberg.initSingleton({
110
+ threads: 16,
111
+ logger: (m: string) => logger.info(m),
112
+ });
113
+
114
+ const backend = new AztecClientBackend(bytecodes, barretenberg);
115
+ const [, proof, vk] = await backend.prove(witnessStack, precomputedVks);
116
+ const verified = await backend.verify(proof, vk);
82
117
 
83
- document.addEventListener('DOMContentLoaded', function () {
84
- setupConsoleOutput(); // Initialize console output capture
118
+ logger.info(`verified? ${verified}`);
85
119
 
86
- const button = document.createElement('button');
87
- button.innerText = 'Run Test';
88
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
89
- button.addEventListener('click', async () => {
90
- logger.info(`generating circuit and witness...`);
91
- const [bytecodes, witnessStack, _publicInputs, precomputedVks] = await generateTestingIVCStack(1, 0);
92
- logger.info(`done. proving and verifying...`);
93
- const verified = await proveThenVerifyAztecClient(bytecodes, witnessStack, precomputedVks);
94
- logger.info(`verified? ${verified}`);
120
+ await Barretenberg.destroySingleton();
121
+ });
122
+ document.body.appendChild(button);
95
123
  });
96
- document.body.appendChild(button);
97
- });
124
+ }
package/src/witgen.ts CHANGED
@@ -12,6 +12,7 @@ import type { RecursiveProof } from '@aztec/stdlib/proofs';
12
12
  import { VerificationKeyAsFields } from '@aztec/stdlib/vks';
13
13
 
14
14
  import { strict as assert } from 'assert';
15
+ import { ungzip } from 'pako';
15
16
 
16
17
  import MockAppCreatorCircuit from '../artifacts/app_creator.json' with { type: 'json' };
17
18
  import MockAppReaderCircuit from '../artifacts/app_reader.json' with { type: 'json' };
@@ -251,7 +252,7 @@ export async function generateTestingIVCStack(
251
252
  // A call to the reader app creates 1 read request. A reset kernel will be run if there are 2 read requests in the
252
253
  // public inputs. All read requests must be cleared before running the tail kernel.
253
254
  numReaderAppCalls: number,
254
- ): Promise<[string[], Uint8Array[], KernelPublicInputs, string[]]> {
255
+ ): Promise<[Uint8Array[], Uint8Array[], KernelPublicInputs, Uint8Array[]]> {
255
256
  if (numCreatorAppCalls > 2) {
256
257
  throw new Error('The creator app can only be called at most twice.');
257
258
  }
@@ -368,7 +369,22 @@ export async function generateTestingIVCStack(
368
369
  bytecodes.push(MockHidingCircuit.bytecode);
369
370
  vks.push(MockHidingVk.keyAsBytes);
370
371
 
371
- return [bytecodes, witnessStack, hidingWitnessGenResult.publicInputs, vks];
372
+ function base64ToUint8Array(base64: string): Uint8Array {
373
+ return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
374
+ }
375
+ function hexToUint8Array(hex: string): Uint8Array {
376
+ const cleaned = hex.replace(/^0x/i, '');
377
+ const bytes = new Uint8Array(cleaned.length / 2);
378
+ for (let i = 0; i < bytes.length; i++) {
379
+ bytes[i] = parseInt(cleaned.slice(i * 2, i * 2 + 2), 16);
380
+ }
381
+ return bytes;
382
+ }
383
+ const rawBytecodes = bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr));
384
+ const rawWitnessStack = witnessStack.map((arr: Uint8Array) => ungzip(arr));
385
+ const rawVks = vks.map(hexToUint8Array);
386
+
387
+ return [rawBytecodes, rawWitnessStack, hidingWitnessGenResult.publicInputs, rawVks];
372
388
  }
373
389
 
374
390
  export function mapRecursiveProofToNoir<N extends number>(proof: RecursiveProof<N>): FixedLengthArray<string, N> {
@@ -1,4 +0,0 @@
1
- import { ChonkProofWithPublicInputs } from '@aztec/stdlib/proofs';
2
- export declare function proveChonk(bytecodes: string[], witnessStack: Uint8Array[], vks: string[], threads?: number): Promise<ChonkProofWithPublicInputs>;
3
- export declare function proveThenVerifyAztecClient(bytecodes: string[], witnessStack: Uint8Array[], vks: string[], threads?: number): Promise<boolean>;
4
- //# sourceMappingURL=prove_wasm.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prove_wasm.d.ts","sourceRoot":"","sources":["../src/prove_wasm.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAWlE,wBAAsB,UAAU,CAC9B,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,EAAE,UAAU,EAAE,EAC1B,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,0BAA0B,CAAC,CAerC;AAED,wBAAsB,0BAA0B,CAC9C,SAAS,EAAE,MAAM,EAAE,EACnB,YAAY,EAAE,UAAU,EAAE,EAC1B,GAAG,EAAE,MAAM,EAAE,EACb,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAiBlB"}
@@ -1,38 +0,0 @@
1
- import { createLogger } from '@aztec/foundation/log';
2
- import { ChonkProofWithPublicInputs } from '@aztec/stdlib/proofs';
3
- import os from 'os';
4
- import { ungzip } from 'pako';
5
- const logger = createLogger('ivc-integration:prove_wasm');
6
- function base64ToUint8Array(base64) {
7
- return Uint8Array.from(atob(base64), (c)=>c.charCodeAt(0));
8
- }
9
- export async function proveChonk(bytecodes, witnessStack, vks, threads) {
10
- const { AztecClientBackend } = await import('@aztec/bb.js');
11
- const backend = new AztecClientBackend(bytecodes.map(base64ToUint8Array).map((arr)=>ungzip(arr)), {
12
- threads: threads || Math.min(os.cpus().length, 16),
13
- logger: logger.info,
14
- wasmPath: process.env.BB_WASM_PATH
15
- });
16
- try {
17
- const [proof] = await backend.prove(witnessStack.map((arr)=>ungzip(arr)), vks.map((hex)=>new Uint8Array(Buffer.from(hex, 'hex'))));
18
- return ChonkProofWithPublicInputs.fromBufferArray(proof);
19
- } finally{
20
- await backend.destroy();
21
- }
22
- }
23
- export async function proveThenVerifyAztecClient(bytecodes, witnessStack, vks, threads) {
24
- const { AztecClientBackend } = await import('@aztec/bb.js');
25
- const backend = new AztecClientBackend(bytecodes.map(base64ToUint8Array).map((arr)=>ungzip(arr)), {
26
- threads: threads || Math.min(os.cpus().length, 16),
27
- logger: logger.info,
28
- wasmPath: process.env.BB_WASM_PATH
29
- });
30
- try {
31
- // These are optional - easier not to pass them.
32
- const [_, msgpackProof, vk] = await backend.prove(witnessStack.map((arr)=>ungzip(arr)), vks.map((hex)=>new Uint8Array(Buffer.from(hex, 'hex'))));
33
- const verified = await backend.verify(msgpackProof, vk);
34
- return verified;
35
- } finally{
36
- await backend.destroy();
37
- }
38
- }
package/src/prove_wasm.ts DELETED
@@ -1,57 +0,0 @@
1
- import { createLogger } from '@aztec/foundation/log';
2
- import { ChonkProofWithPublicInputs } from '@aztec/stdlib/proofs';
3
-
4
- import os from 'os';
5
- import { ungzip } from 'pako';
6
-
7
- const logger = createLogger('ivc-integration:prove_wasm');
8
-
9
- function base64ToUint8Array(base64: string): Uint8Array {
10
- return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
11
- }
12
-
13
- export async function proveChonk(
14
- bytecodes: string[],
15
- witnessStack: Uint8Array[],
16
- vks: string[],
17
- threads?: number,
18
- ): Promise<ChonkProofWithPublicInputs> {
19
- const { AztecClientBackend } = await import('@aztec/bb.js');
20
- const backend = new AztecClientBackend(
21
- bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr)),
22
- { threads: threads || Math.min(os.cpus().length, 16), logger: logger.info, wasmPath: process.env.BB_WASM_PATH },
23
- );
24
- try {
25
- const [proof] = await backend.prove(
26
- witnessStack.map((arr: Uint8Array) => ungzip(arr)),
27
- vks.map(hex => new Uint8Array(Buffer.from(hex, 'hex'))),
28
- );
29
- return ChonkProofWithPublicInputs.fromBufferArray(proof);
30
- } finally {
31
- await backend.destroy();
32
- }
33
- }
34
-
35
- export async function proveThenVerifyAztecClient(
36
- bytecodes: string[],
37
- witnessStack: Uint8Array[],
38
- vks: string[],
39
- threads?: number,
40
- ): Promise<boolean> {
41
- const { AztecClientBackend } = await import('@aztec/bb.js');
42
- const backend = new AztecClientBackend(
43
- bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr)),
44
- { threads: threads || Math.min(os.cpus().length, 16), logger: logger.info, wasmPath: process.env.BB_WASM_PATH },
45
- );
46
- try {
47
- // These are optional - easier not to pass them.
48
- const [_, msgpackProof, vk] = await backend.prove(
49
- witnessStack.map((arr: Uint8Array) => ungzip(arr)),
50
- vks.map(hex => new Uint8Array(Buffer.from(hex, 'hex'))),
51
- );
52
- const verified = await backend.verify(msgpackProof, vk);
53
- return verified;
54
- } finally {
55
- await backend.destroy();
56
- }
57
- }