@aztec/end-to-end 0.87.2 → 0.87.3
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/dest/bench/client_flows/benchmark.d.ts +59 -0
- package/dest/bench/client_flows/benchmark.d.ts.map +1 -0
- package/dest/bench/client_flows/benchmark.js +240 -0
- package/dest/bench/client_flows/client_flows_benchmark.d.ts +5 -3
- package/dest/bench/client_flows/client_flows_benchmark.d.ts.map +1 -1
- package/dest/bench/client_flows/client_flows_benchmark.js +24 -14
- package/dest/bench/client_flows/data_extractor.d.ts +0 -21
- package/dest/bench/client_flows/data_extractor.d.ts.map +1 -1
- package/dest/bench/client_flows/data_extractor.js +5 -122
- package/dest/bench/utils.d.ts +7 -0
- package/dest/bench/utils.d.ts.map +1 -1
- package/dest/e2e_p2p/shared.js +6 -2
- package/dest/fixtures/utils.d.ts.map +1 -1
- package/dest/fixtures/utils.js +7 -4
- package/package.json +34 -34
- package/src/bench/client_flows/benchmark.ts +308 -0
- package/src/bench/client_flows/client_flows_benchmark.ts +28 -10
- package/src/bench/client_flows/data_extractor.ts +8 -142
- package/src/bench/utils.ts +1 -1
- package/src/e2e_p2p/shared.ts +2 -2
- package/src/fixtures/utils.ts +7 -4
- package/dest/shared/capture_private_execution_steps.d.ts +0 -7
- package/dest/shared/capture_private_execution_steps.d.ts.map +0 -1
- package/dest/shared/capture_private_execution_steps.js +0 -49
- package/src/shared/capture_private_execution_steps.ts +0 -68
|
@@ -5,94 +5,16 @@ import { createLogger, logger } from '@aztec/foundation/log';
|
|
|
5
5
|
import { Timer } from '@aztec/foundation/timer';
|
|
6
6
|
import { WASMSimulator } from '@aztec/simulator/client';
|
|
7
7
|
import type { PrivateExecutionStep } from '@aztec/stdlib/kernel';
|
|
8
|
+
import type { ProvingTimings, SimulationTimings } from '@aztec/stdlib/tx';
|
|
8
9
|
|
|
9
10
|
import { Decoder } from 'msgpackr';
|
|
10
|
-
import assert from 'node:assert';
|
|
11
11
|
import { readFile, readdir, writeFile } from 'node:fs/promises';
|
|
12
12
|
import { join } from 'node:path';
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
type LogLevel = (typeof logLevel)[number];
|
|
16
|
-
|
|
17
|
-
type Log = {
|
|
18
|
-
type: LogLevel;
|
|
19
|
-
timestamp: number;
|
|
20
|
-
prefix: string;
|
|
21
|
-
message: string;
|
|
22
|
-
|
|
23
|
-
data: any;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
const GATE_TYPES = [
|
|
27
|
-
'ecc_op',
|
|
28
|
-
'busread',
|
|
29
|
-
'lookup',
|
|
30
|
-
'pub_inputs',
|
|
31
|
-
'arithmetic',
|
|
32
|
-
'delta_range',
|
|
33
|
-
'elliptic',
|
|
34
|
-
'aux',
|
|
35
|
-
'poseidon2_external',
|
|
36
|
-
'poseidon2_internal',
|
|
37
|
-
'overflow',
|
|
38
|
-
] as const;
|
|
39
|
-
|
|
40
|
-
type GateType = (typeof GATE_TYPES)[number];
|
|
41
|
-
|
|
42
|
-
type StructuredTrace = {
|
|
43
|
-
[k in GateType]: number;
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export class ProxyLogger {
|
|
47
|
-
private static instance: ProxyLogger;
|
|
48
|
-
private logs: Log[] = [];
|
|
49
|
-
|
|
50
|
-
private constructor() {}
|
|
51
|
-
|
|
52
|
-
static create() {
|
|
53
|
-
ProxyLogger.instance = new ProxyLogger();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
static getInstance() {
|
|
57
|
-
return ProxyLogger.instance;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
createLogger(prefix: string): Logger {
|
|
61
|
-
return new Proxy(createLogger(prefix), {
|
|
62
|
-
get: (target: Logger, prop: keyof Logger) => {
|
|
63
|
-
if (logLevel.includes(prop as (typeof logLevel)[number])) {
|
|
64
|
-
return function (this: Logger, ...data: Parameters<Logger[LogLevel]>) {
|
|
65
|
-
const loggingFn = prop as LogLevel;
|
|
66
|
-
const args = [loggingFn, prefix, ...data] as Parameters<ProxyLogger['handleLog']>;
|
|
67
|
-
ProxyLogger.getInstance().handleLog(...args);
|
|
68
|
-
target[loggingFn].call(this, ...[data[0], data[1]]);
|
|
69
|
-
};
|
|
70
|
-
} else {
|
|
71
|
-
return target[prop];
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
private handleLog(type: (typeof logLevel)[number], prefix: string, message: string, data: any) {
|
|
78
|
-
this.logs.unshift({ type, prefix, message, data, timestamp: Date.now() });
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
public flushLogs() {
|
|
82
|
-
this.logs = [];
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public getLogs() {
|
|
86
|
-
return this.logs;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
14
|
+
import { type Log, type ProverType, ProxyLogger, generateBenchmark } from './benchmark.js';
|
|
89
15
|
|
|
90
16
|
type NativeProverConfig = { bbBinaryPath?: string; bbWorkingDirectory?: string };
|
|
91
17
|
|
|
92
|
-
type ProverType = 'wasm' | 'native';
|
|
93
|
-
|
|
94
|
-
type Step = { fnName: string; gateCount: number; accGateCount?: number };
|
|
95
|
-
|
|
96
18
|
async function createProver(config: NativeProverConfig = {}, log: Logger) {
|
|
97
19
|
const simulationProvider = new WASMSimulator();
|
|
98
20
|
if (!config.bbBinaryPath || !config.bbWorkingDirectory) {
|
|
@@ -106,33 +28,6 @@ async function createProver(config: NativeProverConfig = {}, log: Logger) {
|
|
|
106
28
|
}
|
|
107
29
|
}
|
|
108
30
|
|
|
109
|
-
function getMinimumTrace(logs: Log[]): StructuredTrace {
|
|
110
|
-
const minimumMessage = 'Trace details:';
|
|
111
|
-
const minimumMessageIndex = logs.findIndex(log => log.message.includes(minimumMessage));
|
|
112
|
-
const candidateLogs = logs.slice(minimumMessageIndex - GATE_TYPES.length, minimumMessageIndex);
|
|
113
|
-
|
|
114
|
-
const traceLogs = candidateLogs
|
|
115
|
-
.filter(log => GATE_TYPES.some(type => log.message.includes(type)))
|
|
116
|
-
.map(log => log.message.split(/\t|\n/))
|
|
117
|
-
.flat()
|
|
118
|
-
.map(log => log.replace(/\(mem: .*\)/, '').trim())
|
|
119
|
-
.filter(Boolean);
|
|
120
|
-
|
|
121
|
-
const traceSizes = traceLogs.map(log => {
|
|
122
|
-
const [gateType, gateSizeStr] = log
|
|
123
|
-
.replace(/\n.*\)$/, '')
|
|
124
|
-
.replace(/bb - /, '')
|
|
125
|
-
.split(':')
|
|
126
|
-
.map(s => s.trim());
|
|
127
|
-
const gateSize = parseInt(gateSizeStr);
|
|
128
|
-
assert(GATE_TYPES.includes(gateType as GateType), `Gate type ${gateType} is not recognized`);
|
|
129
|
-
return { [gateType]: gateSize };
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
assert(traceSizes.length === GATE_TYPES.length, 'Decoded trace sizes do not match expected amount of gate types');
|
|
133
|
-
return traceSizes.reduce((acc, curr) => ({ ...acc, ...curr }), {}) as StructuredTrace;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
31
|
async function main() {
|
|
137
32
|
ProxyLogger.create();
|
|
138
33
|
const proxyLogger = ProxyLogger.getInstance();
|
|
@@ -160,15 +55,15 @@ async function main() {
|
|
|
160
55
|
});
|
|
161
56
|
const profileFile = await readFile(join(ivcFolder, flow, 'profile.json'));
|
|
162
57
|
const profile = JSON.parse(profileFile.toString()) as {
|
|
163
|
-
|
|
58
|
+
timings: ProvingTimings | SimulationTimings;
|
|
164
59
|
steps: {
|
|
165
|
-
|
|
60
|
+
functionName: string;
|
|
166
61
|
gateCount: number;
|
|
167
62
|
timings: { witgen: number; gateCount: number };
|
|
168
63
|
}[];
|
|
169
64
|
};
|
|
170
65
|
const privateExecutionSteps: PrivateExecutionStep[] = profile.steps.map((step, i) => ({
|
|
171
|
-
functionName: step.
|
|
66
|
+
functionName: step.functionName,
|
|
172
67
|
gateCount: step.gateCount,
|
|
173
68
|
bytecode: stepsFromFile[i].bytecode,
|
|
174
69
|
// TODO(AD) do we still want to take this from witness.json?
|
|
@@ -179,7 +74,6 @@ async function main() {
|
|
|
179
74
|
gateCount: step.timings.witgen,
|
|
180
75
|
},
|
|
181
76
|
}));
|
|
182
|
-
let stats: { duration: number; eventName: string; proofSize: number } | undefined;
|
|
183
77
|
|
|
184
78
|
let error: any;
|
|
185
79
|
let currentLogs: Log[] = [];
|
|
@@ -195,38 +89,10 @@ async function main() {
|
|
|
195
89
|
// Extract logs from this run from the proxy and write them to disk unconditionally
|
|
196
90
|
currentLogs = proxyLogger.getLogs();
|
|
197
91
|
await writeFile(join(ivcFolder, flow, 'logs.json'), JSON.stringify(currentLogs, null, 2));
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
stats = currentLogs[0].data as { duration: number; eventName: string; proofSize: number };
|
|
92
|
+
if (!(profile.timings as ProvingTimings).proving) {
|
|
93
|
+
(profile.timings as ProvingTimings).proving = provingTime;
|
|
201
94
|
}
|
|
202
|
-
|
|
203
|
-
const minimumTrace = getMinimumTrace(currentLogs);
|
|
204
|
-
|
|
205
|
-
const steps = profile.steps.reduce<Step[]>((acc, step, i) => {
|
|
206
|
-
const previousAccGateCount = i === 0 ? 0 : acc[i - 1].accGateCount!;
|
|
207
|
-
return [
|
|
208
|
-
...acc,
|
|
209
|
-
{
|
|
210
|
-
fnName: step.fnName,
|
|
211
|
-
gateCount: step.gateCount,
|
|
212
|
-
accGateCount: previousAccGateCount + step.gateCount,
|
|
213
|
-
timings: {
|
|
214
|
-
witgen: step.timings.witgen,
|
|
215
|
-
},
|
|
216
|
-
},
|
|
217
|
-
];
|
|
218
|
-
}, []);
|
|
219
|
-
const totalGateCount = steps[steps.length - 1].accGateCount;
|
|
220
|
-
const benchmark = {
|
|
221
|
-
syncTime: profile.syncTime,
|
|
222
|
-
provingTime,
|
|
223
|
-
proverType,
|
|
224
|
-
minimumTrace: minimumTrace,
|
|
225
|
-
totalGateCount,
|
|
226
|
-
stats,
|
|
227
|
-
steps,
|
|
228
|
-
error,
|
|
229
|
-
};
|
|
95
|
+
const benchmark = generateBenchmark(flow, currentLogs, profile.timings, privateExecutionSteps, proverType, error);
|
|
230
96
|
await writeFile(join(ivcFolder, flow, 'benchmark.json'), JSON.stringify(benchmark, null, 2));
|
|
231
97
|
proxyLogger.flushLogs();
|
|
232
98
|
}
|
package/src/bench/utils.ts
CHANGED
|
@@ -53,7 +53,7 @@ type MetricFilter = {
|
|
|
53
53
|
};
|
|
54
54
|
|
|
55
55
|
// See https://github.com/benchmark-action/github-action-benchmark/blob/e3c661617bc6aa55f26ae4457c737a55545a86a4/src/extract.ts#L659-L670
|
|
56
|
-
type GithubActionBenchmarkResult = {
|
|
56
|
+
export type GithubActionBenchmarkResult = {
|
|
57
57
|
name: string;
|
|
58
58
|
value: number;
|
|
59
59
|
range?: string;
|
package/src/e2e_p2p/shared.ts
CHANGED
|
@@ -48,7 +48,7 @@ export const createPXEServiceAndSubmitTransactions = async (
|
|
|
48
48
|
): Promise<NodeContext> => {
|
|
49
49
|
const rpcConfig = getRpcConfig();
|
|
50
50
|
rpcConfig.proverEnabled = false;
|
|
51
|
-
const pxeService = await createPXEService(node, rpcConfig, true);
|
|
51
|
+
const pxeService = await createPXEService(node, rpcConfig, { useLogSuffix: true });
|
|
52
52
|
|
|
53
53
|
const account = await getSchnorrAccount(
|
|
54
54
|
pxeService,
|
|
@@ -71,7 +71,7 @@ export async function createPXEServiceAndPrepareTransactions(
|
|
|
71
71
|
): Promise<{ pxeService: PXEService; txs: ProvenTx[]; node: AztecNodeService }> {
|
|
72
72
|
const rpcConfig = getRpcConfig();
|
|
73
73
|
rpcConfig.proverEnabled = false;
|
|
74
|
-
const pxe = await createPXEService(node, rpcConfig, true);
|
|
74
|
+
const pxe = await createPXEService(node, rpcConfig, { useLogSuffix: true });
|
|
75
75
|
|
|
76
76
|
const account = await getSchnorrAccount(pxe, fundedAccount.secret, fundedAccount.signingKey, fundedAccount.salt);
|
|
77
77
|
await account.register();
|
package/src/fixtures/utils.ts
CHANGED
|
@@ -59,8 +59,8 @@ import {
|
|
|
59
59
|
} from '@aztec/pxe/server';
|
|
60
60
|
import type { SequencerClient } from '@aztec/sequencer-client';
|
|
61
61
|
import type { TestSequencerClient } from '@aztec/sequencer-client/test';
|
|
62
|
-
import { WASMSimulator } from '@aztec/simulator/client';
|
|
63
|
-
import {
|
|
62
|
+
import { MemoryCircuitRecorder, SimulationProviderRecorderWrapper, WASMSimulator } from '@aztec/simulator/client';
|
|
63
|
+
import { FileCircuitRecorder } from '@aztec/simulator/testing';
|
|
64
64
|
import { getContractClassFromArtifact, getContractInstanceFromDeployParams } from '@aztec/stdlib/contract';
|
|
65
65
|
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
|
|
66
66
|
import type { PublicDataTreeLeaf } from '@aztec/stdlib/trees';
|
|
@@ -171,12 +171,15 @@ export async function setupPXEService(
|
|
|
171
171
|
}
|
|
172
172
|
|
|
173
173
|
const simulationProvider = new WASMSimulator();
|
|
174
|
-
const
|
|
174
|
+
const recorder = process.env.CIRCUIT_RECORD_DIR
|
|
175
|
+
? new FileCircuitRecorder(process.env.CIRCUIT_RECORD_DIR)
|
|
176
|
+
: new MemoryCircuitRecorder();
|
|
177
|
+
const simulationProviderWithRecorder = new SimulationProviderRecorderWrapper(simulationProvider, recorder);
|
|
175
178
|
const pxe = await createPXEServiceWithSimulationProvider(
|
|
176
179
|
aztecNode,
|
|
177
180
|
simulationProviderWithRecorder,
|
|
178
181
|
pxeServiceConfig,
|
|
179
|
-
useLogSuffix,
|
|
182
|
+
{ useLogSuffix },
|
|
180
183
|
);
|
|
181
184
|
|
|
182
185
|
const teardown = async () => {
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This module exposes the ability to capture the private exection steps that go into our "Client IVC" prover.
|
|
3
|
-
* These are used for debugging and benchmarking barretenberg (the prover component).
|
|
4
|
-
*/
|
|
5
|
-
import type { ContractFunctionInteraction, DeployMethod, DeployOptions, ProfileMethodOptions } from '@aztec/aztec.js/contracts';
|
|
6
|
-
export declare function capturePrivateExecutionStepsIfEnvSet(label: string, interaction: ContractFunctionInteraction | DeployMethod, opts?: Omit<ProfileMethodOptions & DeployOptions, 'profileMode'>, expectedSteps?: number): Promise<void>;
|
|
7
|
-
//# sourceMappingURL=capture_private_execution_steps.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"capture_private_execution_steps.d.ts","sourceRoot":"","sources":["../../src/shared/capture_private_execution_steps.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EACV,2BAA2B,EAC3B,YAAY,EACZ,aAAa,EACb,oBAAoB,EACrB,MAAM,2BAA2B,CAAC;AASnC,wBAAsB,oCAAoC,CACxD,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,2BAA2B,GAAG,YAAY,EACvD,IAAI,CAAC,EAAE,IAAI,CAAC,oBAAoB,GAAG,aAAa,EAAE,aAAa,CAAC,EAChE,aAAa,CAAC,EAAE,MAAM,iBA6CvB"}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This module exposes the ability to capture the private exection steps that go into our "Client IVC" prover.
|
|
3
|
-
* These are used for debugging and benchmarking barretenberg (the prover component).
|
|
4
|
-
*/ import { createLogger } from '@aztec/foundation/log';
|
|
5
|
-
import { serializePrivateExecutionSteps } from '@aztec/stdlib/kernel';
|
|
6
|
-
import { promises as fs } from 'fs';
|
|
7
|
-
import path from 'path';
|
|
8
|
-
const logger = createLogger('e2e:capture-private-execution-steps');
|
|
9
|
-
export async function capturePrivateExecutionStepsIfEnvSet(label, interaction, opts, expectedSteps) {
|
|
10
|
-
// Not included in env_var.ts as internal to e2e tests.
|
|
11
|
-
const ivcFolder = process.env.CAPTURE_IVC_FOLDER;
|
|
12
|
-
if (!ivcFolder) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
const profileMode = [
|
|
16
|
-
'execution-steps',
|
|
17
|
-
'full'
|
|
18
|
-
].includes(process.env.PROFILE_MODE ?? '') ? process.env.PROFILE_MODE : 'execution-steps';
|
|
19
|
-
logger.info(`Capturing client ivc execution profile for ${label} in mode ${profileMode}`);
|
|
20
|
-
const result = await interaction.profile({
|
|
21
|
-
...opts,
|
|
22
|
-
profileMode
|
|
23
|
-
});
|
|
24
|
-
if (expectedSteps !== undefined && result.executionSteps.length !== expectedSteps) {
|
|
25
|
-
throw new Error(`Expected ${expectedSteps} execution steps, got ${result.executionSteps.length}`);
|
|
26
|
-
}
|
|
27
|
-
const resultsDirectory = path.join(ivcFolder, label);
|
|
28
|
-
logger.info(`Writing private execution steps to ${resultsDirectory}`);
|
|
29
|
-
await fs.mkdir(resultsDirectory, {
|
|
30
|
-
recursive: true
|
|
31
|
-
});
|
|
32
|
-
// Write the client IVC files read by the prover.
|
|
33
|
-
const ivcInputsPath = path.join(resultsDirectory, 'ivc-inputs.msgpack');
|
|
34
|
-
await fs.writeFile(ivcInputsPath, serializePrivateExecutionSteps(result.executionSteps));
|
|
35
|
-
if (profileMode === 'full') {
|
|
36
|
-
// If we have gate counts, write the steps in human-readable format.
|
|
37
|
-
await fs.writeFile(path.join(resultsDirectory, 'profile.json'), JSON.stringify({
|
|
38
|
-
timings: result.timings,
|
|
39
|
-
steps: result.executionSteps.map((step)=>({
|
|
40
|
-
fnName: step.functionName,
|
|
41
|
-
gateCount: step.gateCount,
|
|
42
|
-
timings: step.timings
|
|
43
|
-
}))
|
|
44
|
-
}, null, 2));
|
|
45
|
-
// In full mode, we also write the raw witnesses in a more human-readable format.
|
|
46
|
-
await fs.writeFile(path.join(resultsDirectory, 'witnesses.json'), JSON.stringify(result.executionSteps.map((step)=>Object.fromEntries(step.witness))));
|
|
47
|
-
}
|
|
48
|
-
logger.info(`Wrote private execution steps to ${resultsDirectory}`);
|
|
49
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This module exposes the ability to capture the private exection steps that go into our "Client IVC" prover.
|
|
3
|
-
* These are used for debugging and benchmarking barretenberg (the prover component).
|
|
4
|
-
*/
|
|
5
|
-
import type {
|
|
6
|
-
ContractFunctionInteraction,
|
|
7
|
-
DeployMethod,
|
|
8
|
-
DeployOptions,
|
|
9
|
-
ProfileMethodOptions,
|
|
10
|
-
} from '@aztec/aztec.js/contracts';
|
|
11
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
12
|
-
import { serializePrivateExecutionSteps } from '@aztec/stdlib/kernel';
|
|
13
|
-
|
|
14
|
-
import { promises as fs } from 'fs';
|
|
15
|
-
import path from 'path';
|
|
16
|
-
|
|
17
|
-
const logger = createLogger('e2e:capture-private-execution-steps');
|
|
18
|
-
|
|
19
|
-
export async function capturePrivateExecutionStepsIfEnvSet(
|
|
20
|
-
label: string,
|
|
21
|
-
interaction: ContractFunctionInteraction | DeployMethod,
|
|
22
|
-
opts?: Omit<ProfileMethodOptions & DeployOptions, 'profileMode'>,
|
|
23
|
-
expectedSteps?: number,
|
|
24
|
-
) {
|
|
25
|
-
// Not included in env_var.ts as internal to e2e tests.
|
|
26
|
-
const ivcFolder = process.env.CAPTURE_IVC_FOLDER;
|
|
27
|
-
if (!ivcFolder) {
|
|
28
|
-
return;
|
|
29
|
-
}
|
|
30
|
-
const profileMode = ['execution-steps', 'full'].includes(process.env.PROFILE_MODE ?? '')
|
|
31
|
-
? (process.env.PROFILE_MODE as 'full' | 'execution-steps')
|
|
32
|
-
: 'execution-steps';
|
|
33
|
-
logger.info(`Capturing client ivc execution profile for ${label} in mode ${profileMode}`);
|
|
34
|
-
const result = await interaction.profile({ ...opts, profileMode });
|
|
35
|
-
if (expectedSteps !== undefined && result.executionSteps.length !== expectedSteps) {
|
|
36
|
-
throw new Error(`Expected ${expectedSteps} execution steps, got ${result.executionSteps.length}`);
|
|
37
|
-
}
|
|
38
|
-
const resultsDirectory = path.join(ivcFolder, label);
|
|
39
|
-
logger.info(`Writing private execution steps to ${resultsDirectory}`);
|
|
40
|
-
await fs.mkdir(resultsDirectory, { recursive: true });
|
|
41
|
-
// Write the client IVC files read by the prover.
|
|
42
|
-
const ivcInputsPath = path.join(resultsDirectory, 'ivc-inputs.msgpack');
|
|
43
|
-
await fs.writeFile(ivcInputsPath, serializePrivateExecutionSteps(result.executionSteps));
|
|
44
|
-
if (profileMode === 'full') {
|
|
45
|
-
// If we have gate counts, write the steps in human-readable format.
|
|
46
|
-
await fs.writeFile(
|
|
47
|
-
path.join(resultsDirectory, 'profile.json'),
|
|
48
|
-
JSON.stringify(
|
|
49
|
-
{
|
|
50
|
-
timings: result.timings,
|
|
51
|
-
steps: result.executionSteps.map(step => ({
|
|
52
|
-
fnName: step.functionName,
|
|
53
|
-
gateCount: step.gateCount,
|
|
54
|
-
timings: step.timings,
|
|
55
|
-
})),
|
|
56
|
-
},
|
|
57
|
-
null,
|
|
58
|
-
2,
|
|
59
|
-
),
|
|
60
|
-
);
|
|
61
|
-
// In full mode, we also write the raw witnesses in a more human-readable format.
|
|
62
|
-
await fs.writeFile(
|
|
63
|
-
path.join(resultsDirectory, 'witnesses.json'),
|
|
64
|
-
JSON.stringify(result.executionSteps.map(step => Object.fromEntries(step.witness))),
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
logger.info(`Wrote private execution steps to ${resultsDirectory}`);
|
|
68
|
-
}
|