@layerzerolabs/vm-tooling-stellar 1.2.9 → 1.2.10

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.
@@ -0,0 +1,437 @@
1
+ import { __name } from './VUOMXK5T.js';
2
+ import { unzipSync } from 'fflate';
3
+ import { execFile, spawn } from 'child_process';
4
+ import { createHash } from 'crypto';
5
+ import { stat, chmod, readFile, copyFile, mkdtemp, mkdir, writeFile, readdir, rename, rm } from 'fs/promises';
6
+ import { tmpdir } from 'os';
7
+ import path from 'path';
8
+ import { promisify } from 'util';
9
+ import { parse } from 'toml';
10
+
11
+ var execFileAsync = promisify(execFile);
12
+ var SOURCE_ARCHIVE_NAME = "contracts-source.zip";
13
+ var WASM_TARGET_DIR = path.join("target", "wasm32v1-none", "release");
14
+ var SOURCE_MOUNT = "/source";
15
+ var VERIFIABLE_BUILD_PLATFORM = "linux/amd64";
16
+ var OFFICIAL_IMAGE_REPO = "stellar/stellar-cli";
17
+ var META_FLAG = "--meta";
18
+ var officialImageTagRef = /* @__PURE__ */ __name((stellarVersion, rustVersion) => `${OFFICIAL_IMAGE_REPO}:${stellarVersion}-rust${rustVersion}-slim-bookworm`, "officialImageTagRef");
19
+ var parseAmd64Digest = /* @__PURE__ */ __name((manifestInspectJson) => {
20
+ const { manifests } = JSON.parse(manifestInspectJson);
21
+ if (!Array.isArray(manifests)) {
22
+ throw new Error("`docker manifest inspect` did not return a multi-arch index (no `manifests` array)");
23
+ }
24
+ const digest = manifests.find(({ platform }) => platform?.os === "linux" && platform?.architecture === "amd64")?.digest;
25
+ if (typeof digest !== "string" || !digest.startsWith("sha256:")) {
26
+ throw new Error("No linux/amd64 manifest digest found in `docker manifest inspect` output");
27
+ }
28
+ return digest;
29
+ }, "parseAmd64Digest");
30
+ var resolveAmd64Digest = /* @__PURE__ */ __name(async (imageTagRef) => {
31
+ try {
32
+ const { stdout } = await execFileAsync("docker", [
33
+ "manifest",
34
+ "inspect",
35
+ imageTagRef
36
+ ], {
37
+ maxBuffer: 16 * 1024 * 1024,
38
+ timeout: 3e4
39
+ });
40
+ return parseAmd64Digest(stdout);
41
+ } catch (cause) {
42
+ throw new Error(`Failed to resolve the linux/amd64 digest of ${imageTagRef} (\`docker manifest inspect\`)`, {
43
+ cause
44
+ });
45
+ }
46
+ }, "resolveAmd64Digest");
47
+ var metaKey = /* @__PURE__ */ __name((entry) => {
48
+ const eq = entry.indexOf("=");
49
+ return eq === -1 ? entry : entry.slice(0, eq);
50
+ }, "metaKey");
51
+ var canonicalizeMetaArgs = /* @__PURE__ */ __name((buildArgs, injectedMeta) => {
52
+ const reservedKeys = new Set(injectedMeta.map(metaKey));
53
+ const metas = [
54
+ ...injectedMeta
55
+ ];
56
+ const passthrough = [];
57
+ const addCallerMeta = /* @__PURE__ */ __name((value) => {
58
+ if (!reservedKeys.has(metaKey(value))) metas.push(value);
59
+ }, "addCallerMeta");
60
+ for (let i = 0; i < buildArgs.length; i++) {
61
+ const arg = buildArgs[i];
62
+ if (arg === void 0) continue;
63
+ if (arg === META_FLAG) {
64
+ const value = buildArgs[i + 1];
65
+ if (value !== void 0 && !value.startsWith("--")) {
66
+ addCallerMeta(value);
67
+ i += 1;
68
+ }
69
+ } else if (arg.startsWith(`${META_FLAG}=`)) {
70
+ addCallerMeta(arg.slice(META_FLAG.length + 1));
71
+ } else {
72
+ passthrough.push(arg);
73
+ }
74
+ }
75
+ metas.sort();
76
+ return [
77
+ ...passthrough,
78
+ ...metas.flatMap((meta) => [
79
+ META_FLAG,
80
+ meta
81
+ ])
82
+ ];
83
+ }, "canonicalizeMetaArgs");
84
+ var buildVerifiableBuildDockerArgs = /* @__PURE__ */ __name(({ imageRef, sourceDir, buildArgs, bldimg }) => [
85
+ "run",
86
+ "--rm",
87
+ "--platform",
88
+ VERIFIABLE_BUILD_PLATFORM,
89
+ "-v",
90
+ `${sourceDir}:${SOURCE_MOUNT}`,
91
+ "-w",
92
+ SOURCE_MOUNT,
93
+ imageRef,
94
+ "contract",
95
+ "build",
96
+ ...canonicalizeMetaArgs(buildArgs, [
97
+ `bldimg=${bldimg}`
98
+ ])
99
+ ], "buildVerifiableBuildDockerArgs");
100
+ var resolveBuildDir = /* @__PURE__ */ __name((cwd, sourceDir) => path.resolve(cwd, sourceDir ?? "."), "resolveBuildDir");
101
+ var runDocker = /* @__PURE__ */ __name((dockerArgs) => new Promise((resolve, reject) => {
102
+ const child = spawn("docker", dockerArgs, {
103
+ stdio: "inherit"
104
+ });
105
+ child.on("error", (error) => reject(new Error("Failed to spawn docker for the verifiable build", {
106
+ cause: error
107
+ })));
108
+ child.on("close", (code, signal) => {
109
+ if (code === 0) {
110
+ resolve();
111
+ } else {
112
+ reject(new Error(`Verifiable build failed: docker exited with ${signal ? `signal ${signal}` : `code ${code}`}`));
113
+ }
114
+ });
115
+ }), "runDocker");
116
+ var VerifiableBuildWrapper = class {
117
+ static {
118
+ __name(this, "VerifiableBuildWrapper");
119
+ }
120
+ resolveDigest;
121
+ imagesByTag = /* @__PURE__ */ new Map();
122
+ constructor(resolveDigest = resolveAmd64Digest) {
123
+ this.resolveDigest = resolveDigest;
124
+ }
125
+ resolveImage({ stellarVersion, rustVersion }) {
126
+ const tagRef = officialImageTagRef(stellarVersion, rustVersion);
127
+ const existing = this.imagesByTag.get(tagRef);
128
+ if (existing !== void 0) {
129
+ return existing;
130
+ }
131
+ const resolved = this.resolveDigest(tagRef).then((digest) => ({
132
+ imageRef: `${OFFICIAL_IMAGE_REPO}@${digest}`,
133
+ bldimg: `docker.io/${OFFICIAL_IMAGE_REPO}@${digest}`,
134
+ tagRef
135
+ }));
136
+ this.imagesByTag.set(tagRef, resolved);
137
+ return resolved;
138
+ }
139
+ async run(args, versions, { cwd }, sourceDir) {
140
+ const buildDir = resolveBuildDir(cwd, sourceDir);
141
+ try {
142
+ if (!(await stat(buildDir)).isDirectory()) {
143
+ throw new Error("not a directory");
144
+ }
145
+ } catch (cause) {
146
+ throw new Error(`Verifiable build source directory is not an existing directory: ${buildDir}`, {
147
+ cause
148
+ });
149
+ }
150
+ if (sourceDir !== void 0) {
151
+ await chmod(buildDir, 511);
152
+ }
153
+ const { imageRef, bldimg, tagRef } = await this.resolveImage(versions);
154
+ const dockerArgs = buildVerifiableBuildDockerArgs({
155
+ imageRef,
156
+ sourceDir: buildDir,
157
+ buildArgs: args,
158
+ bldimg
159
+ });
160
+ console.info("\u{1F512} Verifiable build (official stellar/stellar-cli image, run from host)");
161
+ console.info(` source: ${buildDir}`);
162
+ console.info(` image: ${imageRef} (${VERIFIABLE_BUILD_PLATFORM}, from tag ${tagRef})`);
163
+ console.info(` bldimg: ${bldimg}`);
164
+ console.info(` docker ${dockerArgs.join(" ")}`);
165
+ await runDocker(dockerArgs);
166
+ }
167
+ };
168
+ var parsePackageSpec = /* @__PURE__ */ __name((spec) => {
169
+ const colon = spec.indexOf(":");
170
+ if (colon <= 0 || colon === spec.length - 1) {
171
+ throw new Error(`Invalid --package spec ${JSON.stringify(spec)}: expected <name>:<manifest-path>`);
172
+ }
173
+ return {
174
+ packageName: spec.slice(0, colon),
175
+ manifestPath: spec.slice(colon + 1)
176
+ };
177
+ }, "parsePackageSpec");
178
+ var wasmArtifactName = /* @__PURE__ */ __name((packageName) => `${packageName.replaceAll("-", "_")}.wasm`, "wasmArtifactName");
179
+ var validatePackageSpecs = /* @__PURE__ */ __name((packages) => {
180
+ const artifactNames = /* @__PURE__ */ new Set();
181
+ for (const { packageName } of packages) {
182
+ const artifactName = wasmArtifactName(packageName);
183
+ if (artifactNames.has(artifactName)) {
184
+ throw new Error(`Duplicate WASM artifact ${artifactName} from --package options`);
185
+ }
186
+ artifactNames.add(artifactName);
187
+ }
188
+ }, "validatePackageSpecs");
189
+ var resolveRustVersion = /* @__PURE__ */ __name(async (sourceDir, rustVersionFlag) => {
190
+ if (rustVersionFlag !== void 0) {
191
+ return rustVersionFlag;
192
+ }
193
+ const toolchainPath = path.join(sourceDir, "rust-toolchain.toml");
194
+ let contents;
195
+ try {
196
+ contents = await readFile(toolchainPath, "utf-8");
197
+ } catch (cause) {
198
+ if (cause.code === "ENOENT") {
199
+ throw new Error(`Missing rust-toolchain.toml in ${sourceDir} and no --rust-version was provided`, {
200
+ cause
201
+ });
202
+ }
203
+ throw cause;
204
+ }
205
+ const parsed = parse(contents);
206
+ const channel = parsed.toolchain?.channel;
207
+ if (typeof channel !== "string" || channel.length === 0) {
208
+ throw new Error(`Missing 'toolchain.channel' in ${toolchainPath}`);
209
+ }
210
+ return channel;
211
+ }, "resolveRustVersion");
212
+ var buildArchiveContractArgs = /* @__PURE__ */ __name(({ packageName, manifestPath }, sourceSha256) => [
213
+ "--manifest-path",
214
+ manifestPath,
215
+ "--package",
216
+ packageName,
217
+ "--optimize",
218
+ "--meta",
219
+ `bldopt=--manifest-path=${manifestPath}`,
220
+ "--meta",
221
+ `bldopt=--package=${packageName}`,
222
+ "--meta",
223
+ "bldopt=--optimize",
224
+ "--meta",
225
+ `source_sha256=${sourceSha256}`
226
+ ], "buildArchiveContractArgs");
227
+ var pathExists = /* @__PURE__ */ __name(async (filePath) => {
228
+ try {
229
+ await stat(filePath);
230
+ return true;
231
+ } catch (error) {
232
+ if (error.code === "ENOENT") {
233
+ return false;
234
+ }
235
+ throw error;
236
+ }
237
+ }, "pathExists");
238
+ var readArchiveBytes = /* @__PURE__ */ __name(async (archive) => {
239
+ let bytes;
240
+ try {
241
+ bytes = new Uint8Array(await readFile(archive));
242
+ } catch (cause) {
243
+ throw new Error(`Archive not found or unreadable: ${archive}`, {
244
+ cause
245
+ });
246
+ }
247
+ if (bytes.length === 0) {
248
+ throw new Error(`Archive is empty: ${archive}`);
249
+ }
250
+ return bytes;
251
+ }, "readArchiveBytes");
252
+ var extractZip = /* @__PURE__ */ __name(async (bytes, destDir, expectedRootDirName) => {
253
+ const files = unzipSync(bytes);
254
+ const destRoot = path.resolve(destDir);
255
+ const expectedRoot = path.join(destRoot, expectedRootDirName);
256
+ const expectedRootPrefix = `${expectedRootDirName}/`;
257
+ for (const [relPath, content] of Object.entries(files)) {
258
+ const outPath = path.resolve(destRoot, relPath);
259
+ if (outPath !== destRoot && !outPath.startsWith(destRoot + path.sep)) {
260
+ throw new Error(`Zip entry escapes destination: ${relPath}`);
261
+ }
262
+ if (outPath !== expectedRoot && !outPath.startsWith(expectedRoot + path.sep)) {
263
+ throw new Error(`Zip entry is outside expected top-level ${expectedRootPrefix}: ${relPath}`);
264
+ }
265
+ if (relPath.endsWith("/")) continue;
266
+ await mkdir(path.dirname(outPath), {
267
+ recursive: true
268
+ });
269
+ await writeFile(outPath, content);
270
+ }
271
+ }, "extractZip");
272
+ var persistSourceArchive = /* @__PURE__ */ __name(async (archiveBytes, stagingDir) => {
273
+ await mkdir(stagingDir, {
274
+ recursive: true
275
+ });
276
+ await writeFile(path.join(stagingDir, SOURCE_ARCHIVE_NAME), archiveBytes);
277
+ }, "persistSourceArchive");
278
+ var copyFileWithPermissionRepair = /* @__PURE__ */ __name(async (source, destination, repairPermissions, copy = copyFile) => {
279
+ try {
280
+ await copy(source, destination);
281
+ } catch (error) {
282
+ const code = error.code;
283
+ if (code !== "EACCES" && code !== "EPERM") {
284
+ throw error;
285
+ }
286
+ await repairPermissions();
287
+ await copy(source, destination);
288
+ }
289
+ }, "copyFileWithPermissionRepair");
290
+ var persistWasm = /* @__PURE__ */ __name(async (buildRoot, stagingDir, { packageName }, repairPermissions) => {
291
+ const wasmName = wasmArtifactName(packageName);
292
+ const builtPath = path.join(buildRoot, WASM_TARGET_DIR, wasmName);
293
+ if (!await pathExists(builtPath)) {
294
+ throw new Error(`Expected WASM not found after build: ${builtPath}`);
295
+ }
296
+ await mkdir(stagingDir, {
297
+ recursive: true
298
+ });
299
+ await copyFileWithPermissionRepair(builtPath, path.join(stagingDir, wasmName), repairPermissions);
300
+ }, "persistWasm");
301
+ var publishArtifacts = /* @__PURE__ */ __name(async (stagingDir, outputDir) => {
302
+ const parentDir = path.dirname(outputDir);
303
+ const outputBase = path.basename(outputDir);
304
+ await mkdir(parentDir, {
305
+ recursive: true
306
+ });
307
+ const nextDir = await mkdtemp(path.join(parentDir, `${outputBase}.next-`));
308
+ const backupDir = path.join(parentDir, `${outputBase}.prev`);
309
+ const entries = await readdir(stagingDir);
310
+ try {
311
+ for (const entry of entries) {
312
+ await copyFile(path.join(stagingDir, entry), path.join(nextDir, entry));
313
+ }
314
+ if (!await pathExists(outputDir) && await pathExists(backupDir)) {
315
+ await rename(backupDir, outputDir);
316
+ } else if (await pathExists(backupDir)) {
317
+ await rm(backupDir, {
318
+ recursive: true,
319
+ force: true
320
+ });
321
+ }
322
+ if (await pathExists(outputDir)) {
323
+ await rename(outputDir, backupDir);
324
+ }
325
+ await rename(nextDir, outputDir);
326
+ await rm(backupDir, {
327
+ recursive: true,
328
+ force: true
329
+ }).catch((error) => {
330
+ console.warn(`Failed to remove leftover ${backupDir} after publish:`, error);
331
+ });
332
+ } catch (error) {
333
+ await rm(nextDir, {
334
+ recursive: true,
335
+ force: true
336
+ }).catch(() => void 0);
337
+ if (!await pathExists(outputDir) && await pathExists(backupDir)) {
338
+ await rename(backupDir, outputDir).catch(() => void 0);
339
+ }
340
+ throw error;
341
+ }
342
+ }, "publishArtifacts");
343
+ var buildPermissionRepairDockerArgs = /* @__PURE__ */ __name((dir, imageRef) => [
344
+ "run",
345
+ "--rm",
346
+ "--platform",
347
+ VERIFIABLE_BUILD_PLATFORM,
348
+ "--user",
349
+ "0:0",
350
+ "--entrypoint",
351
+ "chmod",
352
+ "-v",
353
+ `${dir}:/cleanup`,
354
+ imageRef,
355
+ "-R",
356
+ "a+rwX",
357
+ "/cleanup"
358
+ ], "buildPermissionRepairDockerArgs");
359
+ var relaxDockerOwnedPermissions = /* @__PURE__ */ __name((dir, imageRef) => new Promise((resolve, reject) => {
360
+ const child = spawn("docker", buildPermissionRepairDockerArgs(dir, imageRef), {
361
+ stdio: "inherit"
362
+ });
363
+ child.on("error", reject);
364
+ child.on("close", (code) => {
365
+ if (code === 0) {
366
+ resolve();
367
+ } else {
368
+ reject(new Error(`Failed to chmod temp dir via docker (exit ${code ?? 1})`));
369
+ }
370
+ });
371
+ }), "relaxDockerOwnedPermissions");
372
+ var removeTempDir = /* @__PURE__ */ __name(async (tempDir, resolveImage) => {
373
+ try {
374
+ await rm(tempDir, {
375
+ recursive: true,
376
+ force: true
377
+ });
378
+ } catch (error) {
379
+ const code = error.code;
380
+ if (code !== "EACCES" && code !== "EPERM") {
381
+ throw error;
382
+ }
383
+ if (resolveImage === void 0) {
384
+ throw error;
385
+ }
386
+ const { imageRef } = await resolveImage();
387
+ await relaxDockerOwnedPermissions(tempDir, imageRef);
388
+ await rm(tempDir, {
389
+ recursive: true,
390
+ force: true
391
+ });
392
+ }
393
+ }, "removeTempDir");
394
+ var runVerifiableBuildFromArchive = /* @__PURE__ */ __name(async ({ archive, packages, outputDir, stellarVersion, rustVersion }, { cwd }) => {
395
+ if (packages.length === 0) {
396
+ throw new Error("verifiable-build requires at least one --package <name>:<manifest-path>");
397
+ }
398
+ validatePackageSpecs(packages);
399
+ const archiveBytes = await readArchiveBytes(archive);
400
+ const sourceSha256 = createHash("sha256").update(archiveBytes).digest("hex");
401
+ const tempDir = await mkdtemp(path.join(tmpdir(), "stellar-verifiable-build-"));
402
+ const extractionDir = path.join(tempDir, "source");
403
+ const stagingDir = path.join(tempDir, "staging");
404
+ let versions;
405
+ const wrapper = new VerifiableBuildWrapper();
406
+ try {
407
+ const rootDirName = path.basename(cwd);
408
+ await extractZip(archiveBytes, extractionDir, rootDirName);
409
+ const buildRoot = path.join(extractionDir, rootDirName);
410
+ if (!await pathExists(buildRoot) || !(await stat(buildRoot)).isDirectory()) {
411
+ throw new Error(`Expected top-level ${rootDirName}/ directory not found after extraction`);
412
+ }
413
+ versions = {
414
+ stellarVersion,
415
+ rustVersion: await resolveRustVersion(buildRoot, rustVersion)
416
+ };
417
+ await persistSourceArchive(archiveBytes, stagingDir);
418
+ for (const packageSpec of packages) {
419
+ await wrapper.run(buildArchiveContractArgs(packageSpec, sourceSha256), versions, {
420
+ cwd
421
+ }, buildRoot);
422
+ await persistWasm(buildRoot, stagingDir, packageSpec, async () => {
423
+ const { imageRef } = await wrapper.resolveImage(versions);
424
+ await relaxDockerOwnedPermissions(buildRoot, imageRef);
425
+ });
426
+ }
427
+ await publishArtifacts(stagingDir, outputDir);
428
+ } finally {
429
+ await removeTempDir(tempDir, versions === void 0 ? void 0 : () => wrapper.resolveImage(versions)).catch((error) => {
430
+ console.warn(`Temp dir cleanup failed (build result unchanged): ${tempDir}`, error);
431
+ });
432
+ }
433
+ }, "runVerifiableBuildFromArchive");
434
+
435
+ export { VerifiableBuildWrapper, buildArchiveContractArgs, buildPermissionRepairDockerArgs, buildVerifiableBuildDockerArgs, canonicalizeMetaArgs, copyFileWithPermissionRepair, officialImageTagRef, parseAmd64Digest, parsePackageSpec, resolveBuildDir, resolveRustVersion, runVerifiableBuildFromArchive, wasmArtifactName };
436
+ //# sourceMappingURL=D25LP26W.js.map
437
+ //# sourceMappingURL=D25LP26W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/verifiable-build.ts"],"names":["execFileAsync","promisify","execFile","SOURCE_ARCHIVE_NAME","WASM_TARGET_DIR","path","join","SOURCE_MOUNT","VERIFIABLE_BUILD_PLATFORM","OFFICIAL_IMAGE_REPO","META_FLAG","officialImageTagRef","stellarVersion","rustVersion","parseAmd64Digest","manifestInspectJson","manifests","JSON","parse","Array","isArray","Error","digest","find","platform","os","architecture","startsWith","resolveAmd64Digest","imageTagRef","stdout","maxBuffer","timeout","cause","metaKey","entry","eq","indexOf","slice","canonicalizeMetaArgs","buildArgs","injectedMeta","reservedKeys","Set","map","metas","passthrough","addCallerMeta","value","has","push","i","length","arg","undefined","sort","flatMap","meta","buildVerifiableBuildDockerArgs","imageRef","sourceDir","bldimg","resolveBuildDir","cwd","resolve","runDocker","dockerArgs","Promise","reject","child","spawn","stdio","on","error","code","signal","VerifiableBuildWrapper","imagesByTag","Map","resolveDigest","resolveImage","tagRef","existing","get","resolved","then","set","run","args","versions","buildDir","stat","isDirectory","chmod","console","info","parsePackageSpec","spec","colon","stringify","packageName","manifestPath","wasmArtifactName","replaceAll","validatePackageSpecs","packages","artifactNames","artifactName","add","resolveRustVersion","rustVersionFlag","toolchainPath","contents","readFile","parsed","channel","toolchain","buildArchiveContractArgs","sourceSha256","pathExists","filePath","readArchiveBytes","archive","bytes","Uint8Array","extractZip","destDir","expectedRootDirName","files","unzipSync","destRoot","expectedRoot","expectedRootPrefix","relPath","content","Object","entries","outPath","sep","endsWith","mkdir","dirname","recursive","writeFile","persistSourceArchive","archiveBytes","stagingDir","copyFileWithPermissionRepair","source","destination","repairPermissions","copy","copyFile","persistWasm","buildRoot","wasmName","builtPath","publishArtifacts","outputDir","parentDir","outputBase","basename","nextDir","mkdtemp","backupDir","readdir","rename","rm","force","catch","warn","buildPermissionRepairDockerArgs","dir","relaxDockerOwnedPermissions","removeTempDir","tempDir","runVerifiableBuildFromArchive","createHash","update","tmpdir","extractionDir","wrapper","rootDirName","packageSpec"],"mappings":"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","file":"D25LP26W.js","sourcesContent":["import { unzipSync } from 'fflate';\nimport { execFile, spawn } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n chmod,\n copyFile,\n mkdir,\n mkdtemp,\n readdir,\n readFile,\n rename,\n rm,\n stat,\n writeFile,\n} from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\nimport { parse } from 'toml';\n\nimport type { ToolCommandExecutionOptions } from '@layerzerolabs/vm-tooling';\n\nconst execFileAsync = promisify(execFile);\n\nconst SOURCE_ARCHIVE_NAME = 'contracts-source.zip';\nconst WASM_TARGET_DIR = path.join('target', 'wasm32v1-none', 'release');\n\n// The self-contained source is mounted here and built in place. The official image's WORKDIR is\n// already /source; we set it explicitly for clarity.\nconst SOURCE_MOUNT = '/source';\n\n// Canonical reproducible platform. External verifiers reproduce the amd64 artifact, so we always\n// run the amd64 image regardless of the host arch (the daemon emulates it when needed).\nconst VERIFIABLE_BUILD_PLATFORM = 'linux/amd64';\n\nconst OFFICIAL_IMAGE_REPO = 'stellar/stellar-cli';\n\nconst META_FLAG = '--meta';\n\ninterface RustToolchainToml {\n toolchain?: {\n channel?: string;\n };\n}\n\n// The subset of `docker manifest inspect` output (an OCI image index) that we read.\ninterface ManifestDescriptor {\n digest?: string;\n platform?: { os?: string; architecture?: string };\n}\ninterface ManifestIndex {\n manifests?: ManifestDescriptor[];\n}\n\nexport interface PackageSpec {\n packageName: string;\n manifestPath: string;\n}\n\nexport interface VerifiableBuildVersions {\n stellarVersion: string;\n rustVersion: string;\n}\n\nexport interface ResolvedVerifiableBuildImage {\n imageRef: string;\n bldimg: string;\n tagRef: string;\n}\n\nexport interface RunVerifiableBuildFromArchiveOptions {\n archive: string;\n packages: PackageSpec[];\n outputDir: string;\n stellarVersion: string;\n rustVersion?: string;\n}\n\n/**\n * The official reproducible image reference for a (Stellar CLI, Rust) version pair, e.g.\n * `stellar/stellar-cli:25.1.0-rust1.90.0-slim-bookworm`. The caller pins both versions; this is the\n * only image the tool builds against.\n */\nexport const officialImageTagRef = (stellarVersion: string, rustVersion: string): string =>\n `${OFFICIAL_IMAGE_REPO}:${stellarVersion}-rust${rustVersion}-slim-bookworm`;\n\n/**\n * Pick the linux/amd64 manifest digest out of `docker manifest inspect` output. Pure/synchronous so\n * the selection (skip the arm64 and the unknown/unknown attestation entries) is unit-testable.\n */\nexport const parseAmd64Digest = (manifestInspectJson: string): string => {\n const { manifests } = JSON.parse(manifestInspectJson) as ManifestIndex;\n\n if (!Array.isArray(manifests)) {\n throw new Error(\n '`docker manifest inspect` did not return a multi-arch index (no `manifests` array)',\n );\n }\n\n const digest = manifests.find(\n ({ platform }) => platform?.os === 'linux' && platform?.architecture === 'amd64',\n )?.digest;\n\n if (typeof digest !== 'string' || !digest.startsWith('sha256:')) {\n throw new Error('No linux/amd64 manifest digest found in `docker manifest inspect` output');\n }\n\n return digest;\n};\n\n/**\n * Resolve the immutable linux/amd64 digest of a `stellar/stellar-cli` tag via a daemon-less\n * registry query (`docker manifest inspect`). This is the reproducible reference an external\n * verifier pins to (SEP-58).\n */\nconst resolveAmd64Digest = async (imageTagRef: string): Promise<string> => {\n try {\n const { stdout } = await execFileAsync('docker', ['manifest', 'inspect', imageTagRef], {\n maxBuffer: 16 * 1024 * 1024,\n timeout: 30_000,\n });\n return parseAmd64Digest(stdout);\n } catch (cause) {\n throw new Error(\n `Failed to resolve the linux/amd64 digest of ${imageTagRef} (\\`docker manifest inspect\\`)`,\n { cause },\n );\n }\n};\n\n/** The `key` of a `key=value` meta entry (the whole string when there is no `=`). */\nconst metaKey = (entry: string): string => {\n const eq = entry.indexOf('=');\n return eq === -1 ? entry : entry.slice(0, eq);\n};\n\n/**\n * Canonicalize `stellar contract build` args so the embedded metadata order is stable.\n *\n * Soroban stores contract metadata as an ORDERED sequence, so the order of `--meta key=value`\n * flags changes the WASM bytes. To keep the build reproducible, every meta entry — the caller's\n * plus the tool-injected ones — is pulled out, merged, and re-emitted in sorted order.\n *\n * Injected keys (e.g. `bldimg`) are tool-controlled and RESERVED: any caller `--meta` reusing an\n * injected key is dropped.\n */\nexport const canonicalizeMetaArgs = (buildArgs: string[], injectedMeta: string[]): string[] => {\n const reservedKeys = new Set(injectedMeta.map(metaKey));\n const metas = [...injectedMeta];\n const passthrough: string[] = [];\n\n const addCallerMeta = (value: string): void => {\n if (!reservedKeys.has(metaKey(value))) metas.push(value);\n };\n\n for (let i = 0; i < buildArgs.length; i++) {\n const arg = buildArgs[i];\n if (arg === undefined) continue;\n if (arg === META_FLAG) {\n const value = buildArgs[i + 1];\n if (value !== undefined && !value.startsWith('--')) {\n addCallerMeta(value);\n i += 1;\n }\n } else if (arg.startsWith(`${META_FLAG}=`)) {\n addCallerMeta(arg.slice(META_FLAG.length + 1));\n } else {\n passthrough.push(arg);\n }\n }\n\n metas.sort();\n return [...passthrough, ...metas.flatMap((meta) => [META_FLAG, meta])];\n};\n\n/**\n * Assemble the `docker run` argv for a verifiable build. Kept pure and synchronous so the mount /\n * workdir layout and the tool-injected `--meta bldimg=…` are unit-testable without Docker.\n */\nexport const buildVerifiableBuildDockerArgs = ({\n imageRef,\n sourceDir,\n buildArgs,\n bldimg,\n}: {\n imageRef: string;\n sourceDir: string;\n buildArgs: string[];\n bldimg: string;\n}): string[] => [\n 'run',\n '--rm',\n '--platform',\n VERIFIABLE_BUILD_PLATFORM,\n '-v',\n `${sourceDir}:${SOURCE_MOUNT}`,\n '-w',\n SOURCE_MOUNT,\n imageRef,\n 'contract',\n 'build',\n ...canonicalizeMetaArgs(buildArgs, [`bldimg=${bldimg}`]),\n];\n\n/**\n * Resolve the directory to build. An explicit `sourceDir` that is relative resolves against the\n * cwd; an absolute one is used as-is; omitting it falls back to the cwd.\n */\nexport const resolveBuildDir = (cwd: string, sourceDir?: string): string =>\n path.resolve(cwd, sourceDir ?? '.');\n\nconst runDocker = (dockerArgs: string[]): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn('docker', dockerArgs, { stdio: 'inherit' });\n child.on('error', (error) =>\n reject(new Error('Failed to spawn docker for the verifiable build', { cause: error })),\n );\n child.on('close', (code, signal) => {\n if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `Verifiable build failed: docker exited with ${\n signal ? `signal ${signal}` : `code ${code}`\n }`,\n ),\n );\n }\n });\n });\n\n/**\n * Reproducible `stellar contract build` inside the official `stellar/stellar-cli` image.\n * Used by the archive orchestrator for each `--package`.\n */\nexport class VerifiableBuildWrapper {\n private readonly imagesByTag = new Map<string, Promise<ResolvedVerifiableBuildImage>>();\n\n public constructor(\n private readonly resolveDigest: (\n imageTagRef: string,\n ) => Promise<string> = resolveAmd64Digest,\n ) {}\n\n public resolveImage({\n stellarVersion,\n rustVersion,\n }: VerifiableBuildVersions): Promise<ResolvedVerifiableBuildImage> {\n const tagRef = officialImageTagRef(stellarVersion, rustVersion);\n const existing = this.imagesByTag.get(tagRef);\n if (existing !== undefined) {\n return existing;\n }\n\n const resolved = this.resolveDigest(tagRef).then((digest) => ({\n imageRef: `${OFFICIAL_IMAGE_REPO}@${digest}`,\n bldimg: `docker.io/${OFFICIAL_IMAGE_REPO}@${digest}`,\n tagRef,\n }));\n this.imagesByTag.set(tagRef, resolved);\n return resolved;\n }\n\n public async run(\n args: string[],\n versions: VerifiableBuildVersions,\n { cwd }: Pick<ToolCommandExecutionOptions, 'cwd'>,\n sourceDir?: string,\n ): Promise<void> {\n const buildDir = resolveBuildDir(cwd, sourceDir);\n try {\n if (!(await stat(buildDir)).isDirectory()) {\n throw new Error('not a directory');\n }\n } catch (cause) {\n throw new Error(\n `Verifiable build source directory is not an existing directory: ${buildDir}`,\n { cause },\n );\n }\n\n // The official stellar-cli image runs as a non-host UID and must create cargo target\n // dirs under the bind-mounted source. Do not pass --user (that would diverge from what\n // external verifiers run). Only chmod when a sourceDir is passed (typically a\n // throwaway extract dir); never world-write the process cwd.\n if (sourceDir !== undefined) {\n await chmod(buildDir, 0o777);\n }\n\n const { imageRef, bldimg, tagRef } = await this.resolveImage(versions);\n\n const dockerArgs = buildVerifiableBuildDockerArgs({\n imageRef,\n sourceDir: buildDir,\n buildArgs: args,\n bldimg,\n });\n\n console.info('🔒 Verifiable build (official stellar/stellar-cli image, run from host)');\n console.info(` source: ${buildDir}`);\n console.info(` image: ${imageRef} (${VERIFIABLE_BUILD_PLATFORM}, from tag ${tagRef})`);\n console.info(` bldimg: ${bldimg}`);\n console.info(` docker ${dockerArgs.join(' ')}`);\n\n await runDocker(dockerArgs);\n }\n}\n\n/**\n * Parse a `--package <name>:<manifest-path>` pair. Both sides must be non-empty.\n */\nexport const parsePackageSpec = (spec: string): PackageSpec => {\n const colon = spec.indexOf(':');\n if (colon <= 0 || colon === spec.length - 1) {\n throw new Error(\n `Invalid --package spec ${JSON.stringify(spec)}: expected <name>:<manifest-path>`,\n );\n }\n\n return {\n packageName: spec.slice(0, colon),\n manifestPath: spec.slice(colon + 1),\n };\n};\n\n/** Soroban wasm artifact basename: hyphens in the package name become underscores. */\nexport const wasmArtifactName = (packageName: string): string =>\n `${packageName.replaceAll('-', '_')}.wasm`;\n\nconst validatePackageSpecs = (packages: PackageSpec[]): void => {\n const artifactNames = new Set<string>();\n for (const { packageName } of packages) {\n const artifactName = wasmArtifactName(packageName);\n if (artifactNames.has(artifactName)) {\n throw new Error(`Duplicate WASM artifact ${artifactName} from --package options`);\n }\n artifactNames.add(artifactName);\n }\n};\n\n/**\n * Resolve the Rust toolchain version for the verifiable build image tag. An explicit\n * `--rust-version` wins; otherwise read the pinned channel from the supplied source directory.\n */\nexport const resolveRustVersion = async (\n sourceDir: string,\n rustVersionFlag?: string,\n): Promise<string> => {\n if (rustVersionFlag !== undefined) {\n return rustVersionFlag;\n }\n\n const toolchainPath = path.join(sourceDir, 'rust-toolchain.toml');\n let contents: string;\n try {\n contents = await readFile(toolchainPath, 'utf-8');\n } catch (cause) {\n if ((cause as { code?: string }).code === 'ENOENT') {\n throw new Error(\n `Missing rust-toolchain.toml in ${sourceDir} and no --rust-version was provided`,\n { cause },\n );\n }\n throw cause;\n }\n\n const parsed = parse(contents) as RustToolchainToml;\n const channel = parsed.toolchain?.channel;\n if (typeof channel !== 'string' || channel.length === 0) {\n throw new Error(`Missing 'toolchain.channel' in ${toolchainPath}`);\n }\n\n return channel;\n};\n\n/**\n * Build `stellar contract build` args for one archive package. Embeds SEP-58 `source_sha256`\n * and replays the build flags as `bldopt=` metas so external verifiers can reproduce the build.\n * `bldimg` is injected separately by the official-image runner.\n */\nexport const buildArchiveContractArgs = (\n { packageName, manifestPath }: PackageSpec,\n sourceSha256: string,\n): string[] => [\n '--manifest-path',\n manifestPath,\n '--package',\n packageName,\n '--optimize',\n '--meta',\n `bldopt=--manifest-path=${manifestPath}`,\n '--meta',\n `bldopt=--package=${packageName}`,\n '--meta',\n 'bldopt=--optimize',\n '--meta',\n `source_sha256=${sourceSha256}`,\n];\n\nconst pathExists = async (filePath: string): Promise<boolean> => {\n try {\n await stat(filePath);\n return true;\n } catch (error) {\n if ((error as { code?: string }).code === 'ENOENT') {\n return false;\n }\n throw error;\n }\n};\n\nconst readArchiveBytes = async (archive: string): Promise<Uint8Array> => {\n let bytes: Uint8Array;\n try {\n bytes = new Uint8Array(await readFile(archive));\n } catch (cause) {\n throw new Error(`Archive not found or unreadable: ${archive}`, { cause });\n }\n\n if (bytes.length === 0) {\n throw new Error(`Archive is empty: ${archive}`);\n }\n\n return bytes;\n};\n\nconst extractZip = async (\n bytes: Uint8Array,\n destDir: string,\n expectedRootDirName: string,\n): Promise<void> => {\n const files = unzipSync(bytes);\n const destRoot = path.resolve(destDir);\n const expectedRoot = path.join(destRoot, expectedRootDirName);\n const expectedRootPrefix = `${expectedRootDirName}/`;\n\n for (const [relPath, content] of Object.entries(files)) {\n const outPath = path.resolve(destRoot, relPath);\n if (outPath !== destRoot && !outPath.startsWith(destRoot + path.sep)) {\n throw new Error(`Zip entry escapes destination: ${relPath}`);\n }\n if (outPath !== expectedRoot && !outPath.startsWith(expectedRoot + path.sep)) {\n throw new Error(\n `Zip entry is outside expected top-level ${expectedRootPrefix}: ${relPath}`,\n );\n }\n if (relPath.endsWith('/')) continue;\n\n await mkdir(path.dirname(outPath), { recursive: true });\n await writeFile(outPath, content);\n }\n};\n\nconst persistSourceArchive = async (\n archiveBytes: Uint8Array,\n stagingDir: string,\n): Promise<void> => {\n await mkdir(stagingDir, { recursive: true });\n await writeFile(path.join(stagingDir, SOURCE_ARCHIVE_NAME), archiveBytes);\n};\n\nexport const copyFileWithPermissionRepair = async (\n source: string,\n destination: string,\n repairPermissions: () => Promise<void>,\n copy: (source: string, destination: string) => Promise<void> = copyFile,\n): Promise<void> => {\n try {\n await copy(source, destination);\n } catch (error) {\n const code = (error as { code?: string }).code;\n if (code !== 'EACCES' && code !== 'EPERM') {\n throw error;\n }\n\n await repairPermissions();\n await copy(source, destination);\n }\n};\n\nconst persistWasm = async (\n buildRoot: string,\n stagingDir: string,\n { packageName }: PackageSpec,\n repairPermissions: () => Promise<void>,\n): Promise<void> => {\n const wasmName = wasmArtifactName(packageName);\n const builtPath = path.join(buildRoot, WASM_TARGET_DIR, wasmName);\n if (!(await pathExists(builtPath))) {\n throw new Error(`Expected WASM not found after build: ${builtPath}`);\n }\n\n await mkdir(stagingDir, { recursive: true });\n await copyFileWithPermissionRepair(\n builtPath,\n path.join(stagingDir, wasmName),\n repairPermissions,\n );\n};\n\n/**\n * Atomically replace the output directory with the complete staged artifact set.\n * Mirrors protocol stellar's `.next-` / `.prev` swap so failed builds leave prior output intact.\n */\nconst publishArtifacts = async (stagingDir: string, outputDir: string): Promise<void> => {\n const parentDir = path.dirname(outputDir);\n const outputBase = path.basename(outputDir);\n await mkdir(parentDir, { recursive: true });\n\n const nextDir = await mkdtemp(path.join(parentDir, `${outputBase}.next-`));\n const backupDir = path.join(parentDir, `${outputBase}.prev`);\n const entries = await readdir(stagingDir);\n\n try {\n for (const entry of entries) {\n await copyFile(path.join(stagingDir, entry), path.join(nextDir, entry));\n }\n\n if (!(await pathExists(outputDir)) && (await pathExists(backupDir))) {\n await rename(backupDir, outputDir);\n } else if (await pathExists(backupDir)) {\n await rm(backupDir, { recursive: true, force: true });\n }\n\n if (await pathExists(outputDir)) {\n await rename(outputDir, backupDir);\n }\n await rename(nextDir, outputDir);\n await rm(backupDir, { recursive: true, force: true }).catch((error) => {\n console.warn(`Failed to remove leftover ${backupDir} after publish:`, error);\n });\n } catch (error) {\n await rm(nextDir, { recursive: true, force: true }).catch(() => undefined);\n if (!(await pathExists(outputDir)) && (await pathExists(backupDir))) {\n await rename(backupDir, outputDir).catch(() => undefined);\n }\n throw error;\n }\n};\n\nexport const buildPermissionRepairDockerArgs = (dir: string, imageRef: string): string[] => [\n 'run',\n '--rm',\n '--platform',\n VERIFIABLE_BUILD_PLATFORM,\n '--user',\n '0:0',\n '--entrypoint',\n 'chmod',\n '-v',\n `${dir}:/cleanup`,\n imageRef,\n '-R',\n 'a+rwX',\n '/cleanup',\n];\n\nconst relaxDockerOwnedPermissions = (dir: string, imageRef: string): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn('docker', buildPermissionRepairDockerArgs(dir, imageRef), {\n stdio: 'inherit',\n });\n child.on('error', reject);\n child.on('close', (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Failed to chmod temp dir via docker (exit ${code ?? 1})`));\n }\n });\n });\n\nconst removeTempDir = async (\n tempDir: string,\n resolveImage?: () => Promise<ResolvedVerifiableBuildImage>,\n): Promise<void> => {\n try {\n await rm(tempDir, { recursive: true, force: true });\n } catch (error) {\n const code = (error as { code?: string }).code;\n if (code !== 'EACCES' && code !== 'EPERM') {\n throw error;\n }\n if (resolveImage === undefined) {\n throw error;\n }\n\n const { imageRef } = await resolveImage();\n await relaxDockerOwnedPermissions(tempDir, imageRef);\n await rm(tempDir, { recursive: true, force: true });\n }\n};\n\n/**\n * Build one or more Stellar contracts from a self-contained source archive.\n *\n * `packages` is intentionally already parsed: the CLI owns string parsing, while this orchestrator\n * deals only in validated package/manifest pairs.\n */\nexport const runVerifiableBuildFromArchive = async (\n {\n archive,\n packages,\n outputDir,\n stellarVersion,\n rustVersion,\n }: RunVerifiableBuildFromArchiveOptions,\n { cwd }: Pick<ToolCommandExecutionOptions, 'cwd'>,\n): Promise<void> => {\n if (packages.length === 0) {\n throw new Error('verifiable-build requires at least one --package <name>:<manifest-path>');\n }\n validatePackageSpecs(packages);\n\n const archiveBytes = await readArchiveBytes(archive);\n const sourceSha256 = createHash('sha256').update(archiveBytes).digest('hex');\n const tempDir = await mkdtemp(path.join(tmpdir(), 'stellar-verifiable-build-'));\n const extractionDir = path.join(tempDir, 'source');\n const stagingDir = path.join(tempDir, 'staging');\n let versions: VerifiableBuildVersions | undefined;\n const wrapper = new VerifiableBuildWrapper();\n\n try {\n const rootDirName = path.basename(cwd);\n await extractZip(archiveBytes, extractionDir, rootDirName);\n\n const buildRoot = path.join(extractionDir, rootDirName);\n if (!(await pathExists(buildRoot)) || !(await stat(buildRoot)).isDirectory()) {\n throw new Error(\n `Expected top-level ${rootDirName}/ directory not found after extraction`,\n );\n }\n\n versions = {\n stellarVersion,\n rustVersion: await resolveRustVersion(buildRoot, rustVersion),\n };\n await persistSourceArchive(archiveBytes, stagingDir);\n\n for (const packageSpec of packages) {\n await wrapper.run(\n buildArchiveContractArgs(packageSpec, sourceSha256),\n versions,\n { cwd },\n buildRoot,\n );\n await persistWasm(buildRoot, stagingDir, packageSpec, async () => {\n const { imageRef } = await wrapper.resolveImage(versions!);\n await relaxDockerOwnedPermissions(buildRoot, imageRef);\n });\n }\n\n await publishArtifacts(stagingDir, outputDir);\n } finally {\n await removeTempDir(\n tempDir,\n versions === undefined ? undefined : () => wrapper.resolveImage(versions!),\n ).catch((error) => {\n console.warn(`Temp dir cleanup failed (build result unchanged): ${tempDir}`, error);\n });\n }\n};\n"]}
@@ -1,36 +1,49 @@
1
1
  import type { ToolCommandExecutionOptions } from '@layerzerolabs/vm-tooling';
2
+ export interface PackageSpec {
3
+ packageName: string;
4
+ manifestPath: string;
5
+ }
6
+ export interface VerifiableBuildVersions {
7
+ stellarVersion: string;
8
+ rustVersion: string;
9
+ }
10
+ export interface ResolvedVerifiableBuildImage {
11
+ imageRef: string;
12
+ bldimg: string;
13
+ tagRef: string;
14
+ }
15
+ export interface RunVerifiableBuildFromArchiveOptions {
16
+ archive: string;
17
+ packages: PackageSpec[];
18
+ outputDir: string;
19
+ stellarVersion: string;
20
+ rustVersion?: string;
21
+ }
2
22
  /**
3
23
  * The official reproducible image reference for a (Stellar CLI, Rust) version pair, e.g.
4
24
  * `stellar/stellar-cli:25.1.0-rust1.90.0-slim-bookworm`. The caller pins both versions; this is the
5
25
  * only image the tool builds against.
6
26
  */
7
27
  export declare const officialImageTagRef: (stellarVersion: string, rustVersion: string) => string;
28
+ /**
29
+ * Pick the linux/amd64 manifest digest out of `docker manifest inspect` output. Pure/synchronous so
30
+ * the selection (skip the arm64 and the unknown/unknown attestation entries) is unit-testable.
31
+ */
8
32
  export declare const parseAmd64Digest: (manifestInspectJson: string) => string;
9
33
  /**
10
34
  * Canonicalize `stellar contract build` args so the embedded metadata order is stable.
11
35
  *
12
36
  * Soroban stores contract metadata as an ORDERED sequence, so the order of `--meta key=value`
13
- * flags changes the WASM bytes (verified: swapping two `--meta` flags yields a different WASM
14
- * hash). To keep the build reproducible regardless of the order the caller passed `--meta`, every
15
- * meta entry — the caller's plus the tool-injected ones — is pulled out, merged, and re-emitted in
16
- * sorted order. Non-meta args keep their original relative order and precede the sorted metas.
37
+ * flags changes the WASM bytes. To keep the build reproducible, every meta entry — the caller's
38
+ * plus the tool-injected ones — is pulled out, merged, and re-emitted in sorted order.
17
39
  *
18
40
  * Injected keys (e.g. `bldimg`) are tool-controlled and RESERVED: any caller `--meta` reusing an
19
- * injected key is dropped, so a caller can never override the recorded build image by key
20
- * collision (before sorting, the injected entry was always appended last and won on its own).
21
- *
22
- * Both `--meta k=v` and `--meta=k=v` forms are recognized; a dangling `--meta` with no value (or
23
- * one followed by another flag) is dropped.
41
+ * injected key is dropped.
24
42
  */
25
43
  export declare const canonicalizeMetaArgs: (buildArgs: string[], injectedMeta: string[]) => string[];
26
44
  /**
27
45
  * Assemble the `docker run` argv for a verifiable build. Kept pure and synchronous so the mount /
28
46
  * workdir layout and the tool-injected `--meta bldimg=…` are unit-testable without Docker.
29
- *
30
- * The official image's ENTRYPOINT is `stellar`, so the trailing `contract build …` runs under it.
31
- * The source directory is assumed self-contained, so it is mounted at /source and built in place —
32
- * no surrounding workspace is required. All `--meta` flags (the caller's plus the injected
33
- * `bldimg`) are sorted into a canonical order so the WASM hash is independent of `--meta` ordering.
34
47
  */
35
48
  export declare const buildVerifiableBuildDockerArgs: ({ imageRef, sourceDir, buildArgs, bldimg, }: {
36
49
  imageRef: string;
@@ -40,36 +53,44 @@ export declare const buildVerifiableBuildDockerArgs: ({ imageRef, sourceDir, bui
40
53
  }) => string[];
41
54
  /**
42
55
  * Resolve the directory to build. An explicit `sourceDir` that is relative resolves against the
43
- * cwd; an absolute one is used as-is; omitting it falls back to the cwd. Kept pure/synchronous so
44
- * the cwd-vs-explicit-folder precedence is unit-testable without Docker.
45
- *
46
- * This is what lets the pipeline decompress a packaged source archive into a scratch directory and
47
- * build that, instead of always building the process cwd.
56
+ * cwd; an absolute one is used as-is; omitting it falls back to the cwd.
48
57
  */
49
58
  export declare const resolveBuildDir: (cwd: string, sourceDir?: string) => string;
50
- export interface VerifiableBuildVersions {
51
- stellarVersion: string;
52
- rustVersion: string;
53
- }
54
59
  /**
55
- * Reproducible `stellar contract build` that runs inside the OFFICIAL `stellar/stellar-cli` image —
56
- * the exact package an external verifier uses — instead of our own dev image (whose sccache/mold
57
- * layers could change the WASM).
58
- *
59
- * The build runs the official image directly from the HOST: our TypeScript CLI already executes on
60
- * the host runner, so it can `docker run` the official image itself. This is what an external
61
- * verifier's plain `docker run` does, and it means we never bind-mount the host Docker socket into
62
- * a container — eliminating the container-escape / secret-leak surface that mounting the socket
63
- * would create.
64
- *
65
- * The image is `stellar/stellar-cli:<stellarVersion>-rust<rustVersion>-slim-bookworm`, pinned by the
66
- * caller. For a stable reference we resolve it to its linux/amd64 digest and both RUN that digest
67
- * and embed it as the `bldimg` WASM metadata (`docker.io/stellar/stellar-cli@sha256:…`) — the tool
68
- * does this automatically so callers never hand-inject `--meta bldimg=…`. The source directory (the
69
- * cwd, assumed self-contained) is mounted at /source and built in place, and the official image runs
70
- * as its own user/toolchain.
60
+ * Reproducible `stellar contract build` inside the official `stellar/stellar-cli` image.
61
+ * Used by the archive orchestrator for each `--package`.
71
62
  */
72
63
  export declare class VerifiableBuildWrapper {
73
- run(args: string[], { stellarVersion, rustVersion }: VerifiableBuildVersions, options: ToolCommandExecutionOptions, sourceDir?: string): Promise<void>;
64
+ private readonly resolveDigest;
65
+ private readonly imagesByTag;
66
+ constructor(resolveDigest?: (imageTagRef: string) => Promise<string>);
67
+ resolveImage({ stellarVersion, rustVersion, }: VerifiableBuildVersions): Promise<ResolvedVerifiableBuildImage>;
68
+ run(args: string[], versions: VerifiableBuildVersions, { cwd }: Pick<ToolCommandExecutionOptions, 'cwd'>, sourceDir?: string): Promise<void>;
74
69
  }
70
+ /**
71
+ * Parse a `--package <name>:<manifest-path>` pair. Both sides must be non-empty.
72
+ */
73
+ export declare const parsePackageSpec: (spec: string) => PackageSpec;
74
+ /** Soroban wasm artifact basename: hyphens in the package name become underscores. */
75
+ export declare const wasmArtifactName: (packageName: string) => string;
76
+ /**
77
+ * Resolve the Rust toolchain version for the verifiable build image tag. An explicit
78
+ * `--rust-version` wins; otherwise read the pinned channel from the supplied source directory.
79
+ */
80
+ export declare const resolveRustVersion: (sourceDir: string, rustVersionFlag?: string) => Promise<string>;
81
+ /**
82
+ * Build `stellar contract build` args for one archive package. Embeds SEP-58 `source_sha256`
83
+ * and replays the build flags as `bldopt=` metas so external verifiers can reproduce the build.
84
+ * `bldimg` is injected separately by the official-image runner.
85
+ */
86
+ export declare const buildArchiveContractArgs: ({ packageName, manifestPath }: PackageSpec, sourceSha256: string) => string[];
87
+ export declare const copyFileWithPermissionRepair: (source: string, destination: string, repairPermissions: () => Promise<void>, copy?: (source: string, destination: string) => Promise<void>) => Promise<void>;
88
+ export declare const buildPermissionRepairDockerArgs: (dir: string, imageRef: string) => string[];
89
+ /**
90
+ * Build one or more Stellar contracts from a self-contained source archive.
91
+ *
92
+ * `packages` is intentionally already parsed: the CLI owns string parsing, while this orchestrator
93
+ * deals only in validated package/manifest pairs.
94
+ */
95
+ export declare const runVerifiableBuildFromArchive: ({ archive, packages, outputDir, stellarVersion, rustVersion, }: RunVerifiableBuildFromArchiveOptions, { cwd }: Pick<ToolCommandExecutionOptions, "cwd">) => Promise<void>;
75
96
  //# sourceMappingURL=verifiable-build.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"verifiable-build.d.ts","sourceRoot":"","sources":["../../src/commands/verifiable-build.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,2BAA2B,CAAC;AAc7E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,gBAAgB,MAAM,EAAE,aAAa,MAAM,KAAG,MACH,CAAC;AAehF,eAAO,MAAM,gBAAgB,GAAI,qBAAqB,MAAM,KAAG,MAkB9D,CAAC;AA8BF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,EAAE,EAAE,cAAc,MAAM,EAAE,KAAG,MAAM,EA8BxF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,8BAA8B,GAAI,6CAK5C;IACC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAClB,KAAG,MAAM,EAeT,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,GAAI,KAAK,MAAM,EAAE,YAAY,MAAM,KAAG,MAC3B,CAAC;AAuBxC,MAAM,WAAW,uBAAuB;IACpC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,sBAAsB;IAClB,GAAG,CACZ,IAAI,EAAE,MAAM,EAAE,EACd,EAAE,cAAc,EAAE,WAAW,EAAE,EAAE,uBAAuB,EACxD,OAAO,EAAE,2BAA2B,EACpC,SAAS,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,IAAI,CAAC;CAyCnB"}
1
+ {"version":3,"file":"verifiable-build.d.ts","sourceRoot":"","sources":["../../src/commands/verifiable-build.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export { VerifiableBuildWrapper, buildVerifiableBuildDockerArgs, canonicalizeMetaArgs, officialImageTagRef, parseAmd64Digest, resolveBuildDir } from '../WMMRXU3O.js';
1
+ export { VerifiableBuildWrapper, buildArchiveContractArgs, buildPermissionRepairDockerArgs, buildVerifiableBuildDockerArgs, canonicalizeMetaArgs, copyFileWithPermissionRepair, officialImageTagRef, parseAmd64Digest, parsePackageSpec, resolveBuildDir, resolveRustVersion, runVerifiableBuildFromArchive, wasmArtifactName } from '../D25LP26W.js';
2
2
  import '../VUOMXK5T.js';
3
3
  //# sourceMappingURL=verifiable-build.js.map
4
4
  //# sourceMappingURL=verifiable-build.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,IAAI,QAAO,OAAO,CAAC,IAAI,CA6F9B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,IAAI,QAAO,OAAO,CAAC,IAAI,CA4G9B,CAAC"}
package/dist/index.js CHANGED
@@ -1,24 +1,37 @@
1
1
  import { packageSource } from './LCHYL2IQ.js';
2
- import { VerifiableBuildWrapper } from './WMMRXU3O.js';
2
+ import { runVerifiableBuildFromArchive, parsePackageSpec } from './D25LP26W.js';
3
3
  import { versionCombinations, images, tools } from './AY7HGKNR.js';
4
4
  import { syncToolchain } from './P6KJGYNA.js';
5
5
  import { __name } from './VUOMXK5T.js';
6
+ import path from 'path';
6
7
  import { runCli } from '@layerzerolabs/vm-tooling';
7
8
 
9
+ var DEFAULT_OUTPUT_DIR = ".artifacts";
8
10
  var context = {
9
11
  tools,
10
12
  images,
11
13
  versionCombinations
12
14
  };
13
- var verifiableBuildWrapper = new VerifiableBuildWrapper();
15
+ var collectPackageSpecs = /* @__PURE__ */ __name((value, previous) => [
16
+ ...previous,
17
+ value
18
+ ], "collectPackageSpecs");
14
19
  var main = /* @__PURE__ */ __name(() => runCli(context, (program, parseGlobalOptions) => {
15
20
  program.command("sync-toolchain").description("Pre-download the Rust toolchain specified in rust-toolchain.toml under a lock").action(async () => syncToolchain(context, await parseGlobalOptions(program)));
16
21
  const extra = program.command("extra").description("Extra commands for VM tooling");
17
22
  const stellar = extra.command("stellar");
18
- stellar.command("verifiable-build").description("Reproducible `stellar contract build` of the self-contained source in the cwd by default, inside the official stellar/stellar-cli:<stellar>-rust<rust>-slim-bookworm image pinned by its linux/amd64 digest (run from the host, no Docker socket; embeds the bldimg WASM meta automatically)").requiredOption("--stellar-version <version>", "Stellar CLI version of the official reproducible image (e.g. 25.1.0)").requiredOption("--rust-version <version>", "Rust version of the official reproducible image (e.g. 1.90.0)").option("--source-dir <path>", "Directory to build \u2014 the self-contained/decompressed source. Relative paths resolve against the cwd; defaults to the cwd.").argument("[args...]", "Arguments for `stellar contract build`, after `--` (e.g. -- --package <crate>)").passThroughOptions(true).allowUnknownOption().action(async (args, { stellarVersion, rustVersion, sourceDir }) => verifiableBuildWrapper.run(args, {
19
- stellarVersion,
20
- rustVersion
21
- }, await parseGlobalOptions(program), sourceDir));
23
+ stellar.command("verifiable-build").description("Build one or more Stellar contracts reproducibly from a source archive: extract \u2192 hash \u2192 build each --package in the official stellar/stellar-cli image \u2192 atomically publish contracts-source.zip and *.wasm.").requiredOption("--stellar-version <version>", "Stellar CLI version of the official reproducible image (e.g. 25.1.0)").option("--rust-version <version>", "Rust version of the official reproducible image (e.g. 1.90.0); defaults to the archive's rust-toolchain.toml channel").requiredOption("--archive <path>", "Self-contained source .zip for the SEP-58 verifiable build").option("--package <name:manifest>", "Package to build as <name>:<manifest-path> (repeatable; required at least once)", collectPackageSpecs, []).option("--output-dir <path>", "Directory for contracts-source.zip and *.wasm", DEFAULT_OUTPUT_DIR).action(async ({ stellarVersion, rustVersion, archive, package: packageSpecs, outputDir }) => {
24
+ const options = await parseGlobalOptions(program);
25
+ await runVerifiableBuildFromArchive({
26
+ archive: path.resolve(options.cwd, archive),
27
+ packages: packageSpecs.map(parsePackageSpec),
28
+ outputDir: path.resolve(options.cwd, outputDir),
29
+ stellarVersion,
30
+ rustVersion
31
+ }, {
32
+ cwd: options.cwd
33
+ });
34
+ });
22
35
  stellar.command("package-source").description("Package the self-contained crate in the cwd into a byte-deterministic source .zip under .artifacts/ (for the SEP-58 verifiable build) and print its source_sha256. Include-only: packages source files (.rs/.lock, Cargo.toml, rust-toolchain.toml, rustfmt.toml, clippy.toml) plus any --include entries; --exclude always wins. Skips non-source directories (target, node_modules, \u2026).").option("--output <path>", "Output .zip path (default: <cwd>/.artifacts/<basename>-source.zip)").option("--include <pattern...>", "Native Node glob patterns to include beyond the default source extensions", []).option("--exclude <pattern...>", "Native Node glob patterns to exclude (always wins over the allow-list and --include)", []).action(async ({ output, include, exclude }) => packageSource({
23
36
  output,
24
37
  include,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"names":["context","tools","images","versionCombinations","verifiableBuildWrapper","VerifiableBuildWrapper","main","runCli","program","parseGlobalOptions","command","description","action","syncToolchain","extra","stellar","requiredOption","option","argument","passThroughOptions","allowUnknownOption","args","stellarVersion","rustVersion","sourceDir","run","output","include","exclude","packageSource"],"mappings":";;;;;;;AAQA,IAAMA,OAAAA,GAAiC;AAAEC,EAAAA,KAAAA;AAAOC,EAAAA,MAAAA;AAAQC,EAAAA;AAAoB,CAAA;AAE5E,IAAMC,sBAAAA,GAAyB,IAAIC,sBAAAA,EAAAA;AAE5B,IAAMC,uBAAO,MAAA,CAAA,MAChBC,MAAAA,CAAOP,OAAAA,EAAS,CAACQ,SAASC,kBAAAA,KAAAA;AACtBD,EAAAA,OAAAA,CACKE,OAAAA,CAAQ,gBAAA,CAAA,CACRC,WAAAA,CACG,+EAAA,CAAA,CAEHC,MAAAA,CAAO,YAAYC,aAAAA,CAAcb,OAAAA,EAAS,MAAMS,kBAAAA,CAAmBD,OAAAA,CAAAA,CAAAA,CAAAA;AAIxE,EAAA,MAAMM,QAAQN,OAAAA,CAAQE,OAAAA,CAAQ,OAAA,CAAA,CAASC,YAAY,+BAAA,CAAA;AACnD,EAAA,MAAMI,OAAAA,GAAUD,KAAAA,CAAMJ,OAAAA,CAAQ,SAAA,CAAA;AAE9BK,EAAAA,OAAAA,CACKL,QAAQ,kBAAA,CAAA,CACRC,WAAAA,CACG,8RAGI,EAEPK,cAAAA,CACG,6BAAA,EACA,sEAAA,CAAA,CAEHA,eACG,0BAAA,EACA,+DAAA,CAAA,CAEHC,MAAAA,CACG,uBACA,gIACI,CAAA,CAEPC,QAAAA,CACG,WAAA,EACA,gFAAA,CAAA,CAEHC,kBAAAA,CAAmB,IAAA,CAAA,CACnBC,oBAAkB,CAClBR,MAAAA,CACG,OACIS,IAAAA,EACA,EACIC,cAAAA,EACAC,WAAAA,EACAC,WAAS,KAGbpB,sBAAAA,CAAuBqB,IACnBJ,IAAAA,EACA;AAAEC,IAAAA,cAAAA;AAAgBC,IAAAA;AAAY,GAAA,EAC9B,MAAMd,kBAAAA,CAAmBD,OAAAA,CAAAA,EACzBgB,SAAAA,CAAAA,CAAAA;AAIhBT,EAAAA,OAAAA,CACKL,OAAAA,CAAQ,gBAAA,CAAA,CACRC,WAAAA,CACG,gYAII,CAAA,CAEPM,MAAAA,CACG,iBAAA,EACA,oEAAA,CAAA,CAEHA,MAAAA,CACG,wBAAA,EACA,2EAAA,EACA,EAAE,CAAA,CAELA,MAAAA,CACG,wBAAA,EACA,sFAAA,EACA,EAAE,CAAA,CAELL,MAAAA,CACG,OAAO,EACHc,MAAAA,EACAC,OAAAA,EACAC,OAAAA,OAMAC,aAAAA,CAAc;AAAEH,IAAAA,MAAAA;AAAQC,IAAAA,OAAAA;AAASC,IAAAA;AAAQ,GAAA,EAAG,MAAMnB,kBAAAA,CAAmBD,OAAAA,CAAAA,CAAAA,CAAAA;AAErF,CAAA,CAAA,EA7FgB,MAAA","file":"index.js","sourcesContent":["import type { ChainContext } from '@layerzerolabs/vm-tooling';\nimport { runCli } from '@layerzerolabs/vm-tooling';\n\nimport { packageSource } from './commands/package-source';\nimport { syncToolchain } from './commands/sync-toolchain';\nimport { VerifiableBuildWrapper } from './commands/verifiable-build';\nimport { type ImageId, images, tools, versionCombinations } from './config';\n\nconst context: ChainContext<ImageId> = { tools, images, versionCombinations };\n\nconst verifiableBuildWrapper = new VerifiableBuildWrapper();\n\nexport const main = (): Promise<void> =>\n runCli(context, (program, parseGlobalOptions) => {\n program\n .command('sync-toolchain')\n .description(\n 'Pre-download the Rust toolchain specified in rust-toolchain.toml under a lock',\n )\n .action(async () => syncToolchain(context, await parseGlobalOptions(program)));\n\n // Extra (non-passthrough) commands, namespaced under `extra <tool>` like vm-tooling-sui:\n // lz-tool extra stellar verifiable-build [args...]\n const extra = program.command('extra').description('Extra commands for VM tooling');\n const stellar = extra.command('stellar');\n\n stellar\n .command('verifiable-build')\n .description(\n 'Reproducible `stellar contract build` of the self-contained source in the cwd by ' +\n 'default, inside the official stellar/stellar-cli:<stellar>-rust<rust>-slim-bookworm ' +\n 'image pinned by its linux/amd64 digest (run from the host, no Docker socket; embeds ' +\n 'the bldimg WASM meta automatically)',\n )\n .requiredOption(\n '--stellar-version <version>',\n 'Stellar CLI version of the official reproducible image (e.g. 25.1.0)',\n )\n .requiredOption(\n '--rust-version <version>',\n 'Rust version of the official reproducible image (e.g. 1.90.0)',\n )\n .option(\n '--source-dir <path>',\n 'Directory to build — the self-contained/decompressed source. Relative paths ' +\n 'resolve against the cwd; defaults to the cwd.',\n )\n .argument(\n '[args...]',\n 'Arguments for `stellar contract build`, after `--` (e.g. -- --package <crate>)',\n )\n .passThroughOptions(true)\n .allowUnknownOption()\n .action(\n async (\n args: string[],\n {\n stellarVersion,\n rustVersion,\n sourceDir,\n }: { stellarVersion: string; rustVersion: string; sourceDir?: string },\n ) =>\n verifiableBuildWrapper.run(\n args,\n { stellarVersion, rustVersion },\n await parseGlobalOptions(program),\n sourceDir,\n ),\n );\n\n stellar\n .command('package-source')\n .description(\n 'Package the self-contained crate in the cwd into a byte-deterministic source ' +\n '.zip under .artifacts/ (for the SEP-58 verifiable build) and print its ' +\n 'source_sha256. Include-only: packages source files (.rs/.lock, Cargo.toml, ' +\n 'rust-toolchain.toml, rustfmt.toml, clippy.toml) plus any --include entries; ' +\n '--exclude always wins. Skips non-source directories (target, node_modules, …).',\n )\n .option(\n '--output <path>',\n 'Output .zip path (default: <cwd>/.artifacts/<basename>-source.zip)',\n )\n .option(\n '--include <pattern...>',\n 'Native Node glob patterns to include beyond the default source extensions',\n [],\n )\n .option(\n '--exclude <pattern...>',\n 'Native Node glob patterns to exclude (always wins over the allow-list and --include)',\n [],\n )\n .action(\n async ({\n output,\n include,\n exclude,\n }: {\n output?: string;\n include?: string[];\n exclude?: string[];\n }) =>\n packageSource({ output, include, exclude }, await parseGlobalOptions(program)),\n );\n });\n"]}
1
+ {"version":3,"sources":["../src/index.ts"],"names":["DEFAULT_OUTPUT_DIR","context","tools","images","versionCombinations","collectPackageSpecs","value","previous","main","runCli","program","parseGlobalOptions","command","description","action","syncToolchain","extra","stellar","requiredOption","option","stellarVersion","rustVersion","archive","package","packageSpecs","outputDir","options","runVerifiableBuildFromArchive","path","resolve","cwd","packages","map","parsePackageSpec","output","include","exclude","packageSource"],"mappings":";;;;;;;;AAUA,IAAMA,kBAAAA,GAAqB,YAAA;AAE3B,IAAMC,OAAAA,GAAiC;AAAEC,EAAAA,KAAAA;AAAOC,EAAAA,MAAAA;AAAQC,EAAAA;AAAoB,CAAA;AAE5E,IAAMC,mBAAAA,mBAAsB,MAAA,CAAA,CAACC,KAAAA,EAAeC,QAAAA,KAAiC;AAAIA,EAAAA,GAAAA,QAAAA;AAAUD,EAAAA;AAA/D,CAAA,EAAA,qBAAA,CAAA;AAErB,IAAME,uBAAO,MAAA,CAAA,MAChBC,MAAAA,CAAOR,OAAAA,EAAS,CAACS,SAASC,kBAAAA,KAAAA;AACtBD,EAAAA,OAAAA,CACKE,OAAAA,CAAQ,gBAAA,CAAA,CACRC,WAAAA,CACG,+EAAA,CAAA,CAEHC,MAAAA,CAAO,YAAYC,aAAAA,CAAcd,OAAAA,EAAS,MAAMU,kBAAAA,CAAmBD,OAAAA,CAAAA,CAAAA,CAAAA;AAIxE,EAAA,MAAMM,QAAQN,OAAAA,CAAQE,OAAAA,CAAQ,OAAA,CAAA,CAASC,YAAY,+BAAA,CAAA;AACnD,EAAA,MAAMI,OAAAA,GAAUD,KAAAA,CAAMJ,OAAAA,CAAQ,SAAA,CAAA;AAE9BK,EAAAA,OAAAA,CACKL,QAAQ,kBAAA,CAAA,CACRC,WAAAA,CACG,8NAEI,EAEPK,cAAAA,CACG,6BAAA,EACA,sEAAA,CAAA,CAEHC,OACG,0BAAA,EACA,sHACI,EAEPD,cAAAA,CACG,kBAAA,EACA,4DAAA,CAAA,CAEHC,MAAAA,CACG,2BAAA,EACA,iFAAA,EACAd,qBACA,EAAE,EAELc,MAAAA,CACG,qBAAA,EACA,iDACAnB,kBAAAA,CAAAA,CAEHc,MAAAA,CACG,OAAO,EACHM,cAAAA,EACAC,WAAAA,EACAC,SACAC,OAAAA,EAASC,YAAAA,EACTC,WAAS,KAOZ;AACG,IAAA,MAAMC,OAAAA,GAAU,MAAMf,kBAAAA,CAAmBD,OAAAA,CAAAA;AACzC,IAAA,MAAMiB,6BAAAA,CACF;AACIL,MAAAA,OAAAA,EAASM,IAAAA,CAAKC,OAAAA,CAAQH,OAAAA,CAAQI,GAAAA,EAAKR,OAAAA,CAAAA;MACnCS,QAAAA,EAAUP,YAAAA,CAAaQ,IAAIC,gBAAAA,CAAAA;AAC3BR,MAAAA,SAAAA,EAAWG,IAAAA,CAAKC,OAAAA,CAAQH,OAAAA,CAAQI,GAAAA,EAAKL,SAAAA,CAAAA;AACrCL,MAAAA,cAAAA;AACAC,MAAAA;KACJ,EACA;AAAES,MAAAA,GAAAA,EAAKJ,OAAAA,CAAQI;KAAI,CAAA;EAE3B,CAAA,CAAA;AAGRb,EAAAA,OAAAA,CACKL,OAAAA,CAAQ,gBAAA,CAAA,CACRC,WAAAA,CACG,gYAII,CAAA,CAEPM,MAAAA,CACG,iBAAA,EACA,oEAAA,CAAA,CAEHA,MAAAA,CACG,wBAAA,EACA,2EAAA,EACA,EAAE,CAAA,CAELA,MAAAA,CACG,wBAAA,EACA,sFAAA,EACA,EAAE,CAAA,CAELL,MAAAA,CACG,OAAO,EACHoB,MAAAA,EACAC,OAAAA,EACAC,OAAAA,OAMAC,aAAAA,CAAc;AAAEH,IAAAA,MAAAA;AAAQC,IAAAA,OAAAA;AAASC,IAAAA;AAAQ,GAAA,EAAG,MAAMzB,kBAAAA,CAAmBD,OAAAA,CAAAA,CAAAA,CAAAA;AAErF,CAAA,CAAA,EA5GgB,MAAA","file":"index.js","sourcesContent":["import path from 'node:path';\n\nimport type { ChainContext } from '@layerzerolabs/vm-tooling';\nimport { runCli } from '@layerzerolabs/vm-tooling';\n\nimport { packageSource } from './commands/package-source';\nimport { syncToolchain } from './commands/sync-toolchain';\nimport { parsePackageSpec, runVerifiableBuildFromArchive } from './commands/verifiable-build';\nimport { type ImageId, images, tools, versionCombinations } from './config';\n\nconst DEFAULT_OUTPUT_DIR = '.artifacts';\n\nconst context: ChainContext<ImageId> = { tools, images, versionCombinations };\n\nconst collectPackageSpecs = (value: string, previous: string[]): string[] => [...previous, value];\n\nexport const main = (): Promise<void> =>\n runCli(context, (program, parseGlobalOptions) => {\n program\n .command('sync-toolchain')\n .description(\n 'Pre-download the Rust toolchain specified in rust-toolchain.toml under a lock',\n )\n .action(async () => syncToolchain(context, await parseGlobalOptions(program)));\n\n // Extra (non-passthrough) commands, namespaced under `extra <tool>` like vm-tooling-sui:\n // lz-tool extra stellar verifiable-build [options]\n const extra = program.command('extra').description('Extra commands for VM tooling');\n const stellar = extra.command('stellar');\n\n stellar\n .command('verifiable-build')\n .description(\n 'Build one or more Stellar contracts reproducibly from a source archive: ' +\n 'extract → hash → build each --package in the official stellar/stellar-cli ' +\n 'image → atomically publish contracts-source.zip and *.wasm.',\n )\n .requiredOption(\n '--stellar-version <version>',\n 'Stellar CLI version of the official reproducible image (e.g. 25.1.0)',\n )\n .option(\n '--rust-version <version>',\n 'Rust version of the official reproducible image (e.g. 1.90.0); defaults to ' +\n \"the archive's rust-toolchain.toml channel\",\n )\n .requiredOption(\n '--archive <path>',\n 'Self-contained source .zip for the SEP-58 verifiable build',\n )\n .option(\n '--package <name:manifest>',\n 'Package to build as <name>:<manifest-path> (repeatable; required at least once)',\n collectPackageSpecs,\n [] as string[],\n )\n .option(\n '--output-dir <path>',\n 'Directory for contracts-source.zip and *.wasm',\n DEFAULT_OUTPUT_DIR,\n )\n .action(\n async ({\n stellarVersion,\n rustVersion,\n archive,\n package: packageSpecs,\n outputDir,\n }: {\n stellarVersion: string;\n rustVersion?: string;\n archive: string;\n package: string[];\n outputDir: string;\n }) => {\n const options = await parseGlobalOptions(program);\n await runVerifiableBuildFromArchive(\n {\n archive: path.resolve(options.cwd, archive),\n packages: packageSpecs.map(parsePackageSpec),\n outputDir: path.resolve(options.cwd, outputDir),\n stellarVersion,\n rustVersion,\n },\n { cwd: options.cwd },\n );\n },\n );\n\n stellar\n .command('package-source')\n .description(\n 'Package the self-contained crate in the cwd into a byte-deterministic source ' +\n '.zip under .artifacts/ (for the SEP-58 verifiable build) and print its ' +\n 'source_sha256. Include-only: packages source files (.rs/.lock, Cargo.toml, ' +\n 'rust-toolchain.toml, rustfmt.toml, clippy.toml) plus any --include entries; ' +\n '--exclude always wins. Skips non-source directories (target, node_modules, …).',\n )\n .option(\n '--output <path>',\n 'Output .zip path (default: <cwd>/.artifacts/<basename>-source.zip)',\n )\n .option(\n '--include <pattern...>',\n 'Native Node glob patterns to include beyond the default source extensions',\n [],\n )\n .option(\n '--exclude <pattern...>',\n 'Native Node glob patterns to exclude (always wins over the allow-list and --include)',\n [],\n )\n .action(\n async ({\n output,\n include,\n exclude,\n }: {\n output?: string;\n include?: string[];\n exclude?: string[];\n }) =>\n packageSource({ output, include, exclude }, await parseGlobalOptions(program)),\n );\n });\n"]}
package/package.json CHANGED
@@ -19,19 +19,19 @@
19
19
  "bin/**/*"
20
20
  ],
21
21
  "dependencies": {
22
+ "fflate": "^0.8.3",
22
23
  "toml": "^3.0.0",
23
- "@layerzerolabs/deterministic-zip": "1.2.9",
24
- "@layerzerolabs/vm-tooling": "1.2.9"
24
+ "@layerzerolabs/vm-tooling": "1.2.10",
25
+ "@layerzerolabs/deterministic-zip": "1.2.10"
25
26
  },
26
27
  "devDependencies": {
27
- "fflate": "^0.8.3",
28
28
  "tsup": "^8.4.0",
29
29
  "tsx": "^4.21.0",
30
30
  "typescript": "^5.8.2",
31
31
  "vitest": "^3.2.6",
32
- "@layerzerolabs/tsup-configuration": "1.2.9",
33
- "@layerzerolabs/typescript-configuration": "1.2.9",
34
- "@layerzerolabs/vitest-configuration": "1.2.9"
32
+ "@layerzerolabs/tsup-configuration": "1.2.10",
33
+ "@layerzerolabs/vitest-configuration": "1.2.10",
34
+ "@layerzerolabs/typescript-configuration": "1.2.10"
35
35
  },
36
36
  "publishConfig": {
37
37
  "access": "public",
@@ -45,7 +45,7 @@
45
45
  "onesig-client"
46
46
  ]
47
47
  },
48
- "version": "1.2.9",
48
+ "version": "1.2.10",
49
49
  "scripts": {
50
50
  "build": "tsup",
51
51
  "generate-github-matrix": "tsx src/scripts/generate-github-matrix.ts",
package/dist/WMMRXU3O.js DELETED
@@ -1,151 +0,0 @@
1
- import { __name } from './VUOMXK5T.js';
2
- import { execFile, spawn } from 'child_process';
3
- import { stat, chmod } from 'fs/promises';
4
- import path from 'path';
5
- import { promisify } from 'util';
6
-
7
- var execFileAsync = promisify(execFile);
8
- var SOURCE_MOUNT = "/source";
9
- var VERIFIABLE_BUILD_PLATFORM = "linux/amd64";
10
- var OFFICIAL_IMAGE_REPO = "stellar/stellar-cli";
11
- var officialImageTagRef = /* @__PURE__ */ __name((stellarVersion, rustVersion) => `${OFFICIAL_IMAGE_REPO}:${stellarVersion}-rust${rustVersion}-slim-bookworm`, "officialImageTagRef");
12
- var parseAmd64Digest = /* @__PURE__ */ __name((manifestInspectJson) => {
13
- const { manifests } = JSON.parse(manifestInspectJson);
14
- if (!Array.isArray(manifests)) {
15
- throw new Error("`docker manifest inspect` did not return a multi-arch index (no `manifests` array)");
16
- }
17
- const digest = manifests.find(({ platform }) => platform?.os === "linux" && platform?.architecture === "amd64")?.digest;
18
- if (typeof digest !== "string" || !digest.startsWith("sha256:")) {
19
- throw new Error("No linux/amd64 manifest digest found in `docker manifest inspect` output");
20
- }
21
- return digest;
22
- }, "parseAmd64Digest");
23
- var resolveAmd64Digest = /* @__PURE__ */ __name(async (imageTagRef) => {
24
- try {
25
- const { stdout } = await execFileAsync("docker", [
26
- "manifest",
27
- "inspect",
28
- imageTagRef
29
- ], {
30
- maxBuffer: 16 * 1024 * 1024,
31
- timeout: 3e4
32
- });
33
- return parseAmd64Digest(stdout);
34
- } catch (cause) {
35
- throw new Error(`Failed to resolve the linux/amd64 digest of ${imageTagRef} (\`docker manifest inspect\`)`, {
36
- cause
37
- });
38
- }
39
- }, "resolveAmd64Digest");
40
- var META_FLAG = "--meta";
41
- var metaKey = /* @__PURE__ */ __name((entry) => {
42
- const eq = entry.indexOf("=");
43
- return eq === -1 ? entry : entry.slice(0, eq);
44
- }, "metaKey");
45
- var canonicalizeMetaArgs = /* @__PURE__ */ __name((buildArgs, injectedMeta) => {
46
- const reservedKeys = new Set(injectedMeta.map(metaKey));
47
- const metas = [
48
- ...injectedMeta
49
- ];
50
- const passthrough = [];
51
- const addCallerMeta = /* @__PURE__ */ __name((value) => {
52
- if (!reservedKeys.has(metaKey(value))) metas.push(value);
53
- }, "addCallerMeta");
54
- for (let i = 0; i < buildArgs.length; i++) {
55
- const arg = buildArgs[i];
56
- if (arg === void 0) continue;
57
- if (arg === META_FLAG) {
58
- const value = buildArgs[i + 1];
59
- if (value !== void 0 && !value.startsWith("--")) {
60
- addCallerMeta(value);
61
- i += 1;
62
- }
63
- } else if (arg.startsWith(`${META_FLAG}=`)) {
64
- addCallerMeta(arg.slice(META_FLAG.length + 1));
65
- } else {
66
- passthrough.push(arg);
67
- }
68
- }
69
- metas.sort();
70
- return [
71
- ...passthrough,
72
- ...metas.flatMap((meta) => [
73
- META_FLAG,
74
- meta
75
- ])
76
- ];
77
- }, "canonicalizeMetaArgs");
78
- var buildVerifiableBuildDockerArgs = /* @__PURE__ */ __name(({ imageRef, sourceDir, buildArgs, bldimg }) => [
79
- "run",
80
- "--rm",
81
- "--platform",
82
- VERIFIABLE_BUILD_PLATFORM,
83
- "-v",
84
- `${sourceDir}:${SOURCE_MOUNT}`,
85
- "-w",
86
- SOURCE_MOUNT,
87
- imageRef,
88
- "contract",
89
- "build",
90
- // `bldimg` is injected by us (not the caller): the exact build image, so the WASM records what
91
- // produced it. It joins the caller's --meta flags in the canonical sorted order.
92
- ...canonicalizeMetaArgs(buildArgs, [
93
- `bldimg=${bldimg}`
94
- ])
95
- ], "buildVerifiableBuildDockerArgs");
96
- var resolveBuildDir = /* @__PURE__ */ __name((cwd, sourceDir) => path.resolve(cwd, sourceDir ?? "."), "resolveBuildDir");
97
- var runDocker = /* @__PURE__ */ __name((dockerArgs) => new Promise((resolve, reject) => {
98
- const child = spawn("docker", dockerArgs, {
99
- stdio: "inherit"
100
- });
101
- child.on("error", (error) => reject(new Error("Failed to spawn docker for the verifiable build", {
102
- cause: error
103
- })));
104
- child.on("close", (code, signal) => {
105
- if (code === 0) {
106
- resolve();
107
- } else {
108
- reject(new Error(`Verifiable build failed: docker exited with ${signal ? `signal ${signal}` : `code ${code}`}`));
109
- }
110
- });
111
- }), "runDocker");
112
- var VerifiableBuildWrapper = class {
113
- static {
114
- __name(this, "VerifiableBuildWrapper");
115
- }
116
- async run(args, { stellarVersion, rustVersion }, options, sourceDir) {
117
- const buildDir = resolveBuildDir(options.cwd, sourceDir);
118
- try {
119
- if (!(await stat(buildDir)).isDirectory()) {
120
- throw new Error("not a directory");
121
- }
122
- } catch (cause) {
123
- throw new Error(`Verifiable build source directory is not an existing directory: ${buildDir}`, {
124
- cause
125
- });
126
- }
127
- if (sourceDir !== void 0) {
128
- await chmod(buildDir, 511);
129
- }
130
- const tagRef = officialImageTagRef(stellarVersion, rustVersion);
131
- const digest = await resolveAmd64Digest(tagRef);
132
- const imageRef = `${OFFICIAL_IMAGE_REPO}@${digest}`;
133
- const bldimg = `docker.io/${OFFICIAL_IMAGE_REPO}@${digest}`;
134
- const dockerArgs = buildVerifiableBuildDockerArgs({
135
- imageRef,
136
- sourceDir: buildDir,
137
- buildArgs: args,
138
- bldimg
139
- });
140
- console.info("\u{1F512} Verifiable build (official stellar/stellar-cli image, run from host)");
141
- console.info(` source: ${buildDir}`);
142
- console.info(` image: ${imageRef} (${VERIFIABLE_BUILD_PLATFORM}, from tag ${tagRef})`);
143
- console.info(` bldimg: ${bldimg}`);
144
- console.info(` docker ${dockerArgs.join(" ")}`);
145
- await runDocker(dockerArgs);
146
- }
147
- };
148
-
149
- export { VerifiableBuildWrapper, buildVerifiableBuildDockerArgs, canonicalizeMetaArgs, officialImageTagRef, parseAmd64Digest, resolveBuildDir };
150
- //# sourceMappingURL=WMMRXU3O.js.map
151
- //# sourceMappingURL=WMMRXU3O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/verifiable-build.ts"],"names":["execFileAsync","promisify","execFile","SOURCE_MOUNT","VERIFIABLE_BUILD_PLATFORM","OFFICIAL_IMAGE_REPO","officialImageTagRef","stellarVersion","rustVersion","parseAmd64Digest","manifestInspectJson","manifests","JSON","parse","Array","isArray","Error","digest","find","platform","os","architecture","startsWith","resolveAmd64Digest","imageTagRef","stdout","maxBuffer","timeout","cause","META_FLAG","metaKey","entry","eq","indexOf","slice","canonicalizeMetaArgs","buildArgs","injectedMeta","reservedKeys","Set","map","metas","passthrough","addCallerMeta","value","has","push","i","length","arg","undefined","sort","flatMap","meta","buildVerifiableBuildDockerArgs","imageRef","sourceDir","bldimg","resolveBuildDir","cwd","path","resolve","runDocker","dockerArgs","Promise","reject","child","spawn","stdio","on","error","code","signal","VerifiableBuildWrapper","run","args","options","buildDir","stat","isDirectory","chmod","tagRef","console","info","join"],"mappings":"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","file":"WMMRXU3O.js","sourcesContent":["import { execFile, spawn } from 'node:child_process';\nimport { chmod, stat } from 'node:fs/promises';\nimport path from 'node:path';\nimport { promisify } from 'node:util';\n\nimport type { ToolCommandExecutionOptions } from '@layerzerolabs/vm-tooling';\n\nconst execFileAsync = promisify(execFile);\n\n// The self-contained source is mounted here and built in place. The official image's WORKDIR is\n// already /source; we set it explicitly for clarity.\nconst SOURCE_MOUNT = '/source';\n\n// Canonical reproducible platform. External verifiers reproduce the amd64 artifact, so we always\n// run the amd64 image regardless of the host arch (the daemon emulates it when needed).\nconst VERIFIABLE_BUILD_PLATFORM = 'linux/amd64';\n\nconst OFFICIAL_IMAGE_REPO = 'stellar/stellar-cli';\n\n/**\n * The official reproducible image reference for a (Stellar CLI, Rust) version pair, e.g.\n * `stellar/stellar-cli:25.1.0-rust1.90.0-slim-bookworm`. The caller pins both versions; this is the\n * only image the tool builds against.\n */\nexport const officialImageTagRef = (stellarVersion: string, rustVersion: string): string =>\n `${OFFICIAL_IMAGE_REPO}:${stellarVersion}-rust${rustVersion}-slim-bookworm`;\n\n/**\n * Pick the linux/amd64 manifest digest out of `docker manifest inspect` output. Pure/synchronous so\n * the selection (skip the arm64 and the unknown/unknown attestation entries) is unit-testable.\n */\n// The subset of `docker manifest inspect` output (an OCI image index) that we read.\ninterface ManifestDescriptor {\n digest?: string;\n platform?: { os?: string; architecture?: string };\n}\ninterface ManifestIndex {\n manifests?: ManifestDescriptor[];\n}\n\nexport const parseAmd64Digest = (manifestInspectJson: string): string => {\n const { manifests } = JSON.parse(manifestInspectJson) as ManifestIndex;\n\n if (!Array.isArray(manifests)) {\n throw new Error(\n '`docker manifest inspect` did not return a multi-arch index (no `manifests` array)',\n );\n }\n\n const digest = manifests.find(\n ({ platform }) => platform?.os === 'linux' && platform?.architecture === 'amd64',\n )?.digest;\n\n if (typeof digest !== 'string' || !digest.startsWith('sha256:')) {\n throw new Error('No linux/amd64 manifest digest found in `docker manifest inspect` output');\n }\n\n return digest;\n};\n\n/**\n * Resolve the immutable linux/amd64 digest of a `stellar/stellar-cli` tag via a daemon-less\n * registry query (`docker manifest inspect`). This is the reproducible reference an external\n * verifier pins to (SEP-58).\n */\nconst resolveAmd64Digest = async (imageTagRef: string): Promise<string> => {\n try {\n const { stdout } = await execFileAsync('docker', ['manifest', 'inspect', imageTagRef], {\n maxBuffer: 16 * 1024 * 1024,\n timeout: 30_000,\n });\n return parseAmd64Digest(stdout);\n } catch (cause) {\n throw new Error(\n `Failed to resolve the linux/amd64 digest of ${imageTagRef} (\\`docker manifest inspect\\`)`,\n { cause },\n );\n }\n};\n\nconst META_FLAG = '--meta';\n\n/** The `key` of a `key=value` meta entry (the whole string when there is no `=`). */\nconst metaKey = (entry: string): string => {\n const eq = entry.indexOf('=');\n return eq === -1 ? entry : entry.slice(0, eq);\n};\n\n/**\n * Canonicalize `stellar contract build` args so the embedded metadata order is stable.\n *\n * Soroban stores contract metadata as an ORDERED sequence, so the order of `--meta key=value`\n * flags changes the WASM bytes (verified: swapping two `--meta` flags yields a different WASM\n * hash). To keep the build reproducible regardless of the order the caller passed `--meta`, every\n * meta entry — the caller's plus the tool-injected ones — is pulled out, merged, and re-emitted in\n * sorted order. Non-meta args keep their original relative order and precede the sorted metas.\n *\n * Injected keys (e.g. `bldimg`) are tool-controlled and RESERVED: any caller `--meta` reusing an\n * injected key is dropped, so a caller can never override the recorded build image by key\n * collision (before sorting, the injected entry was always appended last and won on its own).\n *\n * Both `--meta k=v` and `--meta=k=v` forms are recognized; a dangling `--meta` with no value (or\n * one followed by another flag) is dropped.\n */\nexport const canonicalizeMetaArgs = (buildArgs: string[], injectedMeta: string[]): string[] => {\n const reservedKeys = new Set(injectedMeta.map(metaKey));\n const metas = [...injectedMeta];\n const passthrough: string[] = [];\n\n // Keep a caller meta unless it collides with a reserved (injected) key.\n const addCallerMeta = (value: string): void => {\n if (!reservedKeys.has(metaKey(value))) metas.push(value);\n };\n\n for (let i = 0; i < buildArgs.length; i++) {\n const arg = buildArgs[i];\n if (arg === undefined) continue;\n if (arg === META_FLAG) {\n const value = buildArgs[i + 1];\n // A meta value is `key=value`; anything starting with `--` is the next flag, so treat\n // this `--meta` as dangling and drop it.\n if (value !== undefined && !value.startsWith('--')) {\n addCallerMeta(value);\n i += 1;\n }\n } else if (arg.startsWith(`${META_FLAG}=`)) {\n addCallerMeta(arg.slice(META_FLAG.length + 1));\n } else {\n passthrough.push(arg);\n }\n }\n\n metas.sort();\n return [...passthrough, ...metas.flatMap((meta) => [META_FLAG, meta])];\n};\n\n/**\n * Assemble the `docker run` argv for a verifiable build. Kept pure and synchronous so the mount /\n * workdir layout and the tool-injected `--meta bldimg=…` are unit-testable without Docker.\n *\n * The official image's ENTRYPOINT is `stellar`, so the trailing `contract build …` runs under it.\n * The source directory is assumed self-contained, so it is mounted at /source and built in place —\n * no surrounding workspace is required. All `--meta` flags (the caller's plus the injected\n * `bldimg`) are sorted into a canonical order so the WASM hash is independent of `--meta` ordering.\n */\nexport const buildVerifiableBuildDockerArgs = ({\n imageRef,\n sourceDir,\n buildArgs,\n bldimg,\n}: {\n imageRef: string;\n sourceDir: string;\n buildArgs: string[];\n bldimg: string;\n}): string[] => [\n 'run',\n '--rm',\n '--platform',\n VERIFIABLE_BUILD_PLATFORM,\n '-v',\n `${sourceDir}:${SOURCE_MOUNT}`,\n '-w',\n SOURCE_MOUNT,\n imageRef,\n 'contract',\n 'build',\n // `bldimg` is injected by us (not the caller): the exact build image, so the WASM records what\n // produced it. It joins the caller's --meta flags in the canonical sorted order.\n ...canonicalizeMetaArgs(buildArgs, [`bldimg=${bldimg}`]),\n];\n\n/**\n * Resolve the directory to build. An explicit `sourceDir` that is relative resolves against the\n * cwd; an absolute one is used as-is; omitting it falls back to the cwd. Kept pure/synchronous so\n * the cwd-vs-explicit-folder precedence is unit-testable without Docker.\n *\n * This is what lets the pipeline decompress a packaged source archive into a scratch directory and\n * build that, instead of always building the process cwd.\n */\nexport const resolveBuildDir = (cwd: string, sourceDir?: string): string =>\n path.resolve(cwd, sourceDir ?? '.');\n\nconst runDocker = (dockerArgs: string[]): Promise<void> =>\n new Promise((resolve, reject) => {\n const child = spawn('docker', dockerArgs, { stdio: 'inherit' });\n child.on('error', (error) =>\n reject(new Error('Failed to spawn docker for the verifiable build', { cause: error })),\n );\n child.on('close', (code, signal) => {\n if (code === 0) {\n resolve();\n } else {\n reject(\n new Error(\n `Verifiable build failed: docker exited with ${\n signal ? `signal ${signal}` : `code ${code}`\n }`,\n ),\n );\n }\n });\n });\n\nexport interface VerifiableBuildVersions {\n stellarVersion: string;\n rustVersion: string;\n}\n\n/**\n * Reproducible `stellar contract build` that runs inside the OFFICIAL `stellar/stellar-cli` image —\n * the exact package an external verifier uses — instead of our own dev image (whose sccache/mold\n * layers could change the WASM).\n *\n * The build runs the official image directly from the HOST: our TypeScript CLI already executes on\n * the host runner, so it can `docker run` the official image itself. This is what an external\n * verifier's plain `docker run` does, and it means we never bind-mount the host Docker socket into\n * a container — eliminating the container-escape / secret-leak surface that mounting the socket\n * would create.\n *\n * The image is `stellar/stellar-cli:<stellarVersion>-rust<rustVersion>-slim-bookworm`, pinned by the\n * caller. For a stable reference we resolve it to its linux/amd64 digest and both RUN that digest\n * and embed it as the `bldimg` WASM metadata (`docker.io/stellar/stellar-cli@sha256:…`) — the tool\n * does this automatically so callers never hand-inject `--meta bldimg=…`. The source directory (the\n * cwd, assumed self-contained) is mounted at /source and built in place, and the official image runs\n * as its own user/toolchain.\n */\nexport class VerifiableBuildWrapper {\n public async run(\n args: string[],\n { stellarVersion, rustVersion }: VerifiableBuildVersions,\n options: ToolCommandExecutionOptions,\n sourceDir?: string,\n ): Promise<void> {\n const buildDir = resolveBuildDir(options.cwd, sourceDir);\n try {\n if (!(await stat(buildDir)).isDirectory()) {\n throw new Error('not a directory');\n }\n } catch (cause) {\n throw new Error(\n `Verifiable build source directory is not an existing directory: ${buildDir}`,\n { cause },\n );\n }\n\n // The official stellar-cli image runs as a non-host UID and must create cargo target\n // dirs under the bind-mounted source. Do not pass --user (that would diverge from what\n // external verifiers run). Only chmod when --source-dir is explicit (typically a\n // throwaway extract dir); never world-write the process cwd.\n if (sourceDir !== undefined) {\n await chmod(buildDir, 0o777);\n }\n\n const tagRef = officialImageTagRef(stellarVersion, rustVersion);\n const digest = await resolveAmd64Digest(tagRef);\n const imageRef = `${OFFICIAL_IMAGE_REPO}@${digest}`;\n const bldimg = `docker.io/${OFFICIAL_IMAGE_REPO}@${digest}`;\n\n const dockerArgs = buildVerifiableBuildDockerArgs({\n imageRef,\n sourceDir: buildDir,\n buildArgs: args,\n bldimg,\n });\n\n console.info('🔒 Verifiable build (official stellar/stellar-cli image, run from host)');\n console.info(` source: ${buildDir}`);\n console.info(` image: ${imageRef} (${VERIFIABLE_BUILD_PLATFORM}, from tag ${tagRef})`);\n console.info(` bldimg: ${bldimg}`);\n console.info(` docker ${dockerArgs.join(' ')}`);\n\n await runDocker(dockerArgs);\n }\n}\n"]}