Skip to content
Open
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
56 changes: 53 additions & 3 deletions .github/workflows/rust-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ jobs:
- counter/native
- counter/pinocchio
- account-comparison
- zk-id
- zk/zk-id
- zk/zk-nullifier
- zk/zk-merkle-proof
- airdrop-implementations/simple-claim/program
include:
- example: basic-operations/native
Expand All @@ -51,10 +53,10 @@ jobs:
example: ${{ matrix.example }}
solana-cli-version: ${{ env.SOLANA_CLI_VERSION }}
rust-toolchain: ${{ env.RUST_TOOLCHAIN }}
install-circom: ${{ matrix.example == 'zk-id' }}
install-circom: ${{ startsWith(matrix.example, 'zk/') || startsWith(matrix.example, 'zk/') }}

- name: Setup ZK circuits
if: matrix.example == 'zk-id'
if: startsWith(matrix.example, 'zk/') || startsWith(matrix.example, 'zk/')
working-directory: ${{ matrix.example }}
run: ./scripts/setup.sh

Expand All @@ -66,3 +68,51 @@ jobs:
else
cargo test-sbf
fi

test-ts:
name: TS ${{ matrix.example }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example:
- zk/zk-id
- zk/zk-nullifier
- zk/zk-merkle-proof
steps:
- uses: actions/checkout@v4

- name: Setup environment
uses: ./.github/actions/setup
with:
example: ${{ matrix.example }}
solana-cli-version: ${{ env.SOLANA_CLI_VERSION }}
rust-toolchain: ${{ env.RUST_TOOLCHAIN }}
install-circom: true

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'

- name: Setup ZK circuits
working-directory: ${{ matrix.example }}
run: ./scripts/setup.sh

- name: Build program
working-directory: ${{ matrix.example }}
run: cargo build-sbf

- name: Install dependencies
working-directory: ${{ matrix.example }}
run: npm install

- name: Start validator and run TS tests
working-directory: ${{ matrix.example }}
run: |
solana-test-validator --reset &
sleep 5
solana airdrop 100
sleep 2
solana program deploy target/deploy/*.so
npm run test:ts
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ test-ledger
.claude
build
pot

# ZK examples - not ready
zk/mixer/
zk/shielded-pool/
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@
For simple client side distribution visit [this example](https://github.com/Lightprotocol/example-token-distribution).

### Basic Operations
- **[create-nullifier](./basic-operations/anchor/create-nullifier)** - Basic Anchor example to create nullifiers.
- **[basic-operations/anchor](./basic-operations/anchor/)** - Anchor program with Rust and TypeScript tests
- **[basic-operations/native-rust](./basic-operations/native-rust/)** - Native Solana program with light-sdk and Rust tests.

Basic Operations include:
- **create** - Initialize a new compressed account.
- **update** - Modify data in an existing compressed account.
- **close** - Clear account data and preserve its address.
- **reinit** - Reinitialize a closed account with the same address.
- **burn** - Permanently delete a compressed account.
- **[create-nullifier](./basic-operations/anchor/create-nullifier)** - Basic Anchor example to create nullifiers for payments.
- **create** - Initialize a new compressed account
- [Anchor](./basic-operations/anchor/create) | [Native](./basic-operations/native/programs/create)
- **update** - Modify data in an existing compressed account
- [Anchor](./basic-operations/anchor/update) | [Native](./basic-operations/native/programs/update)
- **close** - Clear account data and preserve its address
- [Anchor](./basic-operations/anchor/close) | [Native](./basic-operations/native/programs/close)
- **reinit** - Reinitialize a closed account with the same address
- [Anchor](./basic-operations/anchor/reinit) | [Native](./basic-operations/native/programs/reinit)
- **burn** - Permanently delete a compressed account
- [Anchor](./basic-operations/anchor/burn) | [Native](./basic-operations/native/programs/burn)

### Counter Program

Expand All @@ -45,9 +47,16 @@ Full compressed account lifecycle (create, increment, decrement, reset, close):

- **[account-comparison](./account-comparison/)** - Compare compressed vs regular Solana accounts.

### zk-id Program
### ZK Programs

- **[zk-id](./zk-id)** - A minimal zk id Solana program that uses zero-knowledge proofs for identity verification with compressed accounts.
**Full Examples:**

- **[zk-id](./zk/zk-id)** - Identity verification using Groth16 proofs. Issuers create credentials; users prove ownership without revealing the credential.

**Basic Examples:**

- **[zk-nullifier](./zk/zk-nullifier)** - Creates one or four nullifiers. Uses Groth16 proofs and compressed accounts.
- **[zk-merkle-proof](./zk/zk-merkle-proof)** - Creates compressed accounts and verifies with Groth16 proofs (without nullifier).


## Light Protocol dependencies
Expand Down
153 changes: 153 additions & 0 deletions zk/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Makefile for building and testing all ZK examples
# Usage:
# make all - Build and test all examples
# make build - Build all Solana programs
# make test-rust - Run all Rust tests
# make test-ts - Run all TypeScript tests
# make clean - Clean all build artifacts

SHELL := /bin/bash

# ZK example directories
ZK_EXAMPLES := zk-nullifier zk-id zk-merkle-proof

.PHONY: all build deploy test-rust test-ts clean setup help $(ZK_EXAMPLES)

help:
@echo "ZK Examples Makefile"
@echo ""
@echo "Usage:"
@echo " make all - Build and test all examples (Rust + TypeScript)"
@echo " make build - Build all Solana programs"
@echo " make deploy - Deploy all programs to validator (builds first)"
@echo " make test-rust - Run all Rust tests (cargo test-sbf)"
@echo " make test-ts - Run all TypeScript tests (deploys first)"
@echo " make setup - Setup circuits for all examples"
@echo " make clean - Clean all build artifacts"
@echo ""
@echo "Individual examples:"
@echo " make zk-nullifier - Build and test zk-nullifier"
@echo " make zk-id - Build and test zk-id"
@echo " make zk-merkle-proof - Build and test zk-merkle-proof"

all: build test-rust test-ts
@echo "All examples built and tested successfully!"

build:
@echo "Building all ZK examples..."
@for dir in $(ZK_EXAMPLES); do \
echo "Building $$dir..."; \
cd $$dir && cargo build-sbf && cd ..; \
if [ $$? -ne 0 ]; then \
echo "Failed to build $$dir"; \
exit 1; \
fi; \
echo "$$dir built successfully"; \
done
@echo "All programs built successfully!"

deploy: build
@echo "Deploying all ZK programs..."
@for dir in $(ZK_EXAMPLES); do \
echo "Deploying $$dir..."; \
if [ -f "$$dir/target/deploy/"*.so ]; then \
solana program deploy $$dir/target/deploy/*.so; \
if [ $$? -ne 0 ]; then \
echo "Failed to deploy $$dir"; \
exit 1; \
fi; \
echo "$$dir deployed successfully"; \
else \
echo "No .so file found for $$dir, skipping deploy"; \
fi; \
done
@echo "All programs deployed!"

test-rust:
@echo "Running Rust tests for all ZK examples..."
@for dir in $(ZK_EXAMPLES); do \
echo "Testing $$dir (Rust)..."; \
cd $$dir && cargo test-sbf && cd ..; \
if [ $$? -ne 0 ]; then \
echo "Rust tests failed for $$dir"; \
exit 1; \
fi; \
echo "$$dir Rust tests passed"; \
done
@echo "All Rust tests passed!"

test-ts: deploy
@echo "Running TypeScript tests for all ZK examples..."
@for dir in $(ZK_EXAMPLES); do \
echo "Testing $$dir (TypeScript)..."; \
if [ -f "$$dir/package.json" ]; then \
cd $$dir && npm run test:ts && cd ..; \
if [ $$? -ne 0 ]; then \
echo "TypeScript tests failed for $$dir"; \
exit 1; \
fi; \
echo "$$dir TypeScript tests passed"; \
else \
echo "No package.json found in $$dir, skipping TS tests"; \
fi; \
done
@echo "All TypeScript tests passed!"

setup:
@echo "Setting up circuits for all ZK examples..."
@for dir in $(ZK_EXAMPLES); do \
echo "Setting up $$dir..."; \
if [ -f "$$dir/scripts/setup.sh" ]; then \
cd $$dir && ./scripts/setup.sh && cd ..; \
if [ $$? -ne 0 ]; then \
echo "Setup failed for $$dir"; \
exit 1; \
fi; \
echo "$$dir setup completed"; \
else \
echo "No setup script found in $$dir"; \
fi; \
done
@echo "All setups completed!"

clean:
@echo "Cleaning all ZK examples..."
@for dir in $(ZK_EXAMPLES); do \
echo "Cleaning $$dir..."; \
cd $$dir && cargo clean && cd ..; \
if [ -d "$$dir/build" ]; then \
rm -rf $$dir/build; \
fi; \
if [ -d "$$dir/node_modules" ]; then \
rm -rf $$dir/node_modules; \
fi; \
done
@echo "All examples cleaned!"

# Individual example targets
zk-nullifier:
@echo "Building, deploying, and testing zk-nullifier..."
@cd zk-nullifier && cargo build-sbf && cargo test-sbf
@solana program deploy zk-nullifier/target/deploy/zk_nullifier.so
@if [ -f "zk-nullifier/package.json" ]; then \
cd zk-nullifier && npm run test:ts; \
fi
@echo "zk-nullifier completed!"

zk-id:
@echo "Building, deploying, and testing zk-id..."
@cd zk-id && cargo build-sbf && cargo test-sbf
@solana program deploy zk-id/target/deploy/zk_id.so
@if [ -f "zk-id/package.json" ]; then \
cd zk-id && npm run test:ts; \
fi
@echo "zk-id completed!"

zk-merkle-proof:
@echo "Building, deploying, and testing zk-merkle-proof..."
@cd zk-merkle-proof && cargo build-sbf && cargo test-sbf
@solana program deploy zk-merkle-proof/target/deploy/zk_merkle_proof.so
@if [ -f "zk-merkle-proof/package.json" ]; then \
cd zk-merkle-proof && npm run test:ts; \
fi
@echo "zk-merkle-proof completed!"
59 changes: 59 additions & 0 deletions zk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# ZK Examples

Building a private Solana program requires a Merkle tree to store state, a way to track nullifiers, and an indexer to serve Merkle proofs.

You can use Light to:
- Track and store nullifiers rent-free in indexed address Merkle trees
- Store state rent-free in indexed state Merkle trees as compressed accounts

[Learn more in the documentation](https://www.zkcompression.com/zk/overview)

## Examples

**Full Examples:**

- **[zk-id](./zk-id)** - Identity verification using Groth16 proofs. Issuers create credentials; users prove ownership without revealing the credential.

**Basic Examples:**

- **[zk-nullifier](./zk-nullifier)** - Creates one or four nullifiers. Uses Groth16 proofs and compressed accounts.
- **[zk-merkle-proof](./zk-merkle-proof)** - Creates compressed accounts and verifies with Groth16 proofs (without nullifier).

## Building and Testing

A Makefile is provided for building, deploying, and testing all examples:

```bash
# Build all programs
make build

# Deploy all programs to local validator
make deploy

# Run Rust tests (cargo test-sbf)
make test-rust

# Run TypeScript tests (deploys programs first)
make test-ts

# Build and run all tests
make all

# Individual examples
make zk-nullifier
make zk-id
make zk-merkle-proof

# Show all available commands
make help
```

## Light Protocol V2 API

These examples use Light Protocol SDK v0.17+ with the V2 accounts layout:

- `light_sdk::cpi::v2::CpiAccounts` - V2 CPI accounts builder
- `light_sdk::cpi::v2::LightSystemProgramCpi` - V2 system program CPI
- `PackedAddressTreeInfo::into_new_address_params_assigned_packed()` - V2 address parameters

The V2 layout requires a `system_accounts_offset` parameter to locate system accounts in remaining accounts.
File renamed without changes.
19 changes: 19 additions & 0 deletions zk/zk-id/Anchor.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[toolchain]
anchor_version = "0.31.1"

[features]
resolution = true
skip-lint = false

[programs.localnet]
zk_id = "8HYAuAkoLp2UG4mgkqUcJBXo2bzaaKy8nBL62L4S3SSB"

[registry]
url = "https://api.apr.dev"

[provider]
cluster = "localnet"
wallet = "~/.config/solana/id.json"

[scripts]
test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts"
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions zk/zk-id/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[workspace]
members = ["programs/zk-id"]
resolver = "2"

[profile.release]
overflow-checks = true
lto = "fat"
codegen-units = 1

[profile.release.build-override]
opt-level = 3
incremental = false
codegen-units = 1
Loading
Loading