@tokamak-private-dapps/private-state-cli 2.1.1 → 2.2.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.
@@ -33,11 +33,20 @@ import {
33
33
  readGroth16CompatibleBackendVersionFromPackageJson,
34
34
  requireCanonicalGroth16CompatibleBackendVersion,
35
35
  } from "@tokamak-private-dapps/groth16/public-drive-crs";
36
+ import {
37
+ PRIVATE_STATE_CLI_COMMANDS,
38
+ privateStateCliCommandDisplay,
39
+ privateStateCliCommandInstallMode,
40
+ } from "./private-state-cli-command-registry.mjs";
36
41
 
37
42
  const require = createRequire(import.meta.url);
38
43
  const privateStateCliPackageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
39
44
  const defaultCommandCwd = process.cwd();
40
45
  const PRIVATE_STATE_DAPP_LABEL = "private-state";
46
+ const PRIVATE_STATE_INSTALL_MODES = Object.freeze({
47
+ FULL: "full",
48
+ READ_ONLY: "read-only",
49
+ });
41
50
  const DOCKER_CUDA_PROBE_IMAGE = "nvidia/cuda:12.2.0-base-ubuntu22.04";
42
51
  const DOCTOR_GPU_PROBE_TIMEOUT_MS = 120000;
43
52
  const GROTH16_PACKAGE_NAME = "@tokamak-private-dapps/groth16";
@@ -139,9 +148,13 @@ function printDoctorHumanReport(report) {
139
148
  `Generated: ${report.generatedAt}`,
140
149
  `Package: ${report.package.name}@${report.package.version ?? "unknown"}`,
141
150
  `Install manifest: ${report.installManifest.exists ? "found" : "missing"} (${report.installManifest.path})`,
151
+ `Install mode: ${report.installManifest.mode}`,
142
152
  "",
143
153
  formatDoctorTable(rows),
144
154
  "",
155
+ "Command availability",
156
+ formatDoctorCommandAvailabilityTable(report.commandAvailability),
157
+ "",
145
158
  "Run `help doctor --json` for the full machine-readable report.",
146
159
  ];
147
160
  console.log(lines.join("\n"));
@@ -155,6 +168,7 @@ function buildDoctorHumanRows(report) {
155
168
  .find((check) => check.name === "selected proof backend runtime versions")
156
169
  ?.details ?? [];
157
170
  const selectedVersionSummary = selectedVersionDetails
171
+ .filter((entry) => entry.name)
158
172
  .map((entry) => [
159
173
  `${entry.name}:`,
160
174
  `selected=${entry.selectedVersion ?? "none"}`,
@@ -163,6 +177,9 @@ function buildDoctorHumanRows(report) {
163
177
  entry.crsCompatibleBackendVersion ? `crs=${entry.crsCompatibleBackendVersion}` : null,
164
178
  ].filter(Boolean).join(" "))
165
179
  .join("; ");
180
+ const selectedVersionSkippedReason = selectedVersionDetails
181
+ .find((entry) => entry.skippedReason)
182
+ ?.skippedReason;
166
183
 
167
184
  return [
168
185
  {
@@ -172,12 +189,16 @@ function buildDoctorHumanRows(report) {
172
189
  },
173
190
  {
174
191
  check: "selected backend versions",
175
- status: doctorStatus(report.checks.find((check) => check.name === "selected proof backend runtime versions")?.ok),
176
- detail: selectedVersionSummary || "no selected runtime version pin",
192
+ status: report.checks.find((check) => check.name === "selected proof backend runtime versions")?.skipped
193
+ ? "SKIP"
194
+ : doctorStatus(report.checks.find((check) => check.name === "selected proof backend runtime versions")?.ok),
195
+ detail: selectedVersionSkippedReason ?? (selectedVersionSummary || "no selected runtime version pin"),
177
196
  },
178
197
  {
179
198
  check: "tokamak zk-evm runtime",
180
- status: doctorStatus(report.tokamakCli.installed),
199
+ status: report.checks.find((check) => check.name === "tokamak zk-evm runtime")?.skipped
200
+ ? "SKIP"
201
+ : doctorStatus(report.tokamakCli.installed),
181
202
  detail: [
182
203
  `package=${report.tokamakCli.packageVersion ?? "missing"}`,
183
204
  `cbv=${report.tokamakCli.compatibleBackendVersion ?? "missing"}`,
@@ -198,7 +219,9 @@ function buildDoctorHumanRows(report) {
198
219
  },
199
220
  {
200
221
  check: "groth16 runtime",
201
- status: doctorStatus(report.groth16Runtime.installed),
222
+ status: report.checks.find((check) => check.name === "groth16 runtime")?.skipped
223
+ ? "SKIP"
224
+ : doctorStatus(report.groth16Runtime.installed),
202
225
  detail: [
203
226
  `package=${report.groth16Runtime.packageVersion ?? "missing"}`,
204
227
  `cbv=${report.groth16Runtime.compatibleBackendVersion ?? "missing"}`,
@@ -207,6 +230,20 @@ function buildDoctorHumanRows(report) {
207
230
  `doctorStatus=${report.groth16Runtime.doctor.status}`,
208
231
  ].join(" "),
209
232
  },
233
+ {
234
+ check: `${report.installManifest.mode} deployment artifacts`,
235
+ status: doctorStatus(report.checks.find((check) => check.name === `${report.installManifest.mode} deployment artifacts`)?.ok),
236
+ detail: [
237
+ `readOnlyChains=${report.deploymentArtifacts.chains
238
+ .filter((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.READ_ONLY].ok)
239
+ .map((entry) => entry.chainId)
240
+ .join(",") || "none"}`,
241
+ `fullChains=${report.deploymentArtifacts.chains
242
+ .filter((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.FULL].ok)
243
+ .map((entry) => entry.chainId)
244
+ .join(",") || "none"}`,
245
+ ].join(" "),
246
+ },
210
247
  ];
211
248
  }
212
249
 
@@ -235,12 +272,55 @@ function formatDoctorTable(rows) {
235
272
  ].join("\n");
236
273
  }
237
274
 
275
+ function formatDoctorCommandAvailabilityTable(entries) {
276
+ const headers = ["Command", "Mode", "Status", "Detail"];
277
+ const rows = entries.map((entry) => ({
278
+ command: entry.display,
279
+ mode: entry.requiredInstallMode,
280
+ status: entry.available ? "OK" : "FAIL",
281
+ detail: entry.available
282
+ ? (entry.chains.length > 0 ? `chains=${entry.chains.join(",")}` : "no install artifacts required")
283
+ : entry.reasons.join("; "),
284
+ }));
285
+ const commandWidth = Math.max(headers[0].length, ...rows.map((row) => row.command.length));
286
+ const modeWidth = Math.max(headers[1].length, ...rows.map((row) => row.mode.length));
287
+ const statusWidth = Math.max(headers[2].length, ...rows.map((row) => row.status.length));
288
+ return [
289
+ [
290
+ headers[0].padEnd(commandWidth),
291
+ headers[1].padEnd(modeWidth),
292
+ headers[2].padEnd(statusWidth),
293
+ headers[3],
294
+ ].join(" "),
295
+ [
296
+ "-".repeat(commandWidth),
297
+ "-".repeat(modeWidth),
298
+ "-".repeat(statusWidth),
299
+ "-".repeat(headers[3].length),
300
+ ].join(" "),
301
+ ...rows.map((row) => [
302
+ row.command.padEnd(commandWidth),
303
+ row.mode.padEnd(modeWidth),
304
+ row.status.padEnd(statusWidth),
305
+ row.detail,
306
+ ].join(" ")),
307
+ ].join("\n");
308
+ }
309
+
238
310
  function doctorStatus(ok) {
239
311
  if (ok === true) return "OK";
240
312
  if (ok === false) return "FAIL";
241
313
  return "UNKNOWN";
242
314
  }
243
315
 
316
+ function normalizeInstallMode(value = PRIVATE_STATE_INSTALL_MODES.FULL) {
317
+ const normalized = String(value ?? PRIVATE_STATE_INSTALL_MODES.FULL).trim().toLowerCase();
318
+ if (normalized === PRIVATE_STATE_INSTALL_MODES.FULL || normalized === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
319
+ return normalized;
320
+ }
321
+ throw new Error(`Unsupported install mode: ${value}.`);
322
+ }
323
+
244
324
  function formatDoctorBool(value) {
245
325
  return value === true ? "true" : "false";
246
326
  }
@@ -281,6 +361,79 @@ function privateStateCliArtifactPaths(cacheBaseRoot = resolveArtifactCacheBaseRo
281
361
  };
282
362
  }
283
363
 
364
+ function privateStateCliArtifactRequiredFiles(paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
365
+ const normalizedInstallMode = normalizeInstallMode(installMode);
366
+ const readOnlyFiles = [
367
+ { label: "bridge deployment", path: paths.bridgeDeploymentPath },
368
+ { label: "bridge ABI manifest", path: paths.bridgeAbiManifestPath },
369
+ { label: "DApp deployment", path: paths.dappDeploymentPath },
370
+ { label: "DApp storage layout", path: paths.dappStorageLayoutPath },
371
+ ];
372
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
373
+ return readOnlyFiles;
374
+ }
375
+ return [
376
+ ...readOnlyFiles,
377
+ { label: "Groth16 manifest", path: paths.grothManifestPath },
378
+ { label: "Groth16 zkey", path: paths.grothZkeyPath },
379
+ { label: "PrivateStateController callable ABI", path: paths.privateStateControllerAbiPath },
380
+ { label: "DApp registration", path: paths.dappRegistrationPath },
381
+ ];
382
+ }
383
+
384
+ function inspectPrivateStateCliArtifactReadiness({
385
+ cacheBaseRoot = resolveArtifactCacheBaseRoot(),
386
+ installManifest = readPrivateStateCliInstallManifest(cacheBaseRoot),
387
+ } = {}) {
388
+ const chainIds = new Set(
389
+ (installManifest?.install?.installedDeploymentArtifacts ?? [])
390
+ .map((entry) => Number(entry.chainId))
391
+ .filter((chainId) => Number.isInteger(chainId)),
392
+ );
393
+ const artifactRoot = privateStateCliArtifactRoot(cacheBaseRoot);
394
+ if (fs.existsSync(artifactRoot)) {
395
+ for (const entry of fs.readdirSync(artifactRoot, { withFileTypes: true })) {
396
+ if (!entry.isDirectory()) {
397
+ continue;
398
+ }
399
+ const match = /^chain-id-(\d+)$/u.exec(entry.name);
400
+ if (match) {
401
+ chainIds.add(Number(match[1]));
402
+ }
403
+ }
404
+ }
405
+
406
+ const chains = [...chainIds].sort(compareChainIds).map((chainId) => {
407
+ const paths = privateStateCliArtifactPaths(cacheBaseRoot, chainId);
408
+ const modeStatus = Object.fromEntries(
409
+ Object.values(PRIVATE_STATE_INSTALL_MODES).map((mode) => {
410
+ const requiredFiles = privateStateCliArtifactRequiredFiles(paths, mode);
411
+ const missingFiles = requiredFiles
412
+ .filter((entry) => !fs.existsSync(entry.path))
413
+ .map((entry) => entry.path);
414
+ return [mode, {
415
+ ok: missingFiles.length === 0,
416
+ missingFiles,
417
+ requiredFiles: requiredFiles.map((entry) => entry.path),
418
+ }];
419
+ }),
420
+ );
421
+ return {
422
+ chainId,
423
+ rootDir: paths.rootDir,
424
+ modes: modeStatus,
425
+ };
426
+ });
427
+
428
+ return {
429
+ cacheBaseRoot,
430
+ artifactRoot,
431
+ chains,
432
+ readOnlyInstalled: chains.some((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.READ_ONLY].ok),
433
+ fullInstalled: chains.some((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.FULL].ok),
434
+ };
435
+ }
436
+
284
437
  function privateStateCliInstallManifestPath(cacheBaseRoot = resolveArtifactCacheBaseRoot()) {
285
438
  return path.join(privateStateCliArtifactRoot(cacheBaseRoot), "install-manifest.json");
286
439
  }
@@ -290,6 +443,7 @@ function readPrivateStateCliInstallManifest(cacheBaseRoot = resolveArtifactCache
290
443
  }
291
444
 
292
445
  function writePrivateStateCliInstallManifest({
446
+ installMode = PRIVATE_STATE_INSTALL_MODES.FULL,
293
447
  dockerRequested,
294
448
  includeLocalArtifacts,
295
449
  localDeploymentBaseRoot,
@@ -308,6 +462,7 @@ function writePrivateStateCliInstallManifest({
308
462
  dependencies: collectDependencyPackageReports().map(summarizePackageReport),
309
463
  install: {
310
464
  dockerRequested,
465
+ mode: normalizeInstallMode(installMode),
311
466
  includeLocalArtifacts,
312
467
  localDeploymentBaseRoot,
313
468
  artifactCacheRoot: deploymentArtifacts.cacheBaseRoot,
@@ -337,14 +492,24 @@ function buildDoctorReport({ probeGpu = false } = {}) {
337
492
  const cacheBaseRoot = resolveArtifactCacheBaseRoot();
338
493
  const installManifestPath = privateStateCliInstallManifestPath(cacheBaseRoot);
339
494
  const installManifest = readJsonIfExists(installManifestPath);
495
+ const installMode = normalizeInstallMode(installManifest?.install?.mode ?? PRIVATE_STATE_INSTALL_MODES.FULL);
496
+ const requiresProofRuntime = installMode === PRIVATE_STATE_INSTALL_MODES.FULL;
340
497
  const dependencyReports = collectDependencyPackageReports(installManifest);
341
- const tokamakCli = inspectTokamakCliRuntime();
342
- const groth16Runtime = inspectGroth16Runtime();
343
- const gpuDockerReadiness = probeGpu
498
+ const tokamakCli = requiresProofRuntime ? inspectTokamakCliRuntime() : { installed: false, doctor: { status: null }, installations: [] };
499
+ const groth16Runtime = requiresProofRuntime ? inspectGroth16Runtime() : { installed: false, doctor: { status: null }, checks: [] };
500
+ const gpuDockerReadiness = probeGpu && requiresProofRuntime
344
501
  ? inspectGpuDockerReadiness(tokamakCli)
345
502
  : buildSkippedGpuDockerReadiness(tokamakCli);
503
+ const artifactReadiness = inspectPrivateStateCliArtifactReadiness({ cacheBaseRoot, installManifest });
504
+ const commandAvailability = buildCommandAvailability({
505
+ artifactReadiness,
506
+ groth16Runtime,
507
+ installMode,
508
+ tokamakCli,
509
+ });
346
510
  const selectedRuntimeVersionCheck = buildSelectedRuntimeVersionCheck({
347
511
  installManifest,
512
+ installMode,
348
513
  tokamakCli,
349
514
  groth16Runtime,
350
515
  });
@@ -363,8 +528,12 @@ function buildDoctorReport({ probeGpu = false } = {}) {
363
528
  selectedRuntimeVersionCheck,
364
529
  {
365
530
  name: "tokamak zk-evm runtime",
366
- ok: tokamakCli.installed,
531
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY ? true : tokamakCli.installed,
532
+ skipped: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY,
367
533
  details: {
534
+ skippedReason: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
535
+ ? "read-only install mode does not require the Tokamak zk-EVM runtime"
536
+ : null,
368
537
  doctorStatus: tokamakCli.doctor.status,
369
538
  runtimeRoot: tokamakCli.runtimeRoot,
370
539
  installations: tokamakCli.installations.map(({ platform, installMode, packageVersion, docker }) => ({
@@ -395,14 +564,25 @@ function buildDoctorReport({ probeGpu = false } = {}) {
395
564
  },
396
565
  {
397
566
  name: "groth16 runtime",
398
- ok: groth16Runtime.installed,
567
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY ? true : groth16Runtime.installed,
568
+ skipped: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY,
399
569
  details: {
570
+ skippedReason: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
571
+ ? "read-only install mode does not require the Groth16 runtime"
572
+ : null,
400
573
  packageRoot: groth16Runtime.packageRoot,
401
574
  workspaceRoot: groth16Runtime.workspaceRoot,
402
575
  doctorStatus: groth16Runtime.doctor.status,
403
576
  checks: groth16Runtime.checks,
404
577
  },
405
578
  },
579
+ {
580
+ name: `${installMode} deployment artifacts`,
581
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
582
+ ? artifactReadiness.readOnlyInstalled
583
+ : artifactReadiness.fullInstalled,
584
+ details: artifactReadiness,
585
+ },
406
586
  ];
407
587
 
408
588
  return {
@@ -417,6 +597,7 @@ function buildDoctorReport({ probeGpu = false } = {}) {
417
597
  path: installManifestPath,
418
598
  exists: Boolean(installManifest),
419
599
  installedAt: installManifest?.installedAt ?? null,
600
+ mode: installMode,
420
601
  dockerRequested: installManifest?.install?.dockerRequested ?? null,
421
602
  includeLocalArtifacts: installManifest?.install?.includeLocalArtifacts ?? null,
422
603
  selectedVersions: installManifest?.install?.selectedVersions ?? null,
@@ -427,6 +608,8 @@ function buildDoctorReport({ probeGpu = false } = {}) {
427
608
  tokamakCli,
428
609
  groth16Runtime,
429
610
  gpuDockerReadiness,
611
+ deploymentArtifacts: artifactReadiness,
612
+ commandAvailability,
430
613
  checks,
431
614
  };
432
615
  }
@@ -445,7 +628,62 @@ function buildSkippedGpuDockerReadiness(tokamakCli) {
445
628
  };
446
629
  }
447
630
 
448
- function buildSelectedRuntimeVersionCheck({ installManifest, tokamakCli, groth16Runtime }) {
631
+ function buildCommandAvailability({ artifactReadiness, installMode, tokamakCli, groth16Runtime }) {
632
+ const proofRuntimeReady = tokamakCli.installed && groth16Runtime.installed;
633
+ return PRIVATE_STATE_CLI_COMMANDS.map((command) => {
634
+ const requiredInstallMode = privateStateCliCommandInstallMode(command);
635
+ const reasons = [];
636
+ let available = true;
637
+ if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
638
+ available = artifactReadiness.readOnlyInstalled;
639
+ if (!artifactReadiness.readOnlyInstalled) {
640
+ reasons.push("missing read-only deployment artifacts");
641
+ }
642
+ } else if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL && installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
643
+ available = false;
644
+ reasons.push("full install required");
645
+ } else if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
646
+ available = artifactReadiness.fullInstalled && proofRuntimeReady;
647
+ if (!artifactReadiness.fullInstalled) {
648
+ reasons.push("missing full deployment artifacts");
649
+ }
650
+ if (!tokamakCli.installed) {
651
+ reasons.push("missing Tokamak zk-EVM runtime");
652
+ }
653
+ if (!groth16Runtime.installed) {
654
+ reasons.push("missing Groth16 runtime");
655
+ }
656
+ }
657
+ return {
658
+ id: command.id,
659
+ display: privateStateCliCommandDisplay(command),
660
+ requiredInstallMode,
661
+ available,
662
+ chains: requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL
663
+ ? artifactReadiness.chains
664
+ .filter((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.FULL].ok)
665
+ .map((entry) => entry.chainId)
666
+ : requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
667
+ ? artifactReadiness.chains
668
+ .filter((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.READ_ONLY].ok)
669
+ .map((entry) => entry.chainId)
670
+ : [],
671
+ reasons,
672
+ };
673
+ });
674
+ }
675
+
676
+ function buildSelectedRuntimeVersionCheck({ installManifest, installMode, tokamakCli, groth16Runtime }) {
677
+ if (installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
678
+ return {
679
+ name: "selected proof backend runtime versions",
680
+ ok: true,
681
+ skipped: true,
682
+ details: [{
683
+ skippedReason: "read-only install mode does not select proof backend runtime versions",
684
+ }],
685
+ };
686
+ }
449
687
  const selectedVersions = installManifest?.install?.selectedVersions ?? null;
450
688
  const selectedTokamakCompatibleBackendVersion = selectedVersions?.tokamak
451
689
  ? normalizePackageVersionToCompatibleBackendVersion(
@@ -1087,6 +1325,7 @@ function stripAnsi(value) {
1087
1325
 
1088
1326
  async function installPrivateStateCliArtifacts({
1089
1327
  dappName,
1328
+ installMode = PRIVATE_STATE_INSTALL_MODES.FULL,
1090
1329
  indexFileId = process.env.PRIVATE_STATE_DRIVE_ARTIFACT_INDEX_FILE_ID
1091
1330
  ?? process.env.TOKAMAK_ARTIFACT_INDEX_FILE_ID
1092
1331
  ?? DEFAULT_PUBLIC_ARTIFACT_INDEX_FILE_ID,
@@ -1096,6 +1335,7 @@ async function installPrivateStateCliArtifacts({
1096
1335
  groth16CrsVersion,
1097
1336
  } = {}) {
1098
1337
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1338
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1099
1339
  const normalizedCacheBaseRoot = resolveArtifactCacheBaseRoot(cacheBaseRoot);
1100
1340
  const normalizedLocalDeploymentBaseRoot = localDeploymentBaseRoot
1101
1341
  ? path.resolve(localDeploymentBaseRoot)
@@ -1112,6 +1352,7 @@ async function installPrivateStateCliArtifacts({
1112
1352
  index,
1113
1353
  chainId,
1114
1354
  dappName: normalizedDappName,
1355
+ installMode: normalizedInstallMode,
1115
1356
  cacheBaseRoot: normalizedCacheBaseRoot,
1116
1357
  source: "drive",
1117
1358
  groth16CrsVersion,
@@ -1123,6 +1364,7 @@ async function installPrivateStateCliArtifacts({
1123
1364
  installed.push(await materializeLocalPrivateStateCliDeployment({
1124
1365
  chainId,
1125
1366
  dappName: normalizedDappName,
1367
+ installMode: normalizedInstallMode,
1126
1368
  cacheBaseRoot: normalizedCacheBaseRoot,
1127
1369
  localDeploymentBaseRoot: normalizedLocalDeploymentBaseRoot,
1128
1370
  groth16CrsVersion,
@@ -1145,12 +1387,14 @@ async function materializePrivateStateCliDeployment({
1145
1387
  index,
1146
1388
  chainId,
1147
1389
  dappName,
1390
+ installMode,
1148
1391
  cacheBaseRoot,
1149
1392
  source,
1150
1393
  groth16CrsVersion,
1151
1394
  }) {
1152
1395
  const normalizedChainId = String(requireChainId(chainId));
1153
1396
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1397
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1154
1398
  const chain = index.chains[normalizedChainId];
1155
1399
  if (!chain) {
1156
1400
  throw new Error(`Drive artifact index does not contain chain ${normalizedChainId}.`);
@@ -1173,15 +1417,19 @@ async function materializePrivateStateCliDeployment({
1173
1417
  await materializeSelectedDriveFiles({
1174
1418
  targetDir: paths.rootDir,
1175
1419
  files: chain.bridge.files,
1176
- selectedFiles: privateStateBridgeArtifactSelections(normalizedChainId, paths),
1420
+ selectedFiles: privateStateBridgeArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1177
1421
  });
1178
- await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1422
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1423
+ await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1424
+ }
1179
1425
  await materializeSelectedDriveFiles({
1180
1426
  targetDir: paths.rootDir,
1181
1427
  files: dapp.files,
1182
- selectedFiles: privateStateDappArtifactSelections(normalizedChainId, paths),
1428
+ selectedFiles: privateStateDappArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1183
1429
  });
1184
- rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1430
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1431
+ rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1432
+ }
1185
1433
 
1186
1434
  return {
1187
1435
  chainId: Number(normalizedChainId),
@@ -1195,12 +1443,14 @@ async function materializePrivateStateCliDeployment({
1195
1443
  async function materializeLocalPrivateStateCliDeployment({
1196
1444
  chainId,
1197
1445
  dappName,
1446
+ installMode,
1198
1447
  cacheBaseRoot,
1199
1448
  localDeploymentBaseRoot,
1200
1449
  groth16CrsVersion,
1201
1450
  }) {
1202
1451
  const normalizedChainId = String(requireChainId(chainId));
1203
1452
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1453
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1204
1454
  const bridgeRoot = path.join(
1205
1455
  localDeploymentBaseRoot,
1206
1456
  "deployment",
@@ -1225,12 +1475,20 @@ async function materializeLocalPrivateStateCliDeployment({
1225
1475
  materializeSelectedLocalFiles({
1226
1476
  targetDir: paths.rootDir,
1227
1477
  selectedFiles: [
1228
- ...localizeArtifactSelections(bridgeDir, privateStateBridgeArtifactSelections(normalizedChainId, paths)),
1229
- ...localizeArtifactSelections(dappDir, privateStateDappArtifactSelections(normalizedChainId, paths)),
1478
+ ...localizeArtifactSelections(
1479
+ bridgeDir,
1480
+ privateStateBridgeArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1481
+ ),
1482
+ ...localizeArtifactSelections(
1483
+ dappDir,
1484
+ privateStateDappArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1485
+ ),
1230
1486
  ],
1231
1487
  });
1232
- await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1233
- rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1488
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1489
+ await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1490
+ rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1491
+ }
1234
1492
 
1235
1493
  return {
1236
1494
  chainId: Number(normalizedChainId),
@@ -1241,21 +1499,29 @@ async function materializeLocalPrivateStateCliDeployment({
1241
1499
  };
1242
1500
  }
1243
1501
 
1244
- function privateStateBridgeArtifactSelections(chainId, paths) {
1245
- return [
1502
+ function privateStateBridgeArtifactSelections(chainId, paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
1503
+ const selections = [
1246
1504
  [`bridge.${chainId}.json`, path.basename(paths.bridgeDeploymentPath)],
1247
1505
  [`bridge-abi-manifest.${chainId}.json`, path.basename(paths.bridgeAbiManifestPath)],
1248
- [`groth16.${chainId}.latest.json`, path.basename(paths.grothManifestPath)],
1249
1506
  ];
1507
+ if (normalizeInstallMode(installMode) === PRIVATE_STATE_INSTALL_MODES.FULL) {
1508
+ selections.push([`groth16.${chainId}.latest.json`, path.basename(paths.grothManifestPath)]);
1509
+ }
1510
+ return selections;
1250
1511
  }
1251
1512
 
1252
- function privateStateDappArtifactSelections(chainId, paths) {
1253
- return [
1513
+ function privateStateDappArtifactSelections(chainId, paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
1514
+ const selections = [
1254
1515
  [`deployment.${chainId}.latest.json`, path.basename(paths.dappDeploymentPath)],
1255
1516
  [`storage-layout.${chainId}.latest.json`, path.basename(paths.dappStorageLayoutPath)],
1256
- ["PrivateStateController.callable-abi.json", path.basename(paths.privateStateControllerAbiPath)],
1257
- [`dapp-registration.${chainId}.json`, path.basename(paths.dappRegistrationPath)],
1258
1517
  ];
1518
+ if (normalizeInstallMode(installMode) === PRIVATE_STATE_INSTALL_MODES.FULL) {
1519
+ selections.push(
1520
+ ["PrivateStateController.callable-abi.json", path.basename(paths.privateStateControllerAbiPath)],
1521
+ [`dapp-registration.${chainId}.json`, path.basename(paths.dappRegistrationPath)],
1522
+ );
1523
+ }
1524
+ return selections;
1259
1525
  }
1260
1526
 
1261
1527
  function localizeArtifactSelections(sourceDir, selections) {
@@ -1302,6 +1568,9 @@ export {
1302
1568
  parseJsonReport,
1303
1569
  resolveArtifactCacheBaseRoot,
1304
1570
  privateStateCliArtifactPaths,
1571
+ privateStateCliArtifactRequiredFiles,
1572
+ normalizeInstallMode,
1573
+ PRIVATE_STATE_INSTALL_MODES,
1305
1574
  inspectGroth16Runtime,
1306
1575
  stripAnsi,
1307
1576
  resolveActiveGroth16ProverRuntime,