@aztec/ivc-integration 0.84.0 → 0.85.0
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.
- package/artifacts/app_creator.json +1 -1
- package/artifacts/app_reader.json +1 -1
- package/artifacts/keys/app_creator.vk.data.json +69 -69
- package/artifacts/keys/app_reader.vk.data.json +69 -69
- package/artifacts/keys/mock_private_kernel_init.vk.data.json +69 -69
- package/artifacts/keys/mock_private_kernel_inner.vk.data.json +69 -69
- package/artifacts/keys/mock_private_kernel_reset.vk.data.json +69 -69
- package/artifacts/keys/mock_private_kernel_tail.vk.data.json +69 -69
- package/artifacts/keys/mock_rollup_base_private.vk.data.json +144 -0
- package/artifacts/keys/mock_rollup_base_public.vk.data.d.json.ts +2 -0
- package/artifacts/keys/mock_rollup_base_public.vk.data.json +144 -0
- package/artifacts/keys/mock_rollup_merge.vk.data.d.json.ts +2 -0
- package/artifacts/keys/mock_rollup_merge.vk.data.json +144 -0
- package/artifacts/keys/mock_rollup_root.vk.data.d.json.ts +2 -0
- package/artifacts/keys/mock_rollup_root.vk.data.json +133 -0
- package/artifacts/keys/mock_rollup_root_verifier.sol +1914 -0
- package/artifacts/mock_private_kernel_init.json +1 -1
- package/artifacts/mock_private_kernel_inner.json +1 -1
- package/artifacts/mock_private_kernel_reset.json +1 -1
- package/artifacts/mock_private_kernel_tail.json +1 -1
- package/artifacts/mock_rollup_base_private.json +1 -0
- package/artifacts/mock_rollup_base_public.d.json.ts +3 -0
- package/artifacts/mock_rollup_base_public.json +1 -0
- package/artifacts/mock_rollup_merge.d.json.ts +3 -0
- package/artifacts/mock_rollup_merge.json +1 -0
- package/artifacts/mock_rollup_root.d.json.ts +3 -0
- package/artifacts/mock_rollup_root.json +1 -0
- package/dest/index.d.ts +1 -35
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -227
- package/dest/prove_native.d.ts +15 -0
- package/dest/prove_native.d.ts.map +1 -0
- package/dest/prove_native.js +105 -0
- package/dest/prove_wasm.d.ts +2 -0
- package/dest/prove_wasm.d.ts.map +1 -0
- package/dest/prove_wasm.js +17 -0
- package/dest/scripts/generate_ts_from_abi.js +4 -1
- package/dest/serve.js +2 -1
- package/dest/types/index.d.ts +41 -7
- package/dest/types/index.d.ts.map +1 -1
- package/dest/types/index.js +29 -2
- package/dest/witgen.d.ts +60 -0
- package/dest/witgen.d.ts.map +1 -0
- package/dest/witgen.js +335 -0
- package/package.json +15 -17
- package/src/index.ts +1 -260
- package/src/prove_native.ts +238 -0
- package/src/prove_wasm.ts +24 -0
- package/src/scripts/generate_ts_from_abi.ts +4 -1
- package/src/serve.ts +2 -1
- package/src/types/index.ts +72 -10
- package/src/witgen.ts +373 -0
- package/artifacts/keys/mock_public_base.vk.data.json +0 -133
- package/artifacts/mock_public_base.json +0 -1
- /package/artifacts/keys/{mock_public_base.vk.data.d.json.ts → mock_rollup_base_private.vk.data.d.json.ts} +0 -0
- /package/artifacts/{mock_public_base.d.json.ts → mock_rollup_base_private.d.json.ts} +0 -0
package/src/index.ts
CHANGED
|
@@ -1,260 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { type ForeignCallOutput, Noir } from '@aztec/noir-noir_js';
|
|
3
|
-
|
|
4
|
-
import createDebug from 'debug';
|
|
5
|
-
import { ungzip } from 'pako';
|
|
6
|
-
|
|
7
|
-
import MockAppCreatorCircuit from '../artifacts/app_creator.json' assert { type: 'json' };
|
|
8
|
-
import MockAppReaderCircuit from '../artifacts/app_reader.json' assert { type: 'json' };
|
|
9
|
-
import MockAppCreatorVk from '../artifacts/keys/app_creator.vk.data.json' assert { type: 'json' };
|
|
10
|
-
import MockAppReaderVk from '../artifacts/keys/app_reader.vk.data.json' assert { type: 'json' };
|
|
11
|
-
import MockPrivateKernelInitVk from '../artifacts/keys/mock_private_kernel_init.vk.data.json' assert { type: 'json' };
|
|
12
|
-
import MockPrivateKernelInnerVk from '../artifacts/keys/mock_private_kernel_inner.vk.data.json' assert { type: 'json' };
|
|
13
|
-
import MockPrivateKernelResetVk from '../artifacts/keys/mock_private_kernel_reset.vk.data.json' assert { type: 'json' };
|
|
14
|
-
import MockPrivateKernelTailVk from '../artifacts/keys/mock_private_kernel_tail.vk.data.json' assert { type: 'json' };
|
|
15
|
-
import MockPrivateKernelInitCircuit from '../artifacts/mock_private_kernel_init.json' assert { type: 'json' };
|
|
16
|
-
import MockPrivateKernelInnerCircuit from '../artifacts/mock_private_kernel_inner.json' assert { type: 'json' };
|
|
17
|
-
import MockPrivateKernelResetCircuit from '../artifacts/mock_private_kernel_reset.json' assert { type: 'json' };
|
|
18
|
-
import MockPrivateKernelTailCircuit from '../artifacts/mock_private_kernel_tail.json' assert { type: 'json' };
|
|
19
|
-
import MockPublicBaseCircuit from '../artifacts/mock_public_base.json' assert { type: 'json' };
|
|
20
|
-
import type {
|
|
21
|
-
AppCreatorInputType,
|
|
22
|
-
AppPublicInputs,
|
|
23
|
-
AppReaderInputType,
|
|
24
|
-
FixedLengthArray,
|
|
25
|
-
KernelPublicInputs,
|
|
26
|
-
MockPrivateKernelInitInputType,
|
|
27
|
-
MockPrivateKernelInnerInputType,
|
|
28
|
-
MockPrivateKernelResetInputType,
|
|
29
|
-
MockPrivateKernelTailInputType,
|
|
30
|
-
MockPublicBaseInputType,
|
|
31
|
-
PrivateKernelPublicInputs,
|
|
32
|
-
u8,
|
|
33
|
-
} from './types/index.js';
|
|
34
|
-
|
|
35
|
-
// Re export the circuit jsons
|
|
36
|
-
export {
|
|
37
|
-
MockAppCreatorCircuit,
|
|
38
|
-
MockAppReaderCircuit,
|
|
39
|
-
MockPrivateKernelInitCircuit,
|
|
40
|
-
MockPrivateKernelInnerCircuit,
|
|
41
|
-
MockPrivateKernelResetCircuit,
|
|
42
|
-
MockPrivateKernelTailCircuit,
|
|
43
|
-
MockPublicBaseCircuit,
|
|
44
|
-
MockAppCreatorVk,
|
|
45
|
-
MockAppReaderVk,
|
|
46
|
-
MockPrivateKernelInitVk,
|
|
47
|
-
MockPrivateKernelInnerVk,
|
|
48
|
-
MockPrivateKernelResetVk,
|
|
49
|
-
MockPrivateKernelTailVk,
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const logger = createDebug('aztec:ivc-test');
|
|
53
|
-
|
|
54
|
-
/* eslint-disable camelcase */
|
|
55
|
-
|
|
56
|
-
export const MOCK_MAX_COMMITMENTS_PER_TX = 4;
|
|
57
|
-
|
|
58
|
-
function foreignCallHandler(): Promise<ForeignCallOutput[]> {
|
|
59
|
-
throw new Error('Unexpected foreign call');
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface WitnessGenResult<PublicInputsType> {
|
|
63
|
-
witness: Uint8Array;
|
|
64
|
-
publicInputs: PublicInputsType;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export async function witnessGenCreatorAppMockCircuit(
|
|
68
|
-
args: AppCreatorInputType,
|
|
69
|
-
): Promise<WitnessGenResult<AppPublicInputs>> {
|
|
70
|
-
const program = new Noir(MockAppCreatorCircuit);
|
|
71
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
72
|
-
return {
|
|
73
|
-
witness,
|
|
74
|
-
publicInputs: returnValue as AppPublicInputs,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export async function witnessGenReaderAppMockCircuit(
|
|
79
|
-
args: AppReaderInputType,
|
|
80
|
-
): Promise<WitnessGenResult<AppPublicInputs>> {
|
|
81
|
-
const program = new Noir(MockAppReaderCircuit);
|
|
82
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
83
|
-
return {
|
|
84
|
-
witness,
|
|
85
|
-
publicInputs: returnValue as AppPublicInputs,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export async function witnessGenMockPrivateKernelInitCircuit(
|
|
90
|
-
args: MockPrivateKernelInitInputType,
|
|
91
|
-
): Promise<WitnessGenResult<PrivateKernelPublicInputs>> {
|
|
92
|
-
const program = new Noir(MockPrivateKernelInitCircuit);
|
|
93
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
94
|
-
return {
|
|
95
|
-
witness,
|
|
96
|
-
publicInputs: returnValue as PrivateKernelPublicInputs,
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export async function witnessGenMockPrivateKernelInnerCircuit(
|
|
101
|
-
args: MockPrivateKernelInnerInputType,
|
|
102
|
-
): Promise<WitnessGenResult<PrivateKernelPublicInputs>> {
|
|
103
|
-
const program = new Noir(MockPrivateKernelInnerCircuit);
|
|
104
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
105
|
-
return {
|
|
106
|
-
witness,
|
|
107
|
-
publicInputs: returnValue as PrivateKernelPublicInputs,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export async function witnessGenMockPrivateKernelResetCircuit(
|
|
112
|
-
args: MockPrivateKernelResetInputType,
|
|
113
|
-
): Promise<WitnessGenResult<PrivateKernelPublicInputs>> {
|
|
114
|
-
const program = new Noir(MockPrivateKernelResetCircuit);
|
|
115
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
116
|
-
return {
|
|
117
|
-
witness,
|
|
118
|
-
publicInputs: returnValue as PrivateKernelPublicInputs,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export async function witnessGenMockPrivateKernelTailCircuit(
|
|
123
|
-
args: MockPrivateKernelTailInputType,
|
|
124
|
-
): Promise<WitnessGenResult<KernelPublicInputs>> {
|
|
125
|
-
const program = new Noir(MockPrivateKernelTailCircuit);
|
|
126
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
127
|
-
return {
|
|
128
|
-
witness,
|
|
129
|
-
publicInputs: returnValue as KernelPublicInputs,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export async function witnessGenMockPublicBaseCircuit(args: MockPublicBaseInputType): Promise<WitnessGenResult<u8>> {
|
|
134
|
-
const program = new Noir(MockPublicBaseCircuit);
|
|
135
|
-
const { witness, returnValue } = await program.execute(args, foreignCallHandler);
|
|
136
|
-
return {
|
|
137
|
-
witness,
|
|
138
|
-
publicInputs: returnValue as u8,
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export function getVkAsFields(vk: {
|
|
143
|
-
keyAsBytes: string;
|
|
144
|
-
keyAsFields: string[];
|
|
145
|
-
}): FixedLengthArray<string, typeof CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS> {
|
|
146
|
-
return vk.keyAsFields as FixedLengthArray<string, typeof CLIENT_IVC_VERIFICATION_KEY_LENGTH_IN_FIELDS>;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export async function generate3FunctionTestingIVCStack(): Promise<[string[], Uint8Array[]]> {
|
|
150
|
-
const tx = {
|
|
151
|
-
number_of_calls: '0x1',
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
// Witness gen app and kernels
|
|
155
|
-
const appWitnessGenResult = await witnessGenCreatorAppMockCircuit({ commitments_to_create: ['0x1', '0x2'] });
|
|
156
|
-
logger('generated app mock circuit witness');
|
|
157
|
-
|
|
158
|
-
const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({
|
|
159
|
-
app_inputs: appWitnessGenResult.publicInputs,
|
|
160
|
-
tx,
|
|
161
|
-
app_vk: getVkAsFields(MockAppCreatorVk),
|
|
162
|
-
});
|
|
163
|
-
logger('generated mock private kernel init witness');
|
|
164
|
-
|
|
165
|
-
const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({
|
|
166
|
-
prev_kernel_public_inputs: initWitnessGenResult.publicInputs,
|
|
167
|
-
kernel_vk: getVkAsFields(MockPrivateKernelResetVk),
|
|
168
|
-
});
|
|
169
|
-
logger('generated mock private kernel tail witness');
|
|
170
|
-
|
|
171
|
-
// Create client IVC proof
|
|
172
|
-
const bytecodes = [
|
|
173
|
-
MockAppCreatorCircuit.bytecode,
|
|
174
|
-
MockPrivateKernelInitCircuit.bytecode,
|
|
175
|
-
MockPrivateKernelTailCircuit.bytecode,
|
|
176
|
-
];
|
|
177
|
-
const witnessStack = [appWitnessGenResult.witness, initWitnessGenResult.witness, tailWitnessGenResult.witness];
|
|
178
|
-
|
|
179
|
-
return [bytecodes, witnessStack];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
export async function generate6FunctionTestingIVCStack(): Promise<[string[], Uint8Array[]]> {
|
|
183
|
-
const tx = {
|
|
184
|
-
number_of_calls: '0x2',
|
|
185
|
-
};
|
|
186
|
-
// Witness gen app and kernels
|
|
187
|
-
const creatorAppWitnessGenResult = await witnessGenCreatorAppMockCircuit({ commitments_to_create: ['0x1', '0x2'] });
|
|
188
|
-
const readerAppWitnessGenResult = await witnessGenReaderAppMockCircuit({ commitments_to_read: ['0x2', '0x0'] });
|
|
189
|
-
|
|
190
|
-
const initWitnessGenResult = await witnessGenMockPrivateKernelInitCircuit({
|
|
191
|
-
app_inputs: creatorAppWitnessGenResult.publicInputs,
|
|
192
|
-
tx,
|
|
193
|
-
app_vk: getVkAsFields(MockAppCreatorVk),
|
|
194
|
-
});
|
|
195
|
-
const innerWitnessGenResult = await witnessGenMockPrivateKernelInnerCircuit({
|
|
196
|
-
prev_kernel_public_inputs: initWitnessGenResult.publicInputs,
|
|
197
|
-
app_inputs: readerAppWitnessGenResult.publicInputs,
|
|
198
|
-
app_vk: getVkAsFields(MockAppReaderVk),
|
|
199
|
-
kernel_vk: getVkAsFields(MockPrivateKernelInitVk),
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
const resetWitnessGenResult = await witnessGenMockPrivateKernelResetCircuit({
|
|
203
|
-
prev_kernel_public_inputs: innerWitnessGenResult.publicInputs,
|
|
204
|
-
commitment_read_hints: [
|
|
205
|
-
'0x1', // Reader reads commitment 0x2, which is at index 1 of the created commitments
|
|
206
|
-
MOCK_MAX_COMMITMENTS_PER_TX.toString(), // Pad with no-ops
|
|
207
|
-
MOCK_MAX_COMMITMENTS_PER_TX.toString(),
|
|
208
|
-
MOCK_MAX_COMMITMENTS_PER_TX.toString(),
|
|
209
|
-
],
|
|
210
|
-
kernel_vk: getVkAsFields(MockPrivateKernelInnerVk),
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
const tailWitnessGenResult = await witnessGenMockPrivateKernelTailCircuit({
|
|
214
|
-
prev_kernel_public_inputs: resetWitnessGenResult.publicInputs,
|
|
215
|
-
kernel_vk: getVkAsFields(MockPrivateKernelResetVk),
|
|
216
|
-
});
|
|
217
|
-
|
|
218
|
-
// Create client IVC proof
|
|
219
|
-
const bytecodes = [
|
|
220
|
-
MockAppCreatorCircuit.bytecode,
|
|
221
|
-
MockPrivateKernelInitCircuit.bytecode,
|
|
222
|
-
MockAppReaderCircuit.bytecode,
|
|
223
|
-
MockPrivateKernelInnerCircuit.bytecode,
|
|
224
|
-
MockPrivateKernelResetCircuit.bytecode,
|
|
225
|
-
MockPrivateKernelTailCircuit.bytecode,
|
|
226
|
-
];
|
|
227
|
-
const witnessStack = [
|
|
228
|
-
creatorAppWitnessGenResult.witness,
|
|
229
|
-
initWitnessGenResult.witness,
|
|
230
|
-
readerAppWitnessGenResult.witness,
|
|
231
|
-
innerWitnessGenResult.witness,
|
|
232
|
-
resetWitnessGenResult.witness,
|
|
233
|
-
tailWitnessGenResult.witness,
|
|
234
|
-
];
|
|
235
|
-
|
|
236
|
-
return [bytecodes, witnessStack];
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function base64ToUint8Array(base64: string): Uint8Array {
|
|
240
|
-
return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
export async function proveThenVerifyAztecClient(
|
|
244
|
-
bytecodes: string[],
|
|
245
|
-
witnessStack: Uint8Array[],
|
|
246
|
-
threads?: number,
|
|
247
|
-
): Promise<boolean> {
|
|
248
|
-
const { AztecClientBackend } = await import('@aztec/bb.js');
|
|
249
|
-
const backend = new AztecClientBackend(
|
|
250
|
-
bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr)),
|
|
251
|
-
{ threads },
|
|
252
|
-
);
|
|
253
|
-
try {
|
|
254
|
-
const [proof, vk] = await backend.prove(witnessStack.map((arr: Uint8Array) => ungzip(arr)));
|
|
255
|
-
const verified = await backend.verify(proof, vk);
|
|
256
|
-
return verified;
|
|
257
|
-
} finally {
|
|
258
|
-
await backend.destroy();
|
|
259
|
-
}
|
|
260
|
-
}
|
|
1
|
+
export * from './witgen.js';
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BB_RESULT,
|
|
3
|
+
PROOF_FILENAME,
|
|
4
|
+
PUBLIC_INPUTS_FILENAME,
|
|
5
|
+
type UltraHonkFlavor,
|
|
6
|
+
VK_FILENAME,
|
|
7
|
+
executeBbClientIvcProof,
|
|
8
|
+
extractVkData,
|
|
9
|
+
generateAvmProofV2,
|
|
10
|
+
generateProof,
|
|
11
|
+
generateTubeProof,
|
|
12
|
+
readClientIVCProofFromOutputDirectory,
|
|
13
|
+
readProofAsFields,
|
|
14
|
+
verifyProof,
|
|
15
|
+
} from '@aztec/bb-prover';
|
|
16
|
+
import {
|
|
17
|
+
AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED,
|
|
18
|
+
AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED,
|
|
19
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
20
|
+
RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
21
|
+
TUBE_PROOF_LENGTH,
|
|
22
|
+
} from '@aztec/constants';
|
|
23
|
+
import { Fr } from '@aztec/foundation/fields';
|
|
24
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
25
|
+
import { BufferReader } from '@aztec/foundation/serialize';
|
|
26
|
+
import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm';
|
|
27
|
+
import { makeProofAndVerificationKey } from '@aztec/stdlib/interfaces/server';
|
|
28
|
+
import type { NoirCompiledCircuit } from '@aztec/stdlib/noir';
|
|
29
|
+
import type { ClientIvcProof, Proof } from '@aztec/stdlib/proofs';
|
|
30
|
+
import type { VerificationKeyData } from '@aztec/stdlib/vks';
|
|
31
|
+
|
|
32
|
+
import { encode } from '@msgpack/msgpack';
|
|
33
|
+
import * as fs from 'fs/promises';
|
|
34
|
+
import * as path from 'path';
|
|
35
|
+
|
|
36
|
+
export async function proveClientIVC(
|
|
37
|
+
bbBinaryPath: string,
|
|
38
|
+
bbWorkingDirectory: string,
|
|
39
|
+
witnessStack: Uint8Array[],
|
|
40
|
+
bytecodes: string[],
|
|
41
|
+
logger: Logger,
|
|
42
|
+
): Promise<ClientIvcProof> {
|
|
43
|
+
await fs.writeFile(
|
|
44
|
+
path.join(bbWorkingDirectory, 'acir.msgpack'),
|
|
45
|
+
encode(bytecodes.map(bytecode => Buffer.from(bytecode, 'base64'))),
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
await fs.writeFile(path.join(bbWorkingDirectory, 'witnesses.msgpack'), encode(witnessStack));
|
|
49
|
+
const provingResult = await executeBbClientIvcProof(
|
|
50
|
+
bbBinaryPath,
|
|
51
|
+
bbWorkingDirectory,
|
|
52
|
+
path.join(bbWorkingDirectory, 'acir.msgpack'),
|
|
53
|
+
path.join(bbWorkingDirectory, 'witnesses.msgpack'),
|
|
54
|
+
logger.info,
|
|
55
|
+
true,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
if (provingResult.status === BB_RESULT.FAILURE) {
|
|
59
|
+
throw new Error(provingResult.reason);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return readClientIVCProofFromOutputDirectory(bbWorkingDirectory);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async function verifyProofWithKey(
|
|
66
|
+
pathToBB: string,
|
|
67
|
+
workingDirectory: string,
|
|
68
|
+
verificationKey: VerificationKeyData,
|
|
69
|
+
proof: Proof,
|
|
70
|
+
flavor: UltraHonkFlavor,
|
|
71
|
+
logger: Logger,
|
|
72
|
+
) {
|
|
73
|
+
const publicInputsFileName = path.join(workingDirectory, PUBLIC_INPUTS_FILENAME);
|
|
74
|
+
const proofFileName = path.join(workingDirectory, PROOF_FILENAME);
|
|
75
|
+
const verificationKeyPath = path.join(workingDirectory, VK_FILENAME);
|
|
76
|
+
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class.
|
|
77
|
+
await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32));
|
|
78
|
+
await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32));
|
|
79
|
+
await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes);
|
|
80
|
+
|
|
81
|
+
const result = await verifyProof(pathToBB, proofFileName, verificationKeyPath, flavor, logger);
|
|
82
|
+
if (result.status === BB_RESULT.FAILURE) {
|
|
83
|
+
throw new Error(`Failed to verify proof from key!`);
|
|
84
|
+
}
|
|
85
|
+
logger.info(`Successfully verified proof from key in ${result.durationMs} ms`);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export async function proveTube(pathToBB: string, workingDirectory: string, logger: Logger) {
|
|
89
|
+
const tubeResult = await generateTubeProof(pathToBB, workingDirectory, workingDirectory.concat('/vk'), logger.info);
|
|
90
|
+
|
|
91
|
+
if (tubeResult.status != BB_RESULT.SUCCESS) {
|
|
92
|
+
throw new Error('Failed to prove tube');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const tubeVK = await extractVkData(tubeResult.vkPath!);
|
|
96
|
+
const tubeProof = await readProofAsFields(tubeResult.proofPath!, tubeVK, TUBE_PROOF_LENGTH, logger);
|
|
97
|
+
|
|
98
|
+
// Sanity check the tube proof
|
|
99
|
+
await verifyProofWithKey(pathToBB, workingDirectory, tubeVK, tubeProof.binaryProof, 'ultra_rollup_honk', logger);
|
|
100
|
+
|
|
101
|
+
return makeProofAndVerificationKey(tubeProof, tubeVK);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function proveRollupCircuit<T extends UltraHonkFlavor, ProofLength extends number>(
|
|
105
|
+
name: string,
|
|
106
|
+
pathToBB: string,
|
|
107
|
+
workingDirectory: string,
|
|
108
|
+
circuit: NoirCompiledCircuit,
|
|
109
|
+
witness: Uint8Array,
|
|
110
|
+
logger: Logger,
|
|
111
|
+
flavor: T,
|
|
112
|
+
proofLength: ProofLength,
|
|
113
|
+
) {
|
|
114
|
+
await fs.writeFile(path.join(workingDirectory, 'witness.gz'), witness);
|
|
115
|
+
const proofResult = await generateProof(
|
|
116
|
+
pathToBB,
|
|
117
|
+
workingDirectory,
|
|
118
|
+
name,
|
|
119
|
+
Buffer.from(circuit.bytecode, 'base64'),
|
|
120
|
+
true,
|
|
121
|
+
path.join(workingDirectory, 'witness.gz'),
|
|
122
|
+
flavor,
|
|
123
|
+
logger.info,
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
if (proofResult.status != BB_RESULT.SUCCESS) {
|
|
127
|
+
throw new Error(`Failed to generate proof for ${name} with flavor ${flavor}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const vk = await extractVkData(proofResult.vkPath!);
|
|
131
|
+
const proof = await readProofAsFields(proofResult.proofPath!, vk, proofLength, logger);
|
|
132
|
+
|
|
133
|
+
await verifyProofWithKey(pathToBB, workingDirectory, vk, proof.binaryProof, flavor, logger);
|
|
134
|
+
|
|
135
|
+
return makeProofAndVerificationKey(proof, vk);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function proveRollupHonk(
|
|
139
|
+
name: string,
|
|
140
|
+
pathToBB: string,
|
|
141
|
+
workingDirectory: string,
|
|
142
|
+
circuit: NoirCompiledCircuit,
|
|
143
|
+
witness: Uint8Array,
|
|
144
|
+
logger: Logger,
|
|
145
|
+
) {
|
|
146
|
+
return proveRollupCircuit(
|
|
147
|
+
name,
|
|
148
|
+
pathToBB,
|
|
149
|
+
workingDirectory,
|
|
150
|
+
circuit,
|
|
151
|
+
witness,
|
|
152
|
+
logger,
|
|
153
|
+
'ultra_rollup_honk',
|
|
154
|
+
RECURSIVE_ROLLUP_HONK_PROOF_LENGTH,
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function proveKeccakHonk(
|
|
159
|
+
name: string,
|
|
160
|
+
pathToBB: string,
|
|
161
|
+
workingDirectory: string,
|
|
162
|
+
circuit: NoirCompiledCircuit,
|
|
163
|
+
witness: Uint8Array,
|
|
164
|
+
logger: Logger,
|
|
165
|
+
) {
|
|
166
|
+
return proveRollupCircuit(
|
|
167
|
+
name,
|
|
168
|
+
pathToBB,
|
|
169
|
+
workingDirectory,
|
|
170
|
+
circuit,
|
|
171
|
+
witness,
|
|
172
|
+
logger,
|
|
173
|
+
'ultra_keccak_honk',
|
|
174
|
+
NESTED_RECURSIVE_PROOF_LENGTH,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export async function proveAvm(
|
|
179
|
+
avmCircuitInputs: AvmCircuitInputs,
|
|
180
|
+
workingDirectory: string,
|
|
181
|
+
logger: Logger,
|
|
182
|
+
): Promise<{
|
|
183
|
+
vk: Fr[];
|
|
184
|
+
proof: Fr[];
|
|
185
|
+
publicInputs: AvmCircuitPublicInputs;
|
|
186
|
+
}> {
|
|
187
|
+
// The paths for the barretenberg binary and the write path are hardcoded for now.
|
|
188
|
+
const bbPath = path.resolve('../../barretenberg/cpp/build/bin/bb');
|
|
189
|
+
|
|
190
|
+
// Then we prove.
|
|
191
|
+
const proofRes = await generateAvmProofV2(bbPath, workingDirectory, avmCircuitInputs, logger);
|
|
192
|
+
if (proofRes.status === BB_RESULT.FAILURE) {
|
|
193
|
+
throw new Error(`AVM V2 proof generation failed: ${proofRes.reason}`);
|
|
194
|
+
} else if (proofRes.status === BB_RESULT.ALREADY_PRESENT) {
|
|
195
|
+
throw new Error(`AVM V2 proof already exists`);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const avmProofPath = proofRes.proofPath;
|
|
199
|
+
const avmVkPath = proofRes.vkPath;
|
|
200
|
+
expect(avmProofPath).toBeDefined();
|
|
201
|
+
expect(avmVkPath).toBeDefined();
|
|
202
|
+
|
|
203
|
+
// Read the binary proof
|
|
204
|
+
const avmProofBuffer = await fs.readFile(avmProofPath!);
|
|
205
|
+
const reader = BufferReader.asReader(avmProofBuffer);
|
|
206
|
+
|
|
207
|
+
const proof: Fr[] = [];
|
|
208
|
+
while (!reader.isEmpty()) {
|
|
209
|
+
proof.push(Fr.fromBuffer(reader));
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// We extend to a fixed-size padded proof as during development any new AVM circuit column changes the
|
|
213
|
+
// proof length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
214
|
+
// TODO(#13390): Revive a non-padded AVM proof
|
|
215
|
+
while (proof.length < AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED) {
|
|
216
|
+
proof.push(new Fr(0));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Read the key
|
|
220
|
+
const vkBuffer = await fs.readFile(avmVkPath!);
|
|
221
|
+
const vkReader = BufferReader.asReader(vkBuffer);
|
|
222
|
+
const vk: Fr[] = [];
|
|
223
|
+
while (!vkReader.isEmpty()) {
|
|
224
|
+
vk.push(Fr.fromBuffer(vkReader));
|
|
225
|
+
}
|
|
226
|
+
// We extend to a fixed-size padded vk as during development any new AVM circuit precomputed
|
|
227
|
+
// column changes the vk length and we do not have a mechanism to feedback a cpp constant to noir/TS.
|
|
228
|
+
// TODO(#13390): Revive a non-padded vk proof
|
|
229
|
+
while (vk.length < AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED) {
|
|
230
|
+
vk.push(new Fr(0));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
proof,
|
|
235
|
+
vk,
|
|
236
|
+
publicInputs: avmCircuitInputs.publicInputs,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ungzip } from 'pako';
|
|
2
|
+
|
|
3
|
+
function base64ToUint8Array(base64: string): Uint8Array {
|
|
4
|
+
return Uint8Array.from(atob(base64), c => c.charCodeAt(0));
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export async function proveThenVerifyAztecClient(
|
|
8
|
+
bytecodes: string[],
|
|
9
|
+
witnessStack: Uint8Array[],
|
|
10
|
+
threads?: number,
|
|
11
|
+
): Promise<boolean> {
|
|
12
|
+
const { AztecClientBackend } = await import('@aztec/bb.js');
|
|
13
|
+
const backend = new AztecClientBackend(
|
|
14
|
+
bytecodes.map(base64ToUint8Array).map((arr: Uint8Array) => ungzip(arr)),
|
|
15
|
+
{ threads },
|
|
16
|
+
);
|
|
17
|
+
try {
|
|
18
|
+
const [proof, vk] = await backend.prove(witnessStack.map((arr: Uint8Array) => ungzip(arr)));
|
|
19
|
+
const verified = await backend.verify(proof, vk);
|
|
20
|
+
return verified;
|
|
21
|
+
} finally {
|
|
22
|
+
await backend.destroy();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -14,7 +14,10 @@ const circuits = [
|
|
|
14
14
|
'mock_private_kernel_inner',
|
|
15
15
|
'mock_private_kernel_reset',
|
|
16
16
|
'mock_private_kernel_tail',
|
|
17
|
-
'
|
|
17
|
+
'mock_rollup_base_public',
|
|
18
|
+
'mock_rollup_base_private',
|
|
19
|
+
'mock_rollup_merge',
|
|
20
|
+
'mock_rollup_root',
|
|
18
21
|
];
|
|
19
22
|
|
|
20
23
|
const main = async () => {
|
package/src/serve.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import createDebug from 'debug';
|
|
2
2
|
|
|
3
|
-
import { generate3FunctionTestingIVCStack
|
|
3
|
+
import { generate3FunctionTestingIVCStack } from './index.js';
|
|
4
|
+
import { proveThenVerifyAztecClient } from './prove_wasm.js';
|
|
4
5
|
|
|
5
6
|
const logger = createDebug('aztec:ivc-test');
|
|
6
7
|
|
package/src/types/index.ts
CHANGED
|
@@ -10,7 +10,6 @@ export { type ForeignCallHandler } from "@aztec/noir-noir_js"
|
|
|
10
10
|
export type FixedLengthArray<T, L extends number> = L extends 0 ? never[]: T[] & { length: L }
|
|
11
11
|
export type Field = string;
|
|
12
12
|
export type u32 = string;
|
|
13
|
-
export type u8 = string;
|
|
14
13
|
|
|
15
14
|
export type AppPublicInputs = {
|
|
16
15
|
commitments: FixedLengthArray<Field, 2>;
|
|
@@ -31,6 +30,27 @@ export type KernelPublicInputs = {
|
|
|
31
30
|
commitments: FixedLengthArray<Field, 4>;
|
|
32
31
|
}
|
|
33
32
|
|
|
33
|
+
export type TubeData = {
|
|
34
|
+
public_inputs: KernelPublicInputs;
|
|
35
|
+
proof: FixedLengthArray<Field, 535>;
|
|
36
|
+
vk_data: VerificationKey;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type VerificationKey = {
|
|
40
|
+
key: FixedLengthArray<Field, 139>;
|
|
41
|
+
hash: Field;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type RollupPublicInputs = {
|
|
45
|
+
accumulated: u32;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type PreviousRollupData = {
|
|
49
|
+
base_or_merge_public_inputs: RollupPublicInputs;
|
|
50
|
+
proof: FixedLengthArray<Field, 535>;
|
|
51
|
+
vk: VerificationKey;
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
|
|
35
55
|
export type AppCreatorInputType = {
|
|
36
56
|
commitments_to_create: FixedLengthArray<Field, 2>;
|
|
@@ -118,18 +138,60 @@ export async function MockPrivateKernelTail(prev_kernel_public_inputs: PrivateKe
|
|
|
118
138
|
const { returnValue } = await program.execute(args, foreignCallHandler);
|
|
119
139
|
return returnValue as KernelPublicInputs;
|
|
120
140
|
}
|
|
121
|
-
export type
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
141
|
+
export type MockRollupBasePublicInputType = {
|
|
142
|
+
tube_data: TubeData;
|
|
143
|
+
verification_key: FixedLengthArray<Field, 1000>;
|
|
144
|
+
proof: FixedLengthArray<Field, 20000>;
|
|
145
|
+
pub_cols_flattened: FixedLengthArray<Field, 1>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type MockRollupBasePublicReturnType = RollupPublicInputs;
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
export async function MockRollupBasePublic(tube_data: TubeData, verification_key: FixedLengthArray<Field, 1000>, proof: FixedLengthArray<Field, 20000>, pub_cols_flattened: FixedLengthArray<Field, 1>, MockRollupBasePublic_circuit: CompiledCircuit, foreignCallHandler?: ForeignCallHandler): Promise<RollupPublicInputs> {
|
|
152
|
+
const program = new Noir(MockRollupBasePublic_circuit);
|
|
153
|
+
const args: InputMap = { tube_data, verification_key, proof, pub_cols_flattened };
|
|
154
|
+
const { returnValue } = await program.execute(args, foreignCallHandler);
|
|
155
|
+
return returnValue as RollupPublicInputs;
|
|
156
|
+
}
|
|
157
|
+
export type MockRollupBasePrivateInputType = {
|
|
158
|
+
tube_data: TubeData;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export type MockRollupBasePrivateReturnType = RollupPublicInputs;
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
export async function MockRollupBasePrivate(tube_data: TubeData, MockRollupBasePrivate_circuit: CompiledCircuit, foreignCallHandler?: ForeignCallHandler): Promise<RollupPublicInputs> {
|
|
165
|
+
const program = new Noir(MockRollupBasePrivate_circuit);
|
|
166
|
+
const args: InputMap = { tube_data };
|
|
167
|
+
const { returnValue } = await program.execute(args, foreignCallHandler);
|
|
168
|
+
return returnValue as RollupPublicInputs;
|
|
169
|
+
}
|
|
170
|
+
export type MockRollupMergeInputType = {
|
|
171
|
+
a: PreviousRollupData;
|
|
172
|
+
b: PreviousRollupData;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export type MockRollupMergeReturnType = RollupPublicInputs;
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
export async function MockRollupMerge(a: PreviousRollupData, b: PreviousRollupData, MockRollupMerge_circuit: CompiledCircuit, foreignCallHandler?: ForeignCallHandler): Promise<RollupPublicInputs> {
|
|
179
|
+
const program = new Noir(MockRollupMerge_circuit);
|
|
180
|
+
const args: InputMap = { a, b };
|
|
181
|
+
const { returnValue } = await program.execute(args, foreignCallHandler);
|
|
182
|
+
return returnValue as RollupPublicInputs;
|
|
183
|
+
}
|
|
184
|
+
export type MockRollupRootInputType = {
|
|
185
|
+
a: PreviousRollupData;
|
|
186
|
+
b: PreviousRollupData;
|
|
125
187
|
}
|
|
126
188
|
|
|
127
|
-
export type
|
|
189
|
+
export type MockRollupRootReturnType = RollupPublicInputs;
|
|
128
190
|
|
|
129
191
|
|
|
130
|
-
export async function
|
|
131
|
-
const program = new Noir(
|
|
132
|
-
const args: InputMap = {
|
|
192
|
+
export async function MockRollupRoot(a: PreviousRollupData, b: PreviousRollupData, MockRollupRoot_circuit: CompiledCircuit, foreignCallHandler?: ForeignCallHandler): Promise<RollupPublicInputs> {
|
|
193
|
+
const program = new Noir(MockRollupRoot_circuit);
|
|
194
|
+
const args: InputMap = { a, b };
|
|
133
195
|
const { returnValue } = await program.execute(args, foreignCallHandler);
|
|
134
|
-
return returnValue as
|
|
196
|
+
return returnValue as RollupPublicInputs;
|
|
135
197
|
}
|