The verify example demonstrates the complete verification flow with all 4 verifiers. You can specify which proof file to verify using the --proof argument.
cargo run --bin client verify --rpc-url <YOUR_RPC> --payer-keypair <YOUR_KEY> --proof <YOUR_PROOF>
Run with default proof (saya.json):
cargo run --example verifyRun with a specific proof file:
cargo run --example verify -- --proof example_proof/fibonnaci_proof.jsonOr use the short form:
cargo run --example verify -- -p example_proof/fibonnaci_proof.jsonThe following proof files are available in the example_proof/ directory:
saya.json(default)fibonnaci_proof.jsonfactorial_proof.json
- Deploys all 4 verifier programs to the Solana network
- Creates two accounts for the ping-pong architecture
- Loads the specified proof from the JSON file
- Executes Stage 1 (Verifier1) - validates public input, computes hash, creates STARK commitment
- Executes Stage 2 (Verifier2) - verifies STARK decommitments
- Executes Stage 3 (Verifier3) - verifies STARK verification step
- Executes Stage 4 (Verifier4) - verifies FRI (Fast Reed-Solomon Interactive) proof
- Displays final verification results including program hash and output hash
The example uses the ping-pong pattern to transfer data between accounts as ownership changes between verifiers.
Before building or running the project, ensure you have the following dependencies installed:
-
System packages:
libudev-devbuild-essentialpkg-configllvmlibclang-devprotobuf-compilerlibssl-dev
-
Solana CLI:
-
Install using:
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"
-
After installation, ensure Solana CLI binaries are in your PATH:
echo "$HOME/.local/share/solana/install/active_release/bin" >> ~/.bashrc
source ~/.bashrcThis project demonstrates how to build, deploy, and interact with Solana programs using Rust, with a focus on on-chain verification of various computational tasks.
This verifier is a working proof of concept. The current implementation includes:
- ✅ Full end-to-end verification flow working
- ✅ Stack overflow fixes and compute unit optimizations
- ✅ Ping-pong architecture for data sharing between verifiers
- ✅ All 4 verifiers tested and passing
- ✅ Integration between verifiers functional
⚠️ Production hardening needed (error handling, edge cases)⚠️ Performance optimizations for larger proofs⚠️ Security audit recommended before production use
Note: This is a proof of concept that demonstrates the complete verification pipeline. While functional, it requires additional hardening and security review before production deployment.
- Uncomment safety assertions - Many critical safety checks are currently commented out for development
- Remove unwrap() calls - Replace with proper error handling and graceful failure modes
- Add bounds checking - Ensure array and FunVec access never goes out of bounds
- Validate input data - Add comprehensive validation for all external inputs
- Optimize FunVec/array sizes - Current fixed sizes may not handle larger proofs
- Implement chunked processing - Replace single-transaction loops with chunked processing:
// Instead of: for item in large_data { process(item) } // Use: process_in_chunks(large_data, chunk_size)
- Dynamic sizing - Allow FunVec and arrays to scale based on proof size
- Transaction batching - Split large operations across multiple transactions
- Remove development shortcuts - Clean up temporary workarounds
- Add comprehensive logging - Better debugging and monitoring capabilities
- Improve documentation - Add detailed comments for complex algorithms
- Memory optimization - Reduce stack allocations and improve memory efficiency
client/: A Rust client application that deploys and interacts with programsprograms/: Solana programs written in Rustverifier1/: Core verification program responsible for first stage of verification - validate-public-input, get-hash, stark-commitverifier2/: Core verification program responsible for second stage of verification - stark-verifyverifier3/: Third stage verification program - stark-verify-verificationverifier4/: Fourth stage verification program - stark-verify-friutils/: Shared utilities for Solana programs
tasks/: Task implementations for the verifierfelt/: Field element typeget_hash/: Hashing utilitespedersen/: Pedersen hash implementationposeidon/: Poseidon hash implementationstark_commit/: STARK commitment logicstark_verify/: STARK verification logicstark_verify_verification/: STARK verification verification logicstark_verify_fri/: STARK verification FRI logictypes/: Common types for tasks, proof and etcvalidate_public_input/: Public input validationverify_1/: First stage verification logic, combining all requiered stepsverify_2/: Second stage verification logicverify_3/: Third stage verification logicverify_4/: Fourth stage verification logicverify_public_input/: Public input verification
This project uses a two-account ping-pong architecture to handle large data (904KB) across 4 verifier programs, since Solana only allows a program to modify accounts it owns.
4 verifier programs need to share and modify the same large data (904176 bytes), but Solana only allows a program to modify accounts it owns.
Use 2 accounts that alternate ownership between verifiers:
account1 ←→ account2
904KB 904KB
Client creates:
- account1 (owner: verifier1, size: 904176 bytes)
- account2 (owner: verifier2, size: 904176 bytes)
Client initializes account1 with initial data
Owner: account1 = verifier1, account2 = verifier2
verifier1.Execute(account1)
→ Computes in account1
→ Results stored in account1
Owner: account1 = verifier1, account2 = verifier2
verifier2.CopyFromAccount(source: account1, dest: account2)
→ Reads account1 (readonly, OK even though owner is verifier1)
→ Copies to account2 (writable, OK because owner is verifier2)
verifier2.Execute(account2)
→ Computes in account2
→ Results stored in account2
Need to transfer ownership!
Client calls:
transfer_ownership(account1, new_owner: verifier3)
Owner: account1 = verifier3, account2 = verifier2
verifier3.CopyFromAccount(source: account2, dest: account1)
→ Reads account2 (readonly, OK)
→ Copies to account1 (writable, OK because owner is verifier3)
verifier3.Execute(account1)
→ Computes in account1
→ Results stored in account1
Client calls:
transfer_ownership(account2, new_owner: verifier4)
Owner: account1 = verifier3, account2 = verifier4
verifier4.CopyFromAccount(source: account1, dest: account2)
→ Reads account1 (readonly, OK)
→ Copies to account2 (writable, OK because owner is verifier4)
verifier4.Execute(account2)
→ Computes in account2
→ FINAL RESULTS in account2
Solana requires accounts to be zeroed before ownership transfer:
// In verifier program or via System Program:
account.realloc(0, false)?; // Zero the data
account.assign(&new_owner_program_id)?; // Transfer ownership
account.realloc(904176, false)?; // Resize back✅ Each verifier can modify its own account
✅ Each verifier can read from the other account (readonly)
✅ No PDA or invoke_signed complexity
✅ Simple ping-pong pattern
- CopyFromAccount instruction in all verifiers
- Test for verifier1 → verifier2 copy
- Ownership transfer mechanism (TransferOwnership instruction in verifier1)
- Test for ownership transfer (test_two_accounts.rs now includes transfer test)
- Full 4-verifier test
- Integration with existing verify flow
- Start a Solana test validator:
solana-test-validator- Build the Solana programs:
./scripts/compile.sh- Build and run the verification:
cargo run deploy
cargo run verify
cargo run retrive-fundsThe client demonstrates how to:
- Create and manage Solana keypairs
- Request airdrops of SOL for testing
- Deploy Solana programs programmatically using the Solana SDK
- Create program accounts
- Send transactions to interact with the program
- Read account data from the blockchain