@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.
- package/CHANGELOG.md +16 -0
- package/README.md +52 -16
- package/commands/account.mjs +3 -7
- package/commands/channel.mjs +7 -15
- package/commands/notes.mjs +4 -9
- package/commands/wallet.mjs +5 -11
- package/lib/private-state-cli-command-registry.mjs +51 -10
- package/lib/private-state-runtime-management.mjs +299 -35
- package/lib/runtime.mjs +357 -121
- package/package.json +1 -1
|
@@ -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:
|
|
176
|
-
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
756
|
+
return requireExactSemverVersion(metadata?.["dist-tags"]?.latest, `${packageName} npm latest version`);
|
|
524
757
|
}
|
|
525
758
|
|
|
526
|
-
const normalizedVersion =
|
|
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 =
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
1229
|
-
|
|
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
|
-
|
|
1233
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|