Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
3f713f6
feat: forester: pda & mint compression
sergeytimoshin Jan 7, 2026
979ab72
refactor rent exemption calculations
sergeytimoshin Jan 21, 2026
8e68ede
format
sergeytimoshin Jan 21, 2026
e99e8b9
feat: add support for compressed mint retrieval in the indexer
sergeytimoshin Jan 21, 2026
ac7ac52
get_compressed_mints_by_authority authority type filtering
sergeytimoshin Jan 21, 2026
c5e295d
fix: update PHOTON_COMMIT version in versions.sh
sergeytimoshin Jan 21, 2026
afdc3b0
docs: update CLI parameter descriptions for compressible PDA program
sergeytimoshin Jan 21, 2026
e659e62
feat: add hex dependency and update existing hex usage in Cargo.toml …
sergeytimoshin Jan 21, 2026
39ac71a
fix: update authority_type field in GetCompressedMintsByAuthorityOpti…
sergeytimoshin Jan 21, 2026
7400963
fix: update mint_authority and mint fields in build_expected_mint fun…
sergeytimoshin Jan 21, 2026
92b800c
feat: refactor bootstrap logic to use run_bootstrap helper; enhance m…
sergeytimoshin Jan 21, 2026
0960309
fix: update build_expected_mint function to accept version parameter …
sergeytimoshin Jan 21, 2026
b17b96c
fix: adjust calculate_compressible_slot to correctly compute availabl…
sergeytimoshin Jan 21, 2026
4b926fd
bump photon version
sergeytimoshin Jan 21, 2026
d961864
wip
sergeytimoshin Jan 23, 2026
b08f6ee
cleanup
sergeytimoshin Jan 23, 2026
6c8d2fd
cleanup
sergeytimoshin Jan 23, 2026
0b71628
cleanup
sergeytimoshin Jan 23, 2026
ef4f5a4
new apis
sergeytimoshin Jan 27, 2026
21d07c6
feat: add support for unified account interface with hot/cold context…
sergeytimoshin Jan 28, 2026
53b6e33
cleanup
sergeytimoshin Jan 28, 2026
9a5d070
format
sergeytimoshin Jan 28, 2026
a9cac11
refactor account interface
sergeytimoshin Jan 29, 2026
6c30f6f
bump photon version
sergeytimoshin Jan 29, 2026
3713350
feat: implement batch lookup for multiple compressed accounts in RPC
sergeytimoshin Jan 29, 2026
afb4f86
enhance account interface
sergeytimoshin Jan 29, 2026
052b4af
fix: update account types in get_accounts_to_update test
sergeytimoshin Jan 29, 2026
965d971
cleanup
sergeytimoshin Jan 29, 2026
a9b2352
bump photon
sergeytimoshin Jan 29, 2026
d031780
cleanup
sergeytimoshin Jan 29, 2026
03bc07e
fix: update error assertion in test_create_ata_failing for invalid mi…
sergeytimoshin Jan 29, 2026
df1637e
fix: update error assertion in test_create_ata_failing for invalid mi…
sergeytimoshin Jan 30, 2026
98d37cb
Potential fix for code scanning alert no. 143: Workflow does not cont…
sergeytimoshin Jan 30, 2026
7b915df
fix: update default version fallback to V2 in LIGHT_PROTOCOL_VERSION …
sergeytimoshin Jan 30, 2026
84f9d09
cleanup
sergeytimoshin Jan 31, 2026
4374cd4
feat: add forester to cli (particularly useful for compression tests)…
sergeytimoshin Feb 1, 2026
5ffbb7e
bump photon commit hash in versions.sh
sergeytimoshin Feb 1, 2026
c738d08
feat: enhance event handling with ATA owner extraction and update tre…
sergeytimoshin Feb 2, 2026
837567c
fix: bump photon
sergeytimoshin Feb 2, 2026
fb11f55
feat: add validator_args to LightValidatorConfig
sergeytimoshin Feb 2, 2026
cf29d71
refactor: simplify mint account interface creation in AMM stress test
sergeytimoshin Feb 2, 2026
58453b7
cleanup
sergeytimoshin Feb 2, 2026
09421b6
cleanup
sergeytimoshin Feb 2, 2026
93cc168
feat: add lint-readmes target and update README validator_args
sergeytimoshin Feb 2, 2026
3367267
feat: add support for additional account directories in setup command…
sergeytimoshin Feb 2, 2026
958d256
fix: update PHOTON_COMMIT to the latest commit hash
sergeytimoshin Feb 2, 2026
9da455b
fix: add missing RUST_LOG environment variable for test-indexer-inter…
sergeytimoshin Feb 2, 2026
97132b6
refactor: remove mint-related models and methods
sergeytimoshin Feb 4, 2026
7b9bc97
format
sergeytimoshin Feb 4, 2026
5a0a078
feat: add get_mint_interface method to Rpc trait and implement it
sergeytimoshin Feb 4, 2026
aa92def
Refactor ATA interface method and streamline mint account handling
sergeytimoshin Feb 5, 2026
99cc50f
refactor: streamline signature conversion and enhance error handling …
sergeytimoshin Feb 5, 2026
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
72 changes: 18 additions & 54 deletions .github/workflows/programs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
- "program-tests/**"
- "program-libs/**"
- "prover/client/**"
- ".github/workflows/light-system-programs-tests.yml"
- ".github/workflows/programs.yml"
pull_request:
branches:
- "*"
Expand All @@ -16,22 +16,24 @@ on:
- "program-tests/**"
- "program-libs/**"
- "prover/client/**"
- ".github/workflows/light-system-programs-tests.yml"
- ".github/workflows/programs.yml"
types:
- opened
- synchronize
- reopened
- ready_for_review

name: programs
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
system-programs:
name: programs
name: ${{ matrix.test-group }}
if: github.event.pull_request.draft == false
runs-on: warp-ubuntu-latest-x64-4x
timeout-minutes: 90
Expand All @@ -52,27 +54,16 @@ jobs:

strategy:
matrix:
include:
- program: account-compression-and-registry
sub-tests: '["cargo-test-sbf -p account-compression-test", "cargo-test-sbf -p registry-test"]'
- program: light-system-program-address
sub-tests: '["cargo-test-sbf -p system-test -- test_with_address", "cargo-test-sbf -p e2e-test", "cargo-test-sbf -p compressed-token-test --test light_token"]'
- program: light-system-program-compression
sub-tests: '["cargo-test-sbf -p system-test -- test_with_compression", "cargo-test-sbf -p system-test --test test_re_init_cpi_account"]'
- program: compressed-token-and-e2e
sub-tests: '["cargo test -p light-compressed-token", "cargo-test-sbf -p compressed-token-test --test v1", "cargo-test-sbf -p compressed-token-test --test mint"]'
- program: compressed-token-batched-tree
sub-tests: '["cargo-test-sbf -p compressed-token-test -- test_transfer_with_photon_and_batched_tree"]'
- program: system-cpi-test
sub-tests:
'["cargo-test-sbf -p system-cpi-test", "cargo test -p light-system-program-pinocchio",
"cargo-test-sbf -p system-cpi-v2-test -- --skip functional_ --skip event::parse", "cargo-test-sbf -p system-cpi-v2-test -- event::parse",
"cargo-test-sbf -p compressed-token-test --test transfer2"
]'
- program: system-cpi-test-v2-functional-read-only
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_read_only"]'
- program: system-cpi-test-v2-functional-account-infos
sub-tests: '["cargo-test-sbf -p system-cpi-v2-test -- functional_account_infos"]'
test-group:
- account-compression-and-registry
- system-address
- system-compression
- compressed-token-and-e2e
- compressed-token-batched-tree
- system-cpi
- system-cpi-v2-functional-read-only
- system-cpi-v2-functional-account-infos

steps:
- name: Checkout sources
uses: actions/checkout@v6
Expand All @@ -87,34 +78,7 @@ jobs:
run: |
just cli build

- name: ${{ matrix.program }}
- name: Run tests
working-directory: program-tests
run: |

IFS=',' read -r -a sub_tests <<< "${{ join(fromJSON(matrix['sub-tests']), ', ') }}"
for subtest in "${sub_tests[@]}"
do
echo "$subtest"

# Retry logic for flaky batched-tree test
if [[ "$subtest" == *"test_transfer_with_photon_and_batched_tree"* ]]; then
echo "Running flaky test with retry logic (max 3 attempts)..."
attempt=1
max_attempts=3
until RUSTFLAGS="-D warnings" eval "$subtest"; do
attempt=$((attempt + 1))
if [ $attempt -gt $max_attempts ]; then
echo "Test failed after $max_attempts attempts"
exit 1
fi
echo "Attempt $attempt/$max_attempts failed, retrying..."
sleep 5
done
echo "Test passed on attempt $attempt"
else
RUSTFLAGS="-D warnings" eval "$subtest"
if [ "$subtest" == "cargo-test-sbf -p e2e-test" ]; then
just programs build-compressed-token-small
RUSTFLAGS="-D warnings" eval "$subtest -- --test test_10_all"
fi
fi
done
just ci-${{ matrix.test-group }}
4 changes: 4 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Disable mise's Go management for this project.
# We use our own Go installation via devenv.sh.
[settings]
disable_tools = ["go"]
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ pinocchio-pubkey = { version = "0.3.0" }
pinocchio-system = { version = "0.3.0" }
bs58 = "^0.5.1"
sha2 = "0.10"
hex = "0.4"
litesvm = "0.7"
# Anchor
anchor-lang = { version = "0.31.1" }
Expand Down
28 changes: 28 additions & 0 deletions cli/src/commands/test-validator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,22 @@ class SetupCommand extends Command {
"Runs a test validator without starting a new prover service.",
default: false,
}),
forester: Flags.boolean({
description:
"Start the forester service for auto-compression of compressible accounts.",
default: false,
}),
"forester-port": Flags.integer({
description: "Port for the forester API server.",
required: false,
default: 8080,
}),
"compressible-pda-program": Flags.string({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"compressible-pda-program": Flags.string({
"light-pda-program": Flags.string({

description:
"Compressible PDA programs to track. Format: 'program_id:discriminator_base58'. Can be specified multiple times.",
required: false,
multiple: true,
}),
"skip-system-accounts": Flags.boolean({
description:
"Runs a test validator without initialized light system accounts.",
Expand Down Expand Up @@ -147,6 +163,13 @@ class SetupCommand extends Command {
default: true,
allowNo: true,
}),
"account-dir": Flags.string({
description:
"Additional directory containing account JSON files to preload. Can be specified multiple times.",
required: false,
multiple: true,
summary: "Usage: --account-dir <path/to/accounts/>",
}),
};

validatePrograms(
Expand Down Expand Up @@ -216,6 +239,7 @@ class SetupCommand extends Command {
await stopTestEnv({
indexer: !flags["skip-indexer"],
prover: !flags["skip-prover"],
forester: flags.forester,
});
this.log("\nTest validator stopped successfully \x1b[32m✔\x1b[0m");
} else {
Expand Down Expand Up @@ -268,6 +292,9 @@ class SetupCommand extends Command {
indexerPort: flags["indexer-port"],
proverPort: flags["prover-port"],
prover: !flags["skip-prover"],
forester: flags.forester,
foresterPort: flags["forester-port"],
compressiblePdaPrograms: flags["compressible-pda-program"],
skipSystemAccounts: flags["skip-system-accounts"],
geyserConfig: flags["geyser-config"],
validatorArgs: flags["validator-args"],
Expand All @@ -279,6 +306,7 @@ class SetupCommand extends Command {
verbose: flags.verbose,
skipReset: flags["skip-reset"],
useSurfpool: flags["use-surfpool"],
additionalAccountDirs: flags["account-dir"],
});
this.log("\nSetup tasks completed successfully \x1b[32m✔\x1b[0m");
}
Expand Down
1 change: 1 addition & 0 deletions cli/src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const SOLANA_VALIDATOR_PROCESS_NAME = "solana-test-validator";
export const SURFPOOL_PROCESS_NAME = "surfpool";
export const LIGHT_PROVER_PROCESS_NAME = "light-prover";
export const INDEXER_PROCESS_NAME = "photon";
export const FORESTER_PROCESS_NAME = "forester";

export const SURFPOOL_VERSION = "1.0.1";
export const SURFPOOL_RELEASE_TAG = "v1.0.1-light";
Expand Down
71 changes: 71 additions & 0 deletions cli/src/utils/initTestEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ import {
} from "./process";
import { killProver, startProver } from "./processProverServer";
import { killIndexer, startIndexer } from "./processPhotonIndexer";
import {
killForester,
startForester,
getPayerForForester,
} from "./processForester";
import { Connection, PublicKey } from "@solana/web3.js";
import { execSync } from "child_process";

Expand Down Expand Up @@ -101,8 +106,10 @@ async function getProgramOwnedAccounts(
export async function stopTestEnv(options: {
indexer: boolean;
prover: boolean;
forester?: boolean;
}) {
const processesToKill = [
{ name: "forester", condition: options.forester ?? false, killFunction: killForester },
{ name: "photon", condition: options.indexer, killFunction: killIndexer },
{ name: "prover", condition: options.prover, killFunction: killProver },
{
Expand Down Expand Up @@ -135,9 +142,11 @@ export async function initTestEnv({
skipSystemAccounts,
indexer = true,
prover = true,
forester = false,
rpcPort = 8899,
indexerPort = 8784,
proverPort = 3001,
foresterPort = 8080,
gossipHost = "127.0.0.1",
checkPhotonVersion = true,
photonDatabaseUrl,
Expand All @@ -148,6 +157,8 @@ export async function initTestEnv({
verbose,
skipReset,
useSurfpool,
compressiblePdaPrograms,
additionalAccountDirs,
}: {
additionalPrograms?: { address: string; path: string }[];
upgradeablePrograms?: {
Expand All @@ -158,9 +169,11 @@ export async function initTestEnv({
skipSystemAccounts?: boolean;
indexer: boolean;
prover: boolean;
forester?: boolean;
rpcPort?: number;
indexerPort?: number;
proverPort?: number;
foresterPort?: number;
gossipHost?: string;
checkPhotonVersion?: boolean;
photonDatabaseUrl?: string;
Expand All @@ -171,6 +184,8 @@ export async function initTestEnv({
verbose?: boolean;
skipReset?: boolean;
useSurfpool?: boolean;
compressiblePdaPrograms?: string[];
additionalAccountDirs?: string[];
}) {
if (useSurfpool) {
// For surfpool we can await startTestValidator because spawnBinary returns
Expand All @@ -189,6 +204,7 @@ export async function initTestEnv({
verbose,
skipReset,
useSurfpool,
additionalAccountDirs,
});
// Surfpool only supports JSON-RPC POST, not GET /health.
await confirmRpcReadiness(`http://127.0.0.1:${rpcPort}`);
Expand All @@ -207,6 +223,7 @@ export async function initTestEnv({
verbose,
skipReset,
useSurfpool,
additionalAccountDirs,
});
await waitForServers([{ port: rpcPort, path: "/health" }]);
await confirmServerStability(`http://127.0.0.1:${rpcPort}/health`);
Expand Down Expand Up @@ -250,6 +267,48 @@ export async function initTestEnv({
startSlot,
);
}

if (forester) {
if (!indexer || !prover) {
throw new Error("Forester requires both indexer and prover to be running");
}
try {
const payer = getPayerForForester();
await startForester({
rpcUrl: `http://127.0.0.1:${rpcPort}`,
wsRpcUrl: `ws://127.0.0.1:${rpcPort + 1}`,
indexerUrl: `http://127.0.0.1:${indexerPort}`,
proverUrl: `http://127.0.0.1:${proverPort}`,
payer,
foresterPort,
compressiblePdaPrograms,
});
} catch (error) {
console.error("Failed to start forester:", error);
throw error;
}
}

if (forester) {
if (!indexer || !prover) {
throw new Error("Forester requires both indexer and prover to be running");
}
try {
const payer = getPayerForForester();
await startForester({
rpcUrl: `http://127.0.0.1:${rpcPort}`,
wsRpcUrl: `ws://127.0.0.1:${rpcPort + 1}`,
indexerUrl: `http://127.0.0.1:${indexerPort}`,
proverUrl: `http://127.0.0.1:${proverPort}`,
payer,
foresterPort,
compressiblePdaPrograms,
});
} catch (error) {
console.error("Failed to start forester:", error);
throw error;
}
}
}

export async function initTestEnvIfNeeded({
Expand Down Expand Up @@ -448,6 +507,7 @@ export async function getSurfpoolArgs({
rpcPort,
gossipHost,
downloadBinaries = true,
additionalAccountDirs,
}: {
additionalPrograms?: { address: string; path: string }[];
upgradeablePrograms?: {
Expand All @@ -459,6 +519,7 @@ export async function getSurfpoolArgs({
rpcPort?: number;
gossipHost?: string;
downloadBinaries?: boolean;
additionalAccountDirs?: string[];
}): Promise<Array<string>> {
const dirPath = programsDirPath();

Expand Down Expand Up @@ -508,6 +569,13 @@ export async function getSurfpoolArgs({
args.push("--account-dir", accountsPath);
}

// Load additional account directories
if (additionalAccountDirs) {
for (const accountDir of additionalAccountDirs) {
args.push("--account-dir", path.resolve(accountDir));
}
}

return args;
}

Expand Down Expand Up @@ -603,6 +671,7 @@ export async function startTestValidator({
verbose,
skipReset,
useSurfpool,
additionalAccountDirs,
}: {
additionalPrograms?: { address: string; path: string }[];
upgradeablePrograms?: {
Expand All @@ -620,6 +689,7 @@ export async function startTestValidator({
verbose?: boolean;
skipReset?: boolean;
useSurfpool?: boolean;
additionalAccountDirs?: string[];
}) {
if (useSurfpool) {
const command = await ensureSurfpoolBinary();
Expand All @@ -629,6 +699,7 @@ export async function startTestValidator({
skipSystemAccounts,
rpcPort,
gossipHost,
additionalAccountDirs,
});

await killTestValidator(rpcPort);
Expand Down
Loading
Loading