@lightprotocol/zk-compression-cli 0.27.1-alpha.1 → 0.27.1-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/accounts/address_merkle_tree_amt1Ayt45jfbdw5YSo7iz6WZxUmnZsQTYXy82hVwyC2.json +1 -1
  2. package/accounts/address_merkle_tree_queue_aq1S9z4reTSQAdgWHGD2zDaS39sjGrAxbR31vxJ2F4F.json +1 -1
  3. package/accounts/batch_address_merkle_tree_EzKE84aVTkCUhDHLELqyJaq1Y7UVVmqxXqZjVHwHY3rK.json +14 -1
  4. package/accounts/{batch_state_merkle_tree_2_2Yb3fGo2E9aWLjY8KuESaqurYpGGhEeJr7eynKrSgXwS.json → batch_address_merkle_tree_amt2kaJA14v3urZbZvnc5v2np8jqvc4Z8zDep5wbtzx.json} +1 -1
  5. package/accounts/{batch_state_merkle_tree_HLKs5NJ8FXkJg8BrzJt56adFYYuwg5etzDtBbQYTsixu.json → batch_state_merkle_tree_bmt1LryLZUMmF7ZtqESaw7wifBXLfXHQYoE4GAmrahU.json} +1 -1
  6. package/accounts/batch_state_merkle_tree_bmt2UxoBxB9xWev4BkLvkGdapsz6sZGkzViPNph7VFi.json +1 -0
  7. package/accounts/batch_state_merkle_tree_bmt3ccLd4bqSVZVeCJnH1F6C8jNygAhaDfxDwePyyGb.json +1 -0
  8. package/accounts/batch_state_merkle_tree_bmt4d3p1a4YQgk9PeZv5s4DBUmbF5NxqYpk9HGjQsd8.json +1 -0
  9. package/accounts/batch_state_merkle_tree_bmt5yU97jC88YXTuSukYHa8Z5Bi2ZDUtmzfkDTA2mG2.json +1 -0
  10. package/accounts/{batched_output_queue_2_12wJT3xYd46rtjeqDU6CrtT8unqLjPiheggzqhN9YsyB.json → batched_output_queue_oq1na8gojfdUhsfCpyjNt6h4JaDWtHf1yQj4koBWfto.json} +1 -1
  11. package/accounts/{batched_output_queue_6L7SzhYB3anwEQ9cphpJ1U7Scwj57bx2xueReg7R9cKU.json → batched_output_queue_oq2UkeMsJLfXt2QHzim242SUi3nvjJs8Pn7Eac9H9vg.json} +1 -1
  12. package/accounts/batched_output_queue_oq3AxjekBWgo64gpauB6QtuZNesuv19xrhaC1ZM1THQ.json +1 -0
  13. package/accounts/batched_output_queue_oq4ypwvVGzCUMoiKKHWh4S1SgZJ9vCvKpcz6RT6A8dq.json +1 -0
  14. package/accounts/batched_output_queue_oq5oh5ZR3yGomuQgFduNDzjtGvVWfDRGLuDVjv9a96P.json +1 -0
  15. package/accounts/compressible_config_pda_ACXg8a7VaqecBWrSbdu73W4Pg9gsqXJ3EXAqkHyhvVXg.json +1 -0
  16. package/accounts/config_counter_pda_8gH9tmziWsS8Wc4fnoN5ax3jsSumNYoRDuSBvmH2GMH8.json +1 -0
  17. package/accounts/{test_batched_cpi_context_7Hp52chxaew8bW1ApR4fck2bh6Y8qA1pu3qwH6N9zaLj.json → cpi_context_cpi15BoVPKgEPw5o8wc2T816GE7b378nMXnhH3Xbq4y.json} +1 -1
  18. package/accounts/cpi_context_cpi1uHzrEhBG733DoEJNgHCyRS3XmmyVNZx5fonubE4.json +1 -1
  19. package/accounts/cpi_context_cpi2cdhkH5roePvcudTgUL8ppEBfTay1desGh8G8QxK.json +1 -1
  20. package/accounts/{cpi_context_batched_2_HwtjxDvFEXiWnzeMeWkMBzpQN45A95rTJNZmz1Z3pe8R.json → cpi_context_cpi2yGapXUR3As5SjnHBAVvmApNiLsbeZpF3euWnW6B.json} +1 -14
  21. package/accounts/cpi_context_cpi3mbwMpSX8FAGMZVP85AwxqCaQMfEk9Em1v8QK9Rf.json +1 -0
  22. package/accounts/cpi_context_cpi4yyPDc4bCgHAnsenunGA8Y77j3XEDyjgfyCKgcoc.json +1 -0
  23. package/accounts/cpi_context_cpi5ZTjdgYpZ1Xr7B1cMLLUE81oTtJbNNAyKary2nV6.json +1 -0
  24. package/accounts/epoch_pda_34w7KcLBXabMkHuXE2fY368vFe6kP3v5EJn8nPvQ8SKn.json +1 -1
  25. package/accounts/forester_epoch_pda_3FBt1BPQHCQkS8k3wrUXMfB6JBhtMhEqQXueHRw2ojZV.json +1 -1
  26. package/accounts/governance_authority_pda_CuEtcKkkbTn6qy2qxqDswq5U2ADsqoipYDAYfRvxPjcp.json +1 -1
  27. package/accounts/group_pda_24rt4RgeyjUCWGS2eF7L7gyNMuz6JWdqYpAvb1KRoHxs.json +1 -1
  28. package/accounts/merkle_tree_pubkey_smt1NamzXdq4AMqS2fS2F1i5KTYPZRhoHgWx38d8WsT.json +1 -1
  29. package/accounts/merkle_tree_pubkey_smt2rJAFdyJJupwMKAqTNAJwvjhmiZ4JYGZmbVRw1Ho.json +1 -1
  30. package/accounts/nullifier_queue_pubkey_nfq1NvQDJ2GEgnS8zt9prAe8rjjpAW1zFkrvZoBR148.json +1 -1
  31. package/accounts/nullifier_queue_pubkey_nfq2hgS7NYemXsFaFUCe3EMXSDSfnZnAe27jC6aPP1X.json +1 -1
  32. package/accounts/registered_forester_pda_2KNqEh23Se8AHecuzR1UkxL26euq2qXSpQPTH1jH7VqU.json +1 -1
  33. package/accounts/rent_sponsor_pda_r18WwUxfG8kQ69bQPAB2jV6zGNKy3GosFGctjQoV4ti.json +1 -0
  34. package/bin/account_compression.so +0 -0
  35. package/bin/light_compressed_token.so +0 -0
  36. package/bin/light_registry.so +0 -0
  37. package/bin/light_system_program_pinocchio.so +0 -0
  38. package/dist/commands/approve-and-mint-to/index.js +26 -29
  39. package/dist/commands/balance/index.js +12 -11
  40. package/dist/commands/compress-sol/index.js +13 -13
  41. package/dist/commands/compress-spl/index.js +19 -19
  42. package/dist/commands/config/config.js +67 -33
  43. package/dist/commands/create-mint/index.js +19 -20
  44. package/dist/commands/create-token-pool/index.js +9 -9
  45. package/dist/commands/decompress-sol/index.js +13 -13
  46. package/dist/commands/decompress-spl/index.js +19 -19
  47. package/dist/commands/init/index.js +8 -8
  48. package/dist/commands/merge-token-accounts/index.js +13 -14
  49. package/dist/commands/mint-to/index.js +24 -25
  50. package/dist/commands/start-prover/index.d.ts +0 -3
  51. package/dist/commands/start-prover/index.js +13 -58
  52. package/dist/commands/test-validator/index.d.ts +4 -2
  53. package/dist/commands/test-validator/index.js +107 -109
  54. package/dist/commands/token-balance/index.js +15 -15
  55. package/dist/commands/transfer/index.js +23 -24
  56. package/dist/psp-utils/download.js +1 -1
  57. package/dist/utils/constants.d.ts +2 -2
  58. package/dist/utils/constants.js +2 -3
  59. package/dist/utils/downloadProverBinary.d.ts +7 -0
  60. package/dist/utils/downloadProverBinary.js +108 -0
  61. package/dist/utils/initTestEnv.d.ts +12 -5
  62. package/dist/utils/initTestEnv.js +84 -15
  63. package/dist/utils/process.js +8 -6
  64. package/dist/utils/processPhotonIndexer.js +3 -3
  65. package/dist/utils/processProverServer.d.ts +1 -2
  66. package/dist/utils/processProverServer.js +70 -86
  67. package/dist/utils/utils.d.ts +4 -0
  68. package/dist/utils/utils.js +44 -3
  69. package/oclif.manifest.json +226 -274
  70. package/package.json +61 -63
  71. package/test_bin/dev +4 -7
  72. package/test_bin/run +2 -2
  73. package/bin/forester +0 -0
  74. package/bin/forester.toml +0 -15
  75. package/bin/light_system_program.so +0 -0
  76. package/bin/prover-darwin-arm64 +0 -0
  77. package/bin/prover-darwin-x64 +0 -0
  78. package/bin/prover-linux-arm64 +0 -0
  79. package/bin/prover-linux-x64 +0 -0
  80. package/bin/proving-keys/combined_26_1_1.key +0 -0
  81. package/bin/proving-keys/combined_26_1_2.key +0 -0
  82. package/bin/proving-keys/combined_26_2_1.key +0 -0
  83. package/bin/proving-keys/combined_32_40_1_1.key +0 -0
  84. package/bin/proving-keys/combined_32_40_1_2.key +0 -0
  85. package/bin/proving-keys/combined_32_40_2_1.key +0 -0
  86. package/bin/proving-keys/inclusion_32_1.key +0 -0
  87. package/bin/proving-keys/inclusion_32_2.key +0 -0
  88. package/bin/proving-keys/inclusion_32_3.key +0 -0
  89. package/bin/proving-keys/inclusion_32_4.key +0 -0
  90. package/bin/proving-keys/mainnet_inclusion_26_1.key +0 -0
  91. package/bin/proving-keys/mainnet_inclusion_26_2.key +0 -0
  92. package/bin/proving-keys/mainnet_inclusion_26_3.key +0 -0
  93. package/bin/proving-keys/mainnet_inclusion_26_4.key +0 -0
  94. package/bin/proving-keys/non-inclusion_26_1.key +0 -0
  95. package/bin/proving-keys/non-inclusion_26_2.key +0 -0
  96. package/bin/proving-keys/non-inclusion_40_1.key +0 -0
  97. package/bin/proving-keys/non-inclusion_40_2.key +0 -0
  98. package/bin/proving-keys/non-inclusion_40_3.key +0 -0
  99. package/bin/proving-keys/non-inclusion_40_4.key +0 -0
  100. package/test_bin/lut.json +0 -1
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadProverBinary = downloadProverBinary;
4
+ exports.getProverVersion = getProverVersion;
5
+ const tslib_1 = require("tslib");
6
+ const fs_1 = tslib_1.__importDefault(require("fs"));
7
+ const path_1 = tslib_1.__importDefault(require("path"));
8
+ const https_1 = tslib_1.__importDefault(require("https"));
9
+ const http_1 = tslib_1.__importDefault(require("http"));
10
+ const promises_1 = require("stream/promises");
11
+ const PROVER_RELEASE_TAG = "2.0.6";
12
+ const PROVER_BINARY_VERSION = "2.0.0"; // Version string the binary actually reports
13
+ const GITHUB_RELEASES_BASE_URL = `https://github.com/Lightprotocol/light-protocol/releases/download/light-prover-v${PROVER_RELEASE_TAG}`;
14
+ const MAX_REDIRECTS = 10;
15
+ async function downloadProverBinary(binaryPath, binaryName, options = {}) {
16
+ const { maxRetries = 3, retryDelay = 2000 } = options;
17
+ const url = `${GITHUB_RELEASES_BASE_URL}/${binaryName}`;
18
+ console.log(`\nDownloading prover binary: ${binaryName}`);
19
+ console.log(` From: ${url}`);
20
+ console.log(` To: ${binaryPath}\n`);
21
+ const dir = path_1.default.dirname(binaryPath);
22
+ if (!fs_1.default.existsSync(dir)) {
23
+ fs_1.default.mkdirSync(dir, { recursive: true });
24
+ }
25
+ let lastError = null;
26
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
27
+ try {
28
+ await downloadFile(url, binaryPath);
29
+ if (process.platform !== "win32") {
30
+ fs_1.default.chmodSync(binaryPath, 0o755);
31
+ }
32
+ console.log("\nProver binary downloaded.\n");
33
+ return;
34
+ }
35
+ catch (error) {
36
+ lastError = error;
37
+ console.error(`\nDownload attempt ${attempt}/${maxRetries} failed: ${lastError.message}`);
38
+ if (attempt < maxRetries) {
39
+ console.log(` Retrying in ${retryDelay / 1000}s...\n`);
40
+ await new Promise((resolve) => setTimeout(resolve, retryDelay));
41
+ }
42
+ }
43
+ }
44
+ throw new Error(`Failed to download prover binary after ${maxRetries} attempts: ${lastError?.message}`);
45
+ }
46
+ async function downloadFile(url, outputPath, redirectDepth = 0) {
47
+ return new Promise((resolve, reject) => {
48
+ const protocol = url.startsWith("https") ? https_1.default : http_1.default;
49
+ const request = protocol.get(url, (response) => {
50
+ if (response.statusCode === 301 ||
51
+ response.statusCode === 302 ||
52
+ response.statusCode === 307 ||
53
+ response.statusCode === 308) {
54
+ const redirectUrl = response.headers.location;
55
+ if (!redirectUrl) {
56
+ return reject(new Error("Redirect without location header"));
57
+ }
58
+ if (redirectDepth >= MAX_REDIRECTS) {
59
+ return reject(new Error(`Too many redirects: exceeded maximum of ${MAX_REDIRECTS} redirects`));
60
+ }
61
+ return downloadFile(redirectUrl, outputPath, redirectDepth + 1).then(resolve, reject);
62
+ }
63
+ if (response.statusCode !== 200) {
64
+ return reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
65
+ }
66
+ const totalBytes = parseInt(response.headers["content-length"] || "0", 10);
67
+ let downloadedBytes = 0;
68
+ let lastProgress = 0;
69
+ const fileStream = fs_1.default.createWriteStream(outputPath);
70
+ response.on("data", (chunk) => {
71
+ downloadedBytes += chunk.length;
72
+ if (totalBytes > 0) {
73
+ const progress = Math.floor((downloadedBytes / totalBytes) * 100);
74
+ if (progress >= lastProgress + 5) {
75
+ lastProgress = progress;
76
+ const mb = (downloadedBytes / 1024 / 1024).toFixed(1);
77
+ const totalMb = (totalBytes / 1024 / 1024).toFixed(1);
78
+ process.stdout.write(`\r Progress: ${progress}% (${mb}MB / ${totalMb}MB)`);
79
+ }
80
+ }
81
+ });
82
+ (0, promises_1.pipeline)(response, fileStream)
83
+ .then(() => {
84
+ if (totalBytes > 0) {
85
+ process.stdout.write("\r Progress: 100% - Download complete\n");
86
+ }
87
+ resolve();
88
+ })
89
+ .catch((error) => {
90
+ fs_1.default.unlinkSync(outputPath);
91
+ reject(error);
92
+ });
93
+ });
94
+ request.on("error", (error) => {
95
+ if (fs_1.default.existsSync(outputPath)) {
96
+ fs_1.default.unlinkSync(outputPath);
97
+ }
98
+ reject(error);
99
+ });
100
+ request.setTimeout(60000, () => {
101
+ request.destroy();
102
+ reject(new Error("Download timeout"));
103
+ });
104
+ });
105
+ }
106
+ function getProverVersion() {
107
+ return PROVER_BINARY_VERSION;
108
+ }
@@ -9,7 +9,7 @@ export declare function stopTestEnv(options: {
9
9
  indexer: boolean;
10
10
  prover: boolean;
11
11
  }): Promise<void>;
12
- export declare function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer, prover, rpcPort, indexerPort, proverPort, gossipHost, checkPhotonVersion, photonDatabaseUrl, limitLedgerSize, proverRunMode, circuits, geyserConfig, validatorArgs, }: {
12
+ export declare function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer, prover, rpcPort, indexerPort, proverPort, gossipHost, checkPhotonVersion, photonDatabaseUrl, limitLedgerSize, geyserConfig, validatorArgs, cloneNetwork, verbose, skipReset, }: {
13
13
  additionalPrograms?: {
14
14
  address: string;
15
15
  path: string;
@@ -24,10 +24,11 @@ export declare function initTestEnv({ additionalPrograms, skipSystemAccounts, in
24
24
  checkPhotonVersion?: boolean;
25
25
  photonDatabaseUrl?: string;
26
26
  limitLedgerSize?: number;
27
- proverRunMode?: "local-rpc" | "inclusion" | "non-inclusion" | "forester" | "forester-test" | "rpc" | "full" | "full-test";
28
- circuits?: string[];
29
27
  validatorArgs?: string;
30
28
  geyserConfig?: string;
29
+ cloneNetwork?: "devnet" | "mainnet";
30
+ verbose?: boolean;
31
+ skipReset?: boolean;
31
32
  }): Promise<void>;
32
33
  export declare function initTestEnvIfNeeded({ additionalPrograms, skipSystemAccounts, indexer, prover, geyserConfig, validatorArgs, }?: {
33
34
  additionalPrograms?: {
@@ -42,7 +43,7 @@ export declare function initTestEnvIfNeeded({ additionalPrograms, skipSystemAcco
42
43
  }): Promise<void>;
43
44
  export declare function programsDirPath(): string;
44
45
  export declare function programFilePath(programName: string): string;
45
- export declare function getSolanaArgs({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, downloadBinaries, }: {
46
+ export declare function getSolanaArgs({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, downloadBinaries, cloneNetwork, verbose, skipReset, }: {
46
47
  additionalPrograms?: {
47
48
  address: string;
48
49
  path: string;
@@ -52,8 +53,11 @@ export declare function getSolanaArgs({ additionalPrograms, skipSystemAccounts,
52
53
  rpcPort?: number;
53
54
  gossipHost?: string;
54
55
  downloadBinaries?: boolean;
56
+ cloneNetwork?: "devnet" | "mainnet";
57
+ verbose?: boolean;
58
+ skipReset?: boolean;
55
59
  }): Promise<Array<string>>;
56
- export declare function startTestValidator({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, validatorArgs, geyserConfig, }: {
60
+ export declare function startTestValidator({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, validatorArgs, geyserConfig, cloneNetwork, verbose, skipReset, }: {
57
61
  additionalPrograms?: {
58
62
  address: string;
59
63
  path: string;
@@ -64,6 +68,9 @@ export declare function startTestValidator({ additionalPrograms, skipSystemAccou
64
68
  gossipHost?: string;
65
69
  validatorArgs?: string;
66
70
  geyserConfig?: string;
71
+ cloneNetwork?: "devnet" | "mainnet";
72
+ verbose?: boolean;
73
+ skipReset?: boolean;
67
74
  }): Promise<void>;
68
75
  export declare function killTestValidator(): Promise<void>;
69
76
  export {};
@@ -17,6 +17,7 @@ const psp_utils_1 = require("../psp-utils");
17
17
  const process_1 = require("./process");
18
18
  const processProverServer_1 = require("./processProverServer");
19
19
  const processPhotonIndexer_1 = require("./processPhotonIndexer");
20
+ const web3_js_1 = require("@solana/web3.js");
20
21
  exports.SYSTEM_PROGRAMS = [
21
22
  {
22
23
  id: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV",
@@ -44,6 +45,38 @@ exports.SYSTEM_PROGRAMS = [
44
45
  tag: constants_1.LIGHT_REGISTRY_TAG,
45
46
  },
46
47
  ];
48
+ // Programs to clone from devnet/mainnet (the three core Light programs)
49
+ const PROGRAMS_TO_CLONE = [
50
+ "Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX", // Light Registry
51
+ "SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7", // Light System Program
52
+ "compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq", // Account Compression
53
+ ];
54
+ // Known Light Registry accounts to clone (excludes forester/epoch accounts)
55
+ // These are the core config accounts needed for protocol operation
56
+ const REGISTRY_ACCOUNTS_TO_CLONE = [
57
+ "CuEtcKkkbTn6qy2qxqDswq5U2ADsqoipYDAYfRvxPjcp", // governance_authority_pda (ProtocolConfigPda)
58
+ "8gH9tmziWsS8Wc4fnoN5ax3jsSumNYoRDuSBvmH2GMH8", // config_counter_pda
59
+ "35hkDgaAKwMCaxRz2ocSZ6NaUrtKkyNqU6c4RV3tYJRh", // registered_program_pda
60
+ "DumMsyvkaGJG4QnQ1BhTgvoRMXsgGxfpKDUCr22Xqu4w", // registered_registry_program_pda
61
+ "24rt4RgeyjUCWGS2eF7L7gyNMuz6JWdqYpAvb1KRoHxs", // group_pda
62
+ ];
63
+ /**
64
+ * Fetches account public keys owned by a program from a given cluster.
65
+ * For Light Registry, returns known config accounts (skips forester/epoch accounts).
66
+ */
67
+ async function getProgramOwnedAccounts(programId, rpcUrl) {
68
+ const isRegistry = programId === "Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX";
69
+ if (isRegistry) {
70
+ // Return known registry accounts instead of fetching all (too slow due to 88k+ forester accounts)
71
+ return REGISTRY_ACCOUNTS_TO_CLONE;
72
+ }
73
+ else {
74
+ // For other programs, fetch all accounts
75
+ const connection = new web3_js_1.Connection(rpcUrl);
76
+ const accounts = await connection.getProgramAccounts(new web3_js_1.PublicKey(programId), { dataSlice: { offset: 0, length: 0 } });
77
+ return accounts.map((acc) => acc.pubkey.toBase58());
78
+ }
79
+ }
47
80
  async function stopTestEnv(options) {
48
81
  const processesToKill = [
49
82
  { name: "photon", condition: options.indexer, killFunction: processPhotonIndexer_1.killIndexer },
@@ -70,7 +103,7 @@ async function stopTestEnv(options) {
70
103
  await Promise.all(killPromises);
71
104
  console.log("All specified processes and validator stopped.");
72
105
  }
73
- async function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer = true, prover = true, rpcPort = 8899, indexerPort = 8784, proverPort = 3001, gossipHost = "127.0.0.1", checkPhotonVersion = true, photonDatabaseUrl, limitLedgerSize, proverRunMode, circuits, geyserConfig, validatorArgs, }) {
106
+ async function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer = true, prover = true, rpcPort = 8899, indexerPort = 8784, proverPort = 3001, gossipHost = "127.0.0.1", checkPhotonVersion = true, photonDatabaseUrl, limitLedgerSize, geyserConfig, validatorArgs, cloneNetwork, verbose, skipReset, }) {
74
107
  // We cannot await this promise directly because it will hang the process
75
108
  startTestValidator({
76
109
  additionalPrograms,
@@ -80,6 +113,9 @@ async function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer = t
80
113
  gossipHost,
81
114
  validatorArgs,
82
115
  geyserConfig,
116
+ cloneNetwork,
117
+ verbose,
118
+ skipReset,
83
119
  });
84
120
  await (0, process_1.waitForServers)([{ port: rpcPort, path: "/health" }]);
85
121
  await (0, process_1.confirmServerStability)(`http://127.0.0.1:${rpcPort}/health`);
@@ -95,7 +131,7 @@ async function initTestEnv({ additionalPrograms, skipSystemAccounts, indexer = t
95
131
  (0, utils_1.setConfig)(config);
96
132
  try {
97
133
  // TODO: check if using redisUrl is better here.
98
- await (0, processProverServer_1.startProver)(proverPort, proverRunMode, circuits);
134
+ await (0, processProverServer_1.startProver)(proverPort);
99
135
  }
100
136
  catch (error) {
101
137
  console.error("Failed to start prover:", error);
@@ -154,26 +190,31 @@ function programFilePath(programName) {
154
190
  }
155
191
  return path_1.default.resolve(__dirname, path_1.default.join(constants_1.BASE_PATH, programName));
156
192
  }
157
- async function getSolanaArgs({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, downloadBinaries = true, }) {
158
- // TODO: adjust program tags
159
- const programs = [...exports.SYSTEM_PROGRAMS];
160
- if (additionalPrograms)
161
- additionalPrograms.forEach((program) => {
162
- programs.push({ id: program.address, path: program.path });
163
- });
193
+ async function getSolanaArgs({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, downloadBinaries = true, cloneNetwork, verbose = false, skipReset = false, }) {
164
194
  const dirPath = programsDirPath();
165
195
  const solanaArgs = [
166
- "--reset",
167
196
  `--limit-ledger-size=${limitLedgerSize}`,
168
197
  `--rpc-port=${rpcPort}`,
169
198
  `--gossip-host=${gossipHost}`,
170
199
  "--quiet",
171
200
  ];
172
- for (const program of programs) {
173
- if (program.path) {
174
- solanaArgs.push("--bpf-program", program.id, program.path);
201
+ if (!skipReset) {
202
+ solanaArgs.unshift("--reset");
203
+ }
204
+ // Add cluster URL if cloning from a network
205
+ if (cloneNetwork) {
206
+ const clusterUrl = cloneNetwork === "devnet" ? "devnet" : "mainnet-beta";
207
+ solanaArgs.push("--url", clusterUrl);
208
+ }
209
+ // Process system programs
210
+ for (const program of exports.SYSTEM_PROGRAMS) {
211
+ const shouldClone = cloneNetwork && PROGRAMS_TO_CLONE.includes(program.id);
212
+ if (shouldClone) {
213
+ // Clone program from network
214
+ solanaArgs.push("--clone-upgradeable-program", program.id);
175
215
  }
176
216
  else {
217
+ // Load program from local binary
177
218
  const localFilePath = programFilePath(program.name);
178
219
  if (program.name === "spl_noop.so" || downloadBinaries) {
179
220
  await (0, psp_utils_1.downloadBinIfNotExists)({
@@ -188,14 +229,39 @@ async function getSolanaArgs({ additionalPrograms, skipSystemAccounts, limitLedg
188
229
  solanaArgs.push("--bpf-program", program.id, localFilePath);
189
230
  }
190
231
  }
191
- if (!skipSystemAccounts) {
232
+ // Clone all accounts owned by the programs being cloned
233
+ if (cloneNetwork) {
234
+ const rpcUrl = cloneNetwork === "devnet"
235
+ ? "https://api.devnet.solana.com"
236
+ : "https://api.mainnet-beta.solana.com";
237
+ for (const programId of PROGRAMS_TO_CLONE) {
238
+ if (verbose) {
239
+ console.log(`Fetching accounts owned by ${programId}...`);
240
+ }
241
+ const accounts = await getProgramOwnedAccounts(programId, rpcUrl);
242
+ if (verbose) {
243
+ console.log(`Found ${accounts.length} accounts`);
244
+ }
245
+ for (const account of accounts) {
246
+ solanaArgs.push("--maybe-clone", account);
247
+ }
248
+ }
249
+ }
250
+ // Add additional user-provided programs (always loaded locally)
251
+ if (additionalPrograms) {
252
+ for (const program of additionalPrograms) {
253
+ solanaArgs.push("--bpf-program", program.address, program.path);
254
+ }
255
+ }
256
+ // Load local system accounts only if not cloning from network
257
+ if (!skipSystemAccounts && !cloneNetwork) {
192
258
  const accountsRelPath = "../../accounts";
193
259
  const accountsPath = path_1.default.resolve(__dirname, accountsRelPath);
194
260
  solanaArgs.push("--account-dir", accountsPath);
195
261
  }
196
262
  return solanaArgs;
197
263
  }
198
- async function startTestValidator({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, validatorArgs, geyserConfig, }) {
264
+ async function startTestValidator({ additionalPrograms, skipSystemAccounts, limitLedgerSize, rpcPort, gossipHost, validatorArgs, geyserConfig, cloneNetwork, verbose, skipReset, }) {
199
265
  const command = "solana-test-validator";
200
266
  const solanaArgs = await getSolanaArgs({
201
267
  additionalPrograms,
@@ -203,6 +269,9 @@ async function startTestValidator({ additionalPrograms, skipSystemAccounts, limi
203
269
  limitLedgerSize,
204
270
  rpcPort,
205
271
  gossipHost,
272
+ cloneNetwork,
273
+ verbose,
274
+ skipReset,
206
275
  });
207
276
  await killTestValidator();
208
277
  await new Promise((r) => setTimeout(r, 1000));
@@ -16,14 +16,14 @@ const find_process_1 = tslib_1.__importDefault(require("find-process"));
16
16
  const node_child_process_1 = require("node:child_process");
17
17
  const util_1 = require("util");
18
18
  const axios_1 = tslib_1.__importDefault(require("axios"));
19
- const waitOn = require("wait-on");
19
+ const wait_on_1 = tslib_1.__importDefault(require("wait-on"));
20
20
  const readdir = (0, util_1.promisify)(fs_1.default.readdir);
21
21
  const readFile = (0, util_1.promisify)(fs_1.default.readFile);
22
22
  /**
23
23
  * Logs the contents of prover log files in test-ledger dir.
24
24
  */
25
25
  async function logProverFileContents() {
26
- const testLedgerDir = path_1.default.join(__dirname, "../..", "test-ledger");
26
+ const testLedgerDir = path_1.default.join(process.cwd(), "test-ledger");
27
27
  try {
28
28
  if (!fs_1.default.existsSync(testLedgerDir)) {
29
29
  console.log("test-ledger directory does not exist");
@@ -167,9 +167,7 @@ async function execute(command) {
167
167
  function spawnBinary(command, args = []) {
168
168
  const logDir = "test-ledger";
169
169
  const binaryName = path_1.default.basename(command);
170
- console.log("command", command);
171
- console.log("args", args);
172
- const dir = path_1.default.join(__dirname, "../..", logDir);
170
+ const dir = path_1.default.join(process.cwd(), logDir);
173
171
  try {
174
172
  if (!fs_1.default.existsSync(dir)) {
175
173
  fs_1.default.mkdirSync(dir, { recursive: true });
@@ -181,6 +179,10 @@ function spawnBinary(command, args = []) {
181
179
  stdio: ["ignore", out, err],
182
180
  shell: false,
183
181
  detached: true,
182
+ env: {
183
+ ...process.env,
184
+ RUST_LOG: process.env.RUST_LOG || "debug",
185
+ },
184
186
  });
185
187
  spawnedProcess.on("close", async (code) => {
186
188
  console.log(`${binaryName} process exited with code ${code}`);
@@ -213,7 +215,7 @@ async function waitForServers(servers) {
213
215
  },
214
216
  };
215
217
  try {
216
- await waitOn(opts);
218
+ await (0, wait_on_1.default)(opts);
217
219
  servers.forEach((server) => {
218
220
  console.log(`${server.port} is up!`);
219
221
  });
@@ -23,13 +23,13 @@ async function isExpectedPhotonVersion(requiredVersion) {
23
23
  }
24
24
  function getPhotonInstallMessage() {
25
25
  if (constants_1.USE_PHOTON_FROM_GIT && constants_1.PHOTON_GIT_COMMIT) {
26
- return `\nLatest Photon indexer not found. Please install it by running: "cargo install --git ${constants_1.PHOTON_GIT_REPO} --rev ${constants_1.PHOTON_GIT_COMMIT} --locked"`;
26
+ return `\nPhoton indexer ${constants_1.PHOTON_VERSION} (commit ${constants_1.PHOTON_GIT_COMMIT}) not found. Please install it by running: "cargo install --git ${constants_1.PHOTON_GIT_REPO} --rev ${constants_1.PHOTON_GIT_COMMIT} --locked --force"`;
27
27
  }
28
28
  else if (constants_1.USE_PHOTON_FROM_GIT) {
29
- return `\nLatest Photon indexer not found. Please install it by running: "cargo install --git ${constants_1.PHOTON_GIT_REPO} --locked"`;
29
+ return `\nPhoton indexer ${constants_1.PHOTON_VERSION} not found. Please install it by running: "cargo install --git ${constants_1.PHOTON_GIT_REPO} --locked --force"`;
30
30
  }
31
31
  else {
32
- return `\nLatest Photon indexer not found. Please install it by running: "cargo install photon-indexer --version ${constants_1.PHOTON_VERSION} --locked"`;
32
+ return `\nPhoton indexer ${constants_1.PHOTON_VERSION} not found. Please install it by running: "cargo install photon-indexer --version ${constants_1.PHOTON_VERSION} --locked --force"`;
33
33
  }
34
34
  }
35
35
  async function startIndexer(rpcUrl, indexerPort, checkPhotonVersion = true, photonDatabaseUrl) {
@@ -1,6 +1,5 @@
1
1
  export declare function killProver(): Promise<void>;
2
- export declare function isProverRunningWithFlags(runMode?: string, circuits?: string[], proverPort?: number, redisUrl?: string): Promise<boolean>;
3
- export declare function startProver(proverPort: number, runMode: string | undefined, circuits?: string[] | undefined, force?: boolean, redisUrl?: string): Promise<void>;
2
+ export declare function startProver(proverPort: number, redisUrl?: string): Promise<void>;
4
3
  export declare function getProverNameByArch(): string;
5
4
  export declare function getProverPathByArch(): string;
6
5
  export declare function healthCheck(port: number, retries?: number, timeout?: number): Promise<boolean>;
@@ -1,103 +1,84 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.killProver = killProver;
4
- exports.isProverRunningWithFlags = isProverRunningWithFlags;
5
4
  exports.startProver = startProver;
6
5
  exports.getProverNameByArch = getProverNameByArch;
7
6
  exports.getProverPathByArch = getProverPathByArch;
8
7
  exports.healthCheck = healthCheck;
9
8
  const tslib_1 = require("tslib");
10
9
  const path_1 = tslib_1.__importDefault(require("path"));
10
+ const os_1 = tslib_1.__importDefault(require("os"));
11
+ const fs_1 = tslib_1.__importDefault(require("fs"));
12
+ const child_process_1 = require("child_process");
11
13
  const process_1 = require("./process");
12
14
  const constants_1 = require("./constants");
13
- const find_process_1 = tslib_1.__importDefault(require("find-process"));
14
- const KEYS_DIR = "proving-keys/";
15
+ const downloadProverBinary_1 = require("./downloadProverBinary");
16
+ const LIGHT_CONFIG_DIR = path_1.default.join(os_1.default.homedir(), ".config", "light");
17
+ const PROVER_BIN_DIR = path_1.default.join(LIGHT_CONFIG_DIR, "bin");
18
+ const KEYS_DIR = path_1.default.join(LIGHT_CONFIG_DIR, "proving-keys");
15
19
  async function killProver() {
16
20
  await (0, process_1.killProcess)(getProverNameByArch());
17
21
  await (0, process_1.killProcess)(constants_1.LIGHT_PROVER_PROCESS_NAME);
18
22
  }
19
- async function isProverRunningWithFlags(runMode, circuits, proverPort, redisUrl) {
20
- // Use find-process to get prover processes by name pattern
21
- const proverProcesses = await (0, find_process_1.default)("name", "prover-");
22
- const expectedArgs = [];
23
- if (runMode) {
24
- expectedArgs.push("--run-mode", runMode);
23
+ /**
24
+ * Gets the version of the installed prover binary
25
+ * Returns null if the binary doesn't exist or version command fails
26
+ */
27
+ function getInstalledProverVersion() {
28
+ const binaryPath = getProverPathByArch();
29
+ if (!fs_1.default.existsSync(binaryPath)) {
30
+ return null;
31
+ }
32
+ try {
33
+ const output = (0, child_process_1.execSync)(`"${binaryPath}" version`, {
34
+ encoding: "utf-8",
35
+ timeout: 5000,
36
+ }).trim();
37
+ // Extract version number (handles "v2.0.6", "light-prover v2.0.6", "2.0.6", etc.)
38
+ const match = output.match(/(\d+\.\d+\.\d+)/);
39
+ return match ? match[1] : null;
40
+ }
41
+ catch (error) {
42
+ return null;
25
43
  }
26
- if (Array.isArray(circuits)) {
27
- for (const c of circuits) {
28
- expectedArgs.push("--circuit", c);
29
- }
44
+ }
45
+ /**
46
+ * Ensures the prover binary exists with the correct version, downloading it if necessary
47
+ */
48
+ async function ensureProverBinary() {
49
+ const binaryPath = getProverPathByArch();
50
+ const binaryName = getProverNameByArch();
51
+ const expectedVersion = (0, downloadProverBinary_1.getProverVersion)();
52
+ const installedVersion = getInstalledProverVersion();
53
+ if (installedVersion === expectedVersion) {
54
+ return;
30
55
  }
31
- if (proverPort) {
32
- expectedArgs.push("--prover-address", `0.0.0.0:${proverPort}`);
56
+ if (installedVersion) {
57
+ console.log(`Prover binary version mismatch. Expected: ${expectedVersion}, Found: ${installedVersion}`);
58
+ console.log("Downloading correct version...");
33
59
  }
34
- if (redisUrl) {
35
- expectedArgs.push("--redis-url", redisUrl);
60
+ else if (fs_1.default.existsSync(binaryPath)) {
61
+ console.log("Prover binary found but version could not be determined. Downloading latest version...");
36
62
  }
37
- let found = false;
38
- for (const proc of proverProcesses) {
39
- if (proc.cmd &&
40
- (proc.cmd.includes("prover-") || proc.name.startsWith("prover-"))) {
41
- console.log("\n[Prover Process Detected]");
42
- console.log(` PID: ${proc.pid}`);
43
- console.log(` Command: ${proc.cmd}`);
44
- let matches = true;
45
- for (const arg of expectedArgs) {
46
- if (!proc.cmd.includes(arg)) {
47
- matches = false;
48
- break;
49
- }
50
- }
51
- if (matches) {
52
- found = true;
53
- console.log("\x1b[32m✔ Prover is already running with the same configuration.\x1b[0m");
54
- console.log(" To restart the prover, stop the process above or use the --force flag.\n");
55
- break;
56
- }
57
- else {
58
- const missing = proc.cmd
59
- ? expectedArgs.filter((arg) => !proc.cmd.includes(arg))
60
- : [];
61
- if (missing.length > 0) {
62
- console.log(` (Not a match for current request. Missing args: ${missing.join(", ")})`);
63
- }
64
- }
65
- }
63
+ else {
64
+ console.log("Prover binary not found. Downloading...");
66
65
  }
67
- if (!found) {
68
- console.log("\x1b[33mNo running prover found with the requested configuration.\x1b[0m");
66
+ try {
67
+ await (0, downloadProverBinary_1.downloadProverBinary)(binaryPath, binaryName);
69
68
  }
70
- return found;
71
- }
72
- async function startProver(proverPort, runMode, circuits = [], force = false, redisUrl) {
73
- if (!force &&
74
- (await isProverRunningWithFlags(runMode, circuits, proverPort))) {
75
- return;
69
+ catch (error) {
70
+ throw new Error(`Failed to download prover binary: ${error instanceof Error ? error.message : String(error)}\n` +
71
+ `Please download manually from: https://github.com/Lightprotocol/light-protocol/releases`);
76
72
  }
77
- console.log("Kill existing prover process...");
73
+ }
74
+ async function startProver(proverPort, redisUrl) {
75
+ await ensureProverBinary();
78
76
  await killProver();
79
77
  await (0, process_1.killProcessByPort)(proverPort);
80
- const keysDir = path_1.default.join(__dirname, "../..", "bin", KEYS_DIR);
81
78
  const args = ["start"];
82
- args.push("--keys-dir", keysDir);
79
+ args.push("--keys-dir", KEYS_DIR);
83
80
  args.push("--prover-address", `0.0.0.0:${proverPort}`);
84
- if (runMode != null) {
85
- args.push("--run-mode", runMode);
86
- }
87
- for (const circuit of circuits) {
88
- args.push("--circuit", circuit);
89
- }
90
- if (runMode != null) {
91
- console.log(`Starting prover in ${runMode} mode...`);
92
- }
93
- else if (circuits && circuits.length > 0) {
94
- console.log(`Starting prover with circuits: ${circuits.join(", ")}...`);
95
- }
96
- if ((!circuits || circuits.length === 0) && runMode == null) {
97
- runMode = "local-rpc";
98
- args.push("--run-mode", runMode);
99
- console.log(`Starting prover with fallback ${runMode} mode...`);
100
- }
81
+ args.push("--auto-download", "true");
101
82
  if (redisUrl) {
102
83
  args.push("--redis-url", redisUrl);
103
84
  }
@@ -106,25 +87,28 @@ async function startProver(proverPort, runMode, circuits = [], force = false, re
106
87
  console.log(`Prover started successfully!`);
107
88
  }
108
89
  function getProverNameByArch() {
109
- const platform = process.platform;
110
- const arch = process.arch;
111
- if (!platform || !arch) {
90
+ const nodePlatform = process.platform;
91
+ const nodeArch = process.arch;
92
+ if (!nodePlatform || !nodeArch) {
112
93
  throw new Error("Unsupported platform or architecture");
113
94
  }
114
- let binaryName = `prover-${platform}-${arch}`;
115
- if (platform.toString() === "windows") {
116
- throw new Error("Windows OS support is not included in this NPM release. Please reach out to team@lightprotocol.com to get the Windows binary.");
117
- //@ts-ignore
95
+ let goPlatform = nodePlatform;
96
+ let goArch = nodeArch;
97
+ if (nodeArch === "x64") {
98
+ goArch = "amd64";
99
+ }
100
+ if (nodePlatform === "win32") {
101
+ goPlatform = "windows";
102
+ }
103
+ let binaryName = `prover-${goPlatform}-${goArch}`;
104
+ if (goPlatform === "windows") {
118
105
  binaryName += ".exe";
119
106
  }
120
107
  return binaryName;
121
108
  }
122
109
  function getProverPathByArch() {
123
- let binaryName = getProverNameByArch();
124
- // We need to provide the full path to the binary because it's not in the PATH.
125
- const binDir = path_1.default.join(__dirname, "../..", "bin");
126
- binaryName = path_1.default.join(binDir, binaryName);
127
- return binaryName;
110
+ const binaryName = getProverNameByArch();
111
+ return path_1.default.join(PROVER_BIN_DIR, binaryName);
128
112
  }
129
113
  async function healthCheck(port, retries = 3, timeout = 3000) {
130
114
  const fetch = (await Promise.resolve().then(() => tslib_1.__importStar(require("node-fetch")))).default;
@@ -1,6 +1,10 @@
1
1
  import * as anchor from "@coral-xyz/anchor";
2
2
  import { Keypair } from "@solana/web3.js";
3
3
  import { Rpc } from "@lightprotocol/stateless.js";
4
+ /**
5
+ * Get a Keypair from a secret key file (compatible with Solana CLI)
6
+ */
7
+ export declare function getKeypairFromFile(filepath?: string): Promise<Keypair>;
4
8
  export declare const defaultSolanaWalletKeypair: () => Keypair;
5
9
  export declare const setAnchorProvider: () => Promise<anchor.AnchorProvider>;
6
10
  export declare function rpc(): Rpc;