Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add support for --sbf-program flag in test-validator #1393

Merged
merged 3 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,10 @@
"test-decompress-sol": "mocha ./test/commands/decompress-sol/index.test.ts -t 10000000 --exit",
"test-compress-spl": "mocha ./test/commands/compress-spl/index.test.ts -t 10000000 --exit",
"test-decompress-spl": "mocha ./test/commands/decompress-spl/index.test.ts -t 10000000 --exit",
"test-test-validator": "mocha ./test/commands/test-validator/index.test.ts -t 10000000 --exit",
"kill": "killall solana-test-validator || true && killall solana-test-val || true && sleep 1",
"test-cli": "pnpm test-config && pnpm kill",
"test": "pnpm kill && pnpm test-cli && pnpm test-utils && pnpm test-create-mint && pnpm test-mint-to && pnpm test-transfer && pnpm test-merge-token-accounts && pnpm test-create-token-pool && pnpm test-compress-spl && pnpm test-decompress-spl && pnpm test-balance && pnpm test-compress-sol && pnpm test-decompress-sol && pnpm test-approve-and-mint-to",
"test": "pnpm kill && pnpm test-cli && pnpm test-utils && pnpm test-create-mint && pnpm test-mint-to && pnpm test-transfer && pnpm test-merge-token-accounts && pnpm test-create-token-pool && pnpm test-compress-spl && pnpm test-decompress-spl && pnpm test-balance && pnpm test-compress-sol && pnpm test-decompress-sol && pnpm test-approve-and-mint-to && pnpm test-test-validator",
"install-local": "pnpm build && pnpm global remove @lightprotocol/zk-compression-cli || true && pnpm global add $PWD",
"version": "oclif readme && git add README.md"
},
Expand Down
76 changes: 74 additions & 2 deletions cli/src/commands/test-validator/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Command, Flags } from "@oclif/core";
import { initTestEnv, stopTestEnv } from "../../utils/initTestEnv";
import {
initTestEnv,
stopTestEnv,
SYSTEM_PROGRAMS,
} from "../../utils/initTestEnv";
import { CustomLoader } from "../../utils/index";
import path from "path";
import fs from "fs";
Expand All @@ -13,9 +17,13 @@ class SetupCommand extends Command {
"$ light test-validator --skip-indexer",
"$ light test-validator --geyser-config ./config.json",
'$ light test-validator --validator-args "--limit-ledger-size 50000000"',
sergeytimoshin marked this conversation as resolved.
Show resolved Hide resolved
"$ light test-validator --sbf-program <address> <path/program>",
];

protected finally(_: Error | undefined): Promise<any> {
protected finally(err: Error | undefined): Promise<any> {
if (err) {
console.error(err);
}
process.exit();
}

Expand Down Expand Up @@ -119,8 +127,55 @@ class SetupCommand extends Command {
required: false,
exclusive: ["geyser-config"],
}),
"sbf-program": Flags.string({
description:
"Add a SBF program to the genesis configuration with upgrades disabled. If the ledger already exists then this parameter is silently ignored. First argument can be a pubkey string or path to a keypair",
sergeytimoshin marked this conversation as resolved.
Show resolved Hide resolved
required: false,
multiple: true,
summary: "Usage: --sbf-program <address> <path/program_name.so>",
}),
};

validatePrograms(programs: { address: string; path: string }[]): void {
// Check for duplicate addresses among provided programs
const addresses = new Set<string>();
for (const program of programs) {
if (addresses.has(program.address)) {
this.error(`Duplicate program address detected: ${program.address}`);
}
addresses.add(program.address);

// Get the program filename from the path
const programFileName = path.basename(program.path);

// Check for collisions with system programs (both address and filename)
const systemProgramCollision = SYSTEM_PROGRAMS.find(
(sysProg) =>
sysProg.id === program.address ||
(sysProg.name && programFileName === sysProg.name),
);

if (systemProgramCollision) {
const collisionType =
systemProgramCollision.id === program.address
? `address (${program.address})`
: `filename (${programFileName})`;

this.error(
`Program ${collisionType} collides with system program ` +
`"${systemProgramCollision.name || systemProgramCollision.id}". ` +
`System programs cannot be overwritten.`,
);
}

// Validate program file exists
const programPath = path.resolve(program.path);
if (!fs.existsSync(programPath)) {
this.error(`Program file not found: ${programPath}`);
}
}
}

async run() {
const { flags } = await this.parse(SetupCommand);
const loader = new CustomLoader("Performing setup tasks...\n");
Expand All @@ -139,7 +194,24 @@ class SetupCommand extends Command {
});
this.log("\nTest validator stopped successfully \x1b[32m✔\x1b[0m");
} else {
const rawValues = flags["sbf-program"] || [];

if (rawValues.length % 2 !== 0) {
this.error("Each --sbf-program flag must have exactly two arguments");
}

const programs: { address: string; path: string }[] = [];
for (let i = 0; i < rawValues.length; i += 2) {
programs.push({
address: rawValues[i],
path: rawValues[i + 1],
});
}

this.validatePrograms(programs);

await initTestEnv({
additionalPrograms: programs,
checkPhotonVersion: !flags["relax-indexer-version-constraint"],
indexer: !flags["skip-indexer"],
limitLedgerSize: flags["limit-ledger-size"],
Expand Down
58 changes: 30 additions & 28 deletions cli/src/utils/initTestEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,35 @@ import {
import { killProver, startProver } from "./processProverServer";
import { killIndexer, startIndexer } from "./processPhotonIndexer";

type Program = { id: string; name?: string; tag?: string; path?: string };
export const SYSTEM_PROGRAMS: Program[] = [
{
id: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV",
name: "spl_noop.so",
tag: SPL_NOOP_PROGRAM_TAG,
},
{
id: "SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7",
name: "light_system_program.so",
tag: LIGHT_SYSTEM_PROGRAM_TAG,
},
{
id: "cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m",
name: "light_compressed_token.so",
tag: LIGHT_COMPRESSED_TOKEN_TAG,
},
{
id: "compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq",
name: "account_compression.so",
tag: LIGHT_ACCOUNT_COMPRESSION_TAG,
},
{
id: "Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX",
name: "light_registry.so",
tag: LIGHT_REGISTRY_TAG,
},
];

export async function stopTestEnv(options: {
indexer: boolean;
prover: boolean;
Expand Down Expand Up @@ -208,35 +237,8 @@ export async function getSolanaArgs({
gossipHost?: string;
downloadBinaries?: boolean;
}): Promise<Array<string>> {
type Program = { id: string; name?: string; tag?: string; path?: string };
// TODO: adjust program tags
const programs: Program[] = [
{
id: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV",
name: "spl_noop.so",
tag: SPL_NOOP_PROGRAM_TAG,
},
{
id: "SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7",
name: "light_system_program.so",
tag: LIGHT_SYSTEM_PROGRAM_TAG,
},
{
id: "cTokenmWW8bLPjZEBAUgYy3zKxQZW6VKi7bqNFEVv3m",
name: "light_compressed_token.so",
tag: LIGHT_COMPRESSED_TOKEN_TAG,
},
{
id: "compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq",
name: "account_compression.so",
tag: LIGHT_ACCOUNT_COMPRESSION_TAG,
},
{
id: "Lighton6oQpVkeewmo2mcPTQQp7kYHr4fWpAgJyEmDX",
name: "light_registry.so",
tag: LIGHT_REGISTRY_TAG,
},
];
const programs: Program[] = [...SYSTEM_PROGRAMS];
if (additionalPrograms)
additionalPrograms.forEach((program) => {
programs.push({ id: program.address, path: program.path });
Expand Down
16 changes: 7 additions & 9 deletions cli/src/utils/processPhotonIndexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,14 @@ export async function startIndexer(
throw new Error(message);
} else {
console.log("Starting indexer...");
let args: string[] = [];
const args: string[] = [
"--port",
indexerPort.toString(),
"--rpc-url",
rpcUrl,
];
if (photonDatabaseUrl) {
args = [
"--db-url",
photonDatabaseUrl,
"--port",
indexerPort.toString(),
"--rpc-url",
rpcUrl,
];
args.push("--db-url", photonDatabaseUrl);
}
spawnBinary(INDEXER_PROCESS_NAME, args);
await waitForServers([{ port: indexerPort, path: "/getIndexerHealth" }]);
Expand Down
Loading
Loading