@tokamak-private-dapps/private-state-cli 2.1.2 → 2.2.1

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";
@@ -99,10 +108,6 @@ function runCaptured(command, args, { cwd = defaultCommandCwd, env = process.env
99
108
  };
100
109
  }
101
110
 
102
- function requireSemverVersion(value, label) {
103
- return requireExactSemverVersion(value, label);
104
- }
105
-
106
111
  function readTokamakCliPackageReport(packageRoot = null) {
107
112
  try {
108
113
  const resolvedPackageRoot = packageRoot ?? resolveActiveTokamakCliPackageRoot();
@@ -139,9 +144,13 @@ function printDoctorHumanReport(report) {
139
144
  `Generated: ${report.generatedAt}`,
140
145
  `Package: ${report.package.name}@${report.package.version ?? "unknown"}`,
141
146
  `Install manifest: ${report.installManifest.exists ? "found" : "missing"} (${report.installManifest.path})`,
147
+ `Install mode: ${report.installManifest.mode}`,
142
148
  "",
143
149
  formatDoctorTable(rows),
144
150
  "",
151
+ "Command availability",
152
+ formatDoctorCommandAvailabilityTable(report.commandAvailability),
153
+ "",
145
154
  "Run `help doctor --json` for the full machine-readable report.",
146
155
  ];
147
156
  console.log(lines.join("\n"));
@@ -155,6 +164,7 @@ function buildDoctorHumanRows(report) {
155
164
  .find((check) => check.name === "selected proof backend runtime versions")
156
165
  ?.details ?? [];
157
166
  const selectedVersionSummary = selectedVersionDetails
167
+ .filter((entry) => entry.name)
158
168
  .map((entry) => [
159
169
  `${entry.name}:`,
160
170
  `selected=${entry.selectedVersion ?? "none"}`,
@@ -163,6 +173,9 @@ function buildDoctorHumanRows(report) {
163
173
  entry.crsCompatibleBackendVersion ? `crs=${entry.crsCompatibleBackendVersion}` : null,
164
174
  ].filter(Boolean).join(" "))
165
175
  .join("; ");
176
+ const selectedVersionSkippedReason = selectedVersionDetails
177
+ .find((entry) => entry.skippedReason)
178
+ ?.skippedReason;
166
179
 
167
180
  return [
168
181
  {
@@ -172,12 +185,16 @@ function buildDoctorHumanRows(report) {
172
185
  },
173
186
  {
174
187
  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",
188
+ status: report.checks.find((check) => check.name === "selected proof backend runtime versions")?.skipped
189
+ ? "SKIP"
190
+ : doctorStatus(report.checks.find((check) => check.name === "selected proof backend runtime versions")?.ok),
191
+ detail: selectedVersionSkippedReason ?? (selectedVersionSummary || "no selected runtime version pin"),
177
192
  },
178
193
  {
179
194
  check: "tokamak zk-evm runtime",
180
- status: doctorStatus(report.tokamakCli.installed),
195
+ status: report.checks.find((check) => check.name === "tokamak zk-evm runtime")?.skipped
196
+ ? "SKIP"
197
+ : doctorStatus(report.tokamakCli.installed),
181
198
  detail: [
182
199
  `package=${report.tokamakCli.packageVersion ?? "missing"}`,
183
200
  `cbv=${report.tokamakCli.compatibleBackendVersion ?? "missing"}`,
@@ -198,7 +215,9 @@ function buildDoctorHumanRows(report) {
198
215
  },
199
216
  {
200
217
  check: "groth16 runtime",
201
- status: doctorStatus(report.groth16Runtime.installed),
218
+ status: report.checks.find((check) => check.name === "groth16 runtime")?.skipped
219
+ ? "SKIP"
220
+ : doctorStatus(report.groth16Runtime.installed),
202
221
  detail: [
203
222
  `package=${report.groth16Runtime.packageVersion ?? "missing"}`,
204
223
  `cbv=${report.groth16Runtime.compatibleBackendVersion ?? "missing"}`,
@@ -207,9 +226,21 @@ function buildDoctorHumanRows(report) {
207
226
  `doctorStatus=${report.groth16Runtime.doctor.status}`,
208
227
  ].join(" "),
209
228
  },
229
+ {
230
+ check: `${report.installManifest.mode} deployment artifacts`,
231
+ status: doctorStatus(report.checks.find((check) => check.name === `${report.installManifest.mode} deployment artifacts`)?.ok),
232
+ detail: [
233
+ `readOnlyChains=${formatInstalledArtifactChains(report.deploymentArtifacts, PRIVATE_STATE_INSTALL_MODES.READ_ONLY)}`,
234
+ `fullChains=${formatInstalledArtifactChains(report.deploymentArtifacts, PRIVATE_STATE_INSTALL_MODES.FULL)}`,
235
+ ].join(" "),
236
+ },
210
237
  ];
211
238
  }
212
239
 
240
+ function formatInstalledArtifactChains(artifactReadiness, mode) {
241
+ return installedArtifactChainIds(artifactReadiness, mode).join(",") || "none";
242
+ }
243
+
213
244
  function formatDoctorTable(rows) {
214
245
  const headers = ["Check", "Status", "Detail"];
215
246
  const checkWidth = Math.max(headers[0].length, ...rows.map((row) => row.check.length));
@@ -235,12 +266,55 @@ function formatDoctorTable(rows) {
235
266
  ].join("\n");
236
267
  }
237
268
 
269
+ function formatDoctorCommandAvailabilityTable(entries) {
270
+ const headers = ["Command", "Mode", "Status", "Detail"];
271
+ const rows = entries.map((entry) => ({
272
+ command: entry.display,
273
+ mode: entry.requiredInstallMode,
274
+ status: entry.available ? "OK" : "FAIL",
275
+ detail: entry.available
276
+ ? (entry.chains.length > 0 ? `chains=${entry.chains.join(",")}` : "no install artifacts required")
277
+ : entry.reasons.join("; "),
278
+ }));
279
+ const commandWidth = Math.max(headers[0].length, ...rows.map((row) => row.command.length));
280
+ const modeWidth = Math.max(headers[1].length, ...rows.map((row) => row.mode.length));
281
+ const statusWidth = Math.max(headers[2].length, ...rows.map((row) => row.status.length));
282
+ return [
283
+ [
284
+ headers[0].padEnd(commandWidth),
285
+ headers[1].padEnd(modeWidth),
286
+ headers[2].padEnd(statusWidth),
287
+ headers[3],
288
+ ].join(" "),
289
+ [
290
+ "-".repeat(commandWidth),
291
+ "-".repeat(modeWidth),
292
+ "-".repeat(statusWidth),
293
+ "-".repeat(headers[3].length),
294
+ ].join(" "),
295
+ ...rows.map((row) => [
296
+ row.command.padEnd(commandWidth),
297
+ row.mode.padEnd(modeWidth),
298
+ row.status.padEnd(statusWidth),
299
+ row.detail,
300
+ ].join(" ")),
301
+ ].join("\n");
302
+ }
303
+
238
304
  function doctorStatus(ok) {
239
305
  if (ok === true) return "OK";
240
306
  if (ok === false) return "FAIL";
241
307
  return "UNKNOWN";
242
308
  }
243
309
 
310
+ function normalizeInstallMode(value = PRIVATE_STATE_INSTALL_MODES.FULL) {
311
+ const normalized = String(value ?? PRIVATE_STATE_INSTALL_MODES.FULL).trim().toLowerCase();
312
+ if (normalized === PRIVATE_STATE_INSTALL_MODES.FULL || normalized === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
313
+ return normalized;
314
+ }
315
+ throw new Error(`Unsupported install mode: ${value}.`);
316
+ }
317
+
244
318
  function formatDoctorBool(value) {
245
319
  return value === true ? "true" : "false";
246
320
  }
@@ -281,6 +355,79 @@ function privateStateCliArtifactPaths(cacheBaseRoot = resolveArtifactCacheBaseRo
281
355
  };
282
356
  }
283
357
 
358
+ function privateStateCliArtifactRequiredFiles(paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
359
+ const normalizedInstallMode = normalizeInstallMode(installMode);
360
+ const readOnlyFiles = [
361
+ { label: "bridge deployment", path: paths.bridgeDeploymentPath },
362
+ { label: "bridge ABI manifest", path: paths.bridgeAbiManifestPath },
363
+ { label: "DApp deployment", path: paths.dappDeploymentPath },
364
+ { label: "DApp storage layout", path: paths.dappStorageLayoutPath },
365
+ ];
366
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
367
+ return readOnlyFiles;
368
+ }
369
+ return [
370
+ ...readOnlyFiles,
371
+ { label: "Groth16 manifest", path: paths.grothManifestPath },
372
+ { label: "Groth16 zkey", path: paths.grothZkeyPath },
373
+ { label: "PrivateStateController callable ABI", path: paths.privateStateControllerAbiPath },
374
+ { label: "DApp registration", path: paths.dappRegistrationPath },
375
+ ];
376
+ }
377
+
378
+ function inspectPrivateStateCliArtifactReadiness({
379
+ cacheBaseRoot = resolveArtifactCacheBaseRoot(),
380
+ installManifest = readPrivateStateCliInstallManifest(cacheBaseRoot),
381
+ } = {}) {
382
+ const chainIds = new Set(
383
+ (installManifest?.install?.installedDeploymentArtifacts ?? [])
384
+ .map((entry) => Number(entry.chainId))
385
+ .filter((chainId) => Number.isInteger(chainId)),
386
+ );
387
+ const artifactRoot = privateStateCliArtifactRoot(cacheBaseRoot);
388
+ if (fs.existsSync(artifactRoot)) {
389
+ for (const entry of fs.readdirSync(artifactRoot, { withFileTypes: true })) {
390
+ if (!entry.isDirectory()) {
391
+ continue;
392
+ }
393
+ const match = /^chain-id-(\d+)$/u.exec(entry.name);
394
+ if (match) {
395
+ chainIds.add(Number(match[1]));
396
+ }
397
+ }
398
+ }
399
+
400
+ const chains = [...chainIds].sort(compareChainIds).map((chainId) => {
401
+ const paths = privateStateCliArtifactPaths(cacheBaseRoot, chainId);
402
+ const modeStatus = Object.fromEntries(
403
+ Object.values(PRIVATE_STATE_INSTALL_MODES).map((mode) => {
404
+ const requiredFiles = privateStateCliArtifactRequiredFiles(paths, mode);
405
+ const missingFiles = requiredFiles
406
+ .filter((entry) => !fs.existsSync(entry.path))
407
+ .map((entry) => entry.path);
408
+ return [mode, {
409
+ ok: missingFiles.length === 0,
410
+ missingFiles,
411
+ requiredFiles: requiredFiles.map((entry) => entry.path),
412
+ }];
413
+ }),
414
+ );
415
+ return {
416
+ chainId,
417
+ rootDir: paths.rootDir,
418
+ modes: modeStatus,
419
+ };
420
+ });
421
+
422
+ return {
423
+ cacheBaseRoot,
424
+ artifactRoot,
425
+ chains,
426
+ readOnlyInstalled: chains.some((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.READ_ONLY].ok),
427
+ fullInstalled: chains.some((entry) => entry.modes[PRIVATE_STATE_INSTALL_MODES.FULL].ok),
428
+ };
429
+ }
430
+
284
431
  function privateStateCliInstallManifestPath(cacheBaseRoot = resolveArtifactCacheBaseRoot()) {
285
432
  return path.join(privateStateCliArtifactRoot(cacheBaseRoot), "install-manifest.json");
286
433
  }
@@ -290,6 +437,7 @@ function readPrivateStateCliInstallManifest(cacheBaseRoot = resolveArtifactCache
290
437
  }
291
438
 
292
439
  function writePrivateStateCliInstallManifest({
440
+ installMode = PRIVATE_STATE_INSTALL_MODES.FULL,
293
441
  dockerRequested,
294
442
  includeLocalArtifacts,
295
443
  localDeploymentBaseRoot,
@@ -308,6 +456,7 @@ function writePrivateStateCliInstallManifest({
308
456
  dependencies: collectDependencyPackageReports().map(summarizePackageReport),
309
457
  install: {
310
458
  dockerRequested,
459
+ mode: normalizeInstallMode(installMode),
311
460
  includeLocalArtifacts,
312
461
  localDeploymentBaseRoot,
313
462
  artifactCacheRoot: deploymentArtifacts.cacheBaseRoot,
@@ -337,14 +486,24 @@ function buildDoctorReport({ probeGpu = false } = {}) {
337
486
  const cacheBaseRoot = resolveArtifactCacheBaseRoot();
338
487
  const installManifestPath = privateStateCliInstallManifestPath(cacheBaseRoot);
339
488
  const installManifest = readJsonIfExists(installManifestPath);
489
+ const installMode = normalizeInstallMode(installManifest?.install?.mode ?? PRIVATE_STATE_INSTALL_MODES.FULL);
490
+ const requiresProofRuntime = installMode === PRIVATE_STATE_INSTALL_MODES.FULL;
340
491
  const dependencyReports = collectDependencyPackageReports(installManifest);
341
- const tokamakCli = inspectTokamakCliRuntime();
342
- const groth16Runtime = inspectGroth16Runtime();
343
- const gpuDockerReadiness = probeGpu
492
+ const tokamakCli = requiresProofRuntime ? inspectTokamakCliRuntime() : { installed: false, doctor: { status: null }, installations: [] };
493
+ const groth16Runtime = requiresProofRuntime ? inspectGroth16Runtime() : { installed: false, doctor: { status: null }, checks: [] };
494
+ const gpuDockerReadiness = probeGpu && requiresProofRuntime
344
495
  ? inspectGpuDockerReadiness(tokamakCli)
345
496
  : buildSkippedGpuDockerReadiness(tokamakCli);
497
+ const artifactReadiness = inspectPrivateStateCliArtifactReadiness({ cacheBaseRoot, installManifest });
498
+ const commandAvailability = buildCommandAvailability({
499
+ artifactReadiness,
500
+ groth16Runtime,
501
+ installMode,
502
+ tokamakCli,
503
+ });
346
504
  const selectedRuntimeVersionCheck = buildSelectedRuntimeVersionCheck({
347
505
  installManifest,
506
+ installMode,
348
507
  tokamakCli,
349
508
  groth16Runtime,
350
509
  });
@@ -363,8 +522,12 @@ function buildDoctorReport({ probeGpu = false } = {}) {
363
522
  selectedRuntimeVersionCheck,
364
523
  {
365
524
  name: "tokamak zk-evm runtime",
366
- ok: tokamakCli.installed,
525
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY ? true : tokamakCli.installed,
526
+ skipped: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY,
367
527
  details: {
528
+ skippedReason: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
529
+ ? "read-only install mode does not require the Tokamak zk-EVM runtime"
530
+ : null,
368
531
  doctorStatus: tokamakCli.doctor.status,
369
532
  runtimeRoot: tokamakCli.runtimeRoot,
370
533
  installations: tokamakCli.installations.map(({ platform, installMode, packageVersion, docker }) => ({
@@ -395,14 +558,25 @@ function buildDoctorReport({ probeGpu = false } = {}) {
395
558
  },
396
559
  {
397
560
  name: "groth16 runtime",
398
- ok: groth16Runtime.installed,
561
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY ? true : groth16Runtime.installed,
562
+ skipped: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY,
399
563
  details: {
564
+ skippedReason: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
565
+ ? "read-only install mode does not require the Groth16 runtime"
566
+ : null,
400
567
  packageRoot: groth16Runtime.packageRoot,
401
568
  workspaceRoot: groth16Runtime.workspaceRoot,
402
569
  doctorStatus: groth16Runtime.doctor.status,
403
570
  checks: groth16Runtime.checks,
404
571
  },
405
572
  },
573
+ {
574
+ name: `${installMode} deployment artifacts`,
575
+ ok: installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
576
+ ? artifactReadiness.readOnlyInstalled
577
+ : artifactReadiness.fullInstalled,
578
+ details: artifactReadiness,
579
+ },
406
580
  ];
407
581
 
408
582
  return {
@@ -417,6 +591,7 @@ function buildDoctorReport({ probeGpu = false } = {}) {
417
591
  path: installManifestPath,
418
592
  exists: Boolean(installManifest),
419
593
  installedAt: installManifest?.installedAt ?? null,
594
+ mode: installMode,
420
595
  dockerRequested: installManifest?.install?.dockerRequested ?? null,
421
596
  includeLocalArtifacts: installManifest?.install?.includeLocalArtifacts ?? null,
422
597
  selectedVersions: installManifest?.install?.selectedVersions ?? null,
@@ -427,6 +602,8 @@ function buildDoctorReport({ probeGpu = false } = {}) {
427
602
  tokamakCli,
428
603
  groth16Runtime,
429
604
  gpuDockerReadiness,
605
+ deploymentArtifacts: artifactReadiness,
606
+ commandAvailability,
430
607
  checks,
431
608
  };
432
609
  }
@@ -445,7 +622,63 @@ function buildSkippedGpuDockerReadiness(tokamakCli) {
445
622
  };
446
623
  }
447
624
 
448
- function buildSelectedRuntimeVersionCheck({ installManifest, tokamakCli, groth16Runtime }) {
625
+ function buildCommandAvailability({ artifactReadiness, installMode, tokamakCli, groth16Runtime }) {
626
+ const proofRuntimeReady = tokamakCli.installed && groth16Runtime.installed;
627
+ return PRIVATE_STATE_CLI_COMMANDS.map((command) => {
628
+ const requiredInstallMode = privateStateCliCommandInstallMode(command);
629
+ const reasons = [];
630
+ let available = true;
631
+ if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
632
+ available = artifactReadiness.readOnlyInstalled;
633
+ if (!artifactReadiness.readOnlyInstalled) {
634
+ reasons.push("missing read-only deployment artifacts");
635
+ }
636
+ } else if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL && installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
637
+ available = false;
638
+ reasons.push("full install required");
639
+ } else if (requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
640
+ available = artifactReadiness.fullInstalled && proofRuntimeReady;
641
+ if (!artifactReadiness.fullInstalled) {
642
+ reasons.push("missing full deployment artifacts");
643
+ }
644
+ if (!tokamakCli.installed) {
645
+ reasons.push("missing Tokamak zk-EVM runtime");
646
+ }
647
+ if (!groth16Runtime.installed) {
648
+ reasons.push("missing Groth16 runtime");
649
+ }
650
+ }
651
+ return {
652
+ id: command.id,
653
+ display: privateStateCliCommandDisplay(command),
654
+ requiredInstallMode,
655
+ available,
656
+ chains: requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL
657
+ || requiredInstallMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY
658
+ ? installedArtifactChainIds(artifactReadiness, requiredInstallMode)
659
+ : [],
660
+ reasons,
661
+ };
662
+ });
663
+ }
664
+
665
+ function installedArtifactChainIds(artifactReadiness, mode) {
666
+ return artifactReadiness.chains
667
+ .filter((entry) => entry.modes[mode]?.ok)
668
+ .map((entry) => entry.chainId);
669
+ }
670
+
671
+ function buildSelectedRuntimeVersionCheck({ installManifest, installMode, tokamakCli, groth16Runtime }) {
672
+ if (installMode === PRIVATE_STATE_INSTALL_MODES.READ_ONLY) {
673
+ return {
674
+ name: "selected proof backend runtime versions",
675
+ ok: true,
676
+ skipped: true,
677
+ details: [{
678
+ skippedReason: "read-only install mode does not select proof backend runtime versions",
679
+ }],
680
+ };
681
+ }
449
682
  const selectedVersions = installManifest?.install?.selectedVersions ?? null;
450
683
  const selectedTokamakCompatibleBackendVersion = selectedVersions?.tokamak
451
684
  ? normalizePackageVersionToCompatibleBackendVersion(
@@ -514,16 +747,16 @@ async function resolveRequestedGroth16PackageVersion(requestedVersion) {
514
747
  }
515
748
 
516
749
  const bundledPackageJson = readJson(path.join(resolveGroth16PackageRoot(), "package.json"));
517
- return requireSemverVersion(bundledPackageJson.version, `${GROTH16_PACKAGE_NAME} bundled package version`);
750
+ return requireExactSemverVersion(bundledPackageJson.version, `${GROTH16_PACKAGE_NAME} bundled package version`);
518
751
  }
519
752
 
520
753
  async function resolveRequestedNpmPackageVersion({ packageName, requestedVersion, optionName }) {
521
754
  const metadata = await fetchNpmPackageMetadata(packageName);
522
755
  if (requestedVersion === undefined || requestedVersion === null) {
523
- return requireSemverVersion(metadata?.["dist-tags"]?.latest, `${packageName} npm latest version`);
756
+ return requireExactSemverVersion(metadata?.["dist-tags"]?.latest, `${packageName} npm latest version`);
524
757
  }
525
758
 
526
- const normalizedVersion = requireSemverVersion(requestedVersion, optionName);
759
+ const normalizedVersion = requireExactSemverVersion(requestedVersion, optionName);
527
760
  if (!metadata.versions?.[normalizedVersion]) {
528
761
  throw new Error(`npm package ${packageName} does not contain version ${normalizedVersion}.`);
529
762
  }
@@ -594,7 +827,7 @@ async function installGroth16RuntimeForPrivateState({ version, docker }) {
594
827
  }
595
828
 
596
829
  function resolveGroth16RuntimePackageInstall(version) {
597
- const normalizedVersion = requireSemverVersion(version, `${GROTH16_PACKAGE_NAME} version`);
830
+ const normalizedVersion = requireExactSemverVersion(version, `${GROTH16_PACKAGE_NAME} version`);
598
831
  const bundledPackageRoot = resolveGroth16PackageRoot();
599
832
  const bundledPackageJson = readJson(path.join(bundledPackageRoot, "package.json"));
600
833
  if (bundledPackageJson.name === GROTH16_PACKAGE_NAME && bundledPackageJson.version === normalizedVersion) {
@@ -692,7 +925,7 @@ function parseDriveFileIdFromDownloadUrl(value) {
692
925
 
693
926
  function installManagedNpmPackage({ packageName, version, cacheBaseRoot = resolveArtifactCacheBaseRoot() }) {
694
927
  const normalizedPackageName = requireNonEmptyString(packageName, "packageName");
695
- const normalizedVersion = requireSemverVersion(version, `${normalizedPackageName} version`);
928
+ const normalizedVersion = requireExactSemverVersion(version, `${normalizedPackageName} version`);
696
929
  const installPrefix = managedNpmPackageInstallPrefix({
697
930
  packageName: normalizedPackageName,
698
931
  version: normalizedVersion,
@@ -727,7 +960,7 @@ function managedNpmPackageInstallPrefix({ packageName, version, cacheBaseRoot =
727
960
  const safePackageName = requireNonEmptyString(packageName, "packageName")
728
961
  .replace(/^@/, "")
729
962
  .replace(/[^A-Za-z0-9._-]+/g, "__");
730
- return path.join(privateStateCliRuntimeRoot(cacheBaseRoot), "npm", safePackageName, requireSemverVersion(version, "version"));
963
+ return path.join(privateStateCliRuntimeRoot(cacheBaseRoot), "npm", safePackageName, requireExactSemverVersion(version, "version"));
731
964
  }
732
965
 
733
966
  async function downloadGroth16CrsArtifactsForPrivateState({
@@ -1087,6 +1320,7 @@ function stripAnsi(value) {
1087
1320
 
1088
1321
  async function installPrivateStateCliArtifacts({
1089
1322
  dappName,
1323
+ installMode = PRIVATE_STATE_INSTALL_MODES.FULL,
1090
1324
  indexFileId = process.env.PRIVATE_STATE_DRIVE_ARTIFACT_INDEX_FILE_ID
1091
1325
  ?? process.env.TOKAMAK_ARTIFACT_INDEX_FILE_ID
1092
1326
  ?? DEFAULT_PUBLIC_ARTIFACT_INDEX_FILE_ID,
@@ -1096,6 +1330,7 @@ async function installPrivateStateCliArtifacts({
1096
1330
  groth16CrsVersion,
1097
1331
  } = {}) {
1098
1332
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1333
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1099
1334
  const normalizedCacheBaseRoot = resolveArtifactCacheBaseRoot(cacheBaseRoot);
1100
1335
  const normalizedLocalDeploymentBaseRoot = localDeploymentBaseRoot
1101
1336
  ? path.resolve(localDeploymentBaseRoot)
@@ -1112,6 +1347,7 @@ async function installPrivateStateCliArtifacts({
1112
1347
  index,
1113
1348
  chainId,
1114
1349
  dappName: normalizedDappName,
1350
+ installMode: normalizedInstallMode,
1115
1351
  cacheBaseRoot: normalizedCacheBaseRoot,
1116
1352
  source: "drive",
1117
1353
  groth16CrsVersion,
@@ -1123,6 +1359,7 @@ async function installPrivateStateCliArtifacts({
1123
1359
  installed.push(await materializeLocalPrivateStateCliDeployment({
1124
1360
  chainId,
1125
1361
  dappName: normalizedDappName,
1362
+ installMode: normalizedInstallMode,
1126
1363
  cacheBaseRoot: normalizedCacheBaseRoot,
1127
1364
  localDeploymentBaseRoot: normalizedLocalDeploymentBaseRoot,
1128
1365
  groth16CrsVersion,
@@ -1145,12 +1382,14 @@ async function materializePrivateStateCliDeployment({
1145
1382
  index,
1146
1383
  chainId,
1147
1384
  dappName,
1385
+ installMode,
1148
1386
  cacheBaseRoot,
1149
1387
  source,
1150
1388
  groth16CrsVersion,
1151
1389
  }) {
1152
1390
  const normalizedChainId = String(requireChainId(chainId));
1153
1391
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1392
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1154
1393
  const chain = index.chains[normalizedChainId];
1155
1394
  if (!chain) {
1156
1395
  throw new Error(`Drive artifact index does not contain chain ${normalizedChainId}.`);
@@ -1173,15 +1412,19 @@ async function materializePrivateStateCliDeployment({
1173
1412
  await materializeSelectedDriveFiles({
1174
1413
  targetDir: paths.rootDir,
1175
1414
  files: chain.bridge.files,
1176
- selectedFiles: privateStateBridgeArtifactSelections(normalizedChainId, paths),
1415
+ selectedFiles: privateStateBridgeArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1177
1416
  });
1178
- await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1417
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1418
+ await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1419
+ }
1179
1420
  await materializeSelectedDriveFiles({
1180
1421
  targetDir: paths.rootDir,
1181
1422
  files: dapp.files,
1182
- selectedFiles: privateStateDappArtifactSelections(normalizedChainId, paths),
1423
+ selectedFiles: privateStateDappArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1183
1424
  });
1184
- rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1425
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1426
+ rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1427
+ }
1185
1428
 
1186
1429
  return {
1187
1430
  chainId: Number(normalizedChainId),
@@ -1195,12 +1438,14 @@ async function materializePrivateStateCliDeployment({
1195
1438
  async function materializeLocalPrivateStateCliDeployment({
1196
1439
  chainId,
1197
1440
  dappName,
1441
+ installMode,
1198
1442
  cacheBaseRoot,
1199
1443
  localDeploymentBaseRoot,
1200
1444
  groth16CrsVersion,
1201
1445
  }) {
1202
1446
  const normalizedChainId = String(requireChainId(chainId));
1203
1447
  const normalizedDappName = requireNonEmptyString(dappName, "dappName");
1448
+ const normalizedInstallMode = normalizeInstallMode(installMode);
1204
1449
  const bridgeRoot = path.join(
1205
1450
  localDeploymentBaseRoot,
1206
1451
  "deployment",
@@ -1225,12 +1470,20 @@ async function materializeLocalPrivateStateCliDeployment({
1225
1470
  materializeSelectedLocalFiles({
1226
1471
  targetDir: paths.rootDir,
1227
1472
  selectedFiles: [
1228
- ...localizeArtifactSelections(bridgeDir, privateStateBridgeArtifactSelections(normalizedChainId, paths)),
1229
- ...localizeArtifactSelections(dappDir, privateStateDappArtifactSelections(normalizedChainId, paths)),
1473
+ ...localizeArtifactSelections(
1474
+ bridgeDir,
1475
+ privateStateBridgeArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1476
+ ),
1477
+ ...localizeArtifactSelections(
1478
+ dappDir,
1479
+ privateStateDappArtifactSelections(normalizedChainId, paths, normalizedInstallMode),
1480
+ ),
1230
1481
  ],
1231
1482
  });
1232
- await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1233
- rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1483
+ if (normalizedInstallMode === PRIVATE_STATE_INSTALL_MODES.FULL) {
1484
+ await materializeFlatGroth16Zkey({ paths, groth16CrsVersion });
1485
+ rewriteFlatGroth16Manifest(paths.grothManifestPath, paths.grothZkeyPath);
1486
+ }
1234
1487
 
1235
1488
  return {
1236
1489
  chainId: Number(normalizedChainId),
@@ -1241,21 +1494,29 @@ async function materializeLocalPrivateStateCliDeployment({
1241
1494
  };
1242
1495
  }
1243
1496
 
1244
- function privateStateBridgeArtifactSelections(chainId, paths) {
1245
- return [
1497
+ function privateStateBridgeArtifactSelections(chainId, paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
1498
+ const selections = [
1246
1499
  [`bridge.${chainId}.json`, path.basename(paths.bridgeDeploymentPath)],
1247
1500
  [`bridge-abi-manifest.${chainId}.json`, path.basename(paths.bridgeAbiManifestPath)],
1248
- [`groth16.${chainId}.latest.json`, path.basename(paths.grothManifestPath)],
1249
1501
  ];
1502
+ if (normalizeInstallMode(installMode) === PRIVATE_STATE_INSTALL_MODES.FULL) {
1503
+ selections.push([`groth16.${chainId}.latest.json`, path.basename(paths.grothManifestPath)]);
1504
+ }
1505
+ return selections;
1250
1506
  }
1251
1507
 
1252
- function privateStateDappArtifactSelections(chainId, paths) {
1253
- return [
1508
+ function privateStateDappArtifactSelections(chainId, paths, installMode = PRIVATE_STATE_INSTALL_MODES.FULL) {
1509
+ const selections = [
1254
1510
  [`deployment.${chainId}.latest.json`, path.basename(paths.dappDeploymentPath)],
1255
1511
  [`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
1512
  ];
1513
+ if (normalizeInstallMode(installMode) === PRIVATE_STATE_INSTALL_MODES.FULL) {
1514
+ selections.push(
1515
+ ["PrivateStateController.callable-abi.json", path.basename(paths.privateStateControllerAbiPath)],
1516
+ [`dapp-registration.${chainId}.json`, path.basename(paths.dappRegistrationPath)],
1517
+ );
1518
+ }
1519
+ return selections;
1259
1520
  }
1260
1521
 
1261
1522
  function localizeArtifactSelections(sourceDir, selections) {
@@ -1302,6 +1563,9 @@ export {
1302
1563
  parseJsonReport,
1303
1564
  resolveArtifactCacheBaseRoot,
1304
1565
  privateStateCliArtifactPaths,
1566
+ privateStateCliArtifactRequiredFiles,
1567
+ normalizeInstallMode,
1568
+ PRIVATE_STATE_INSTALL_MODES,
1305
1569
  inspectGroth16Runtime,
1306
1570
  stripAnsi,
1307
1571
  resolveActiveGroth16ProverRuntime,