Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/ci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ jobs:
shell: bash
- name: Check workflow files
run: ${{ steps.get_actionlint.outputs.executable }} -color
shell: bash
shell: bash
8 changes: 6 additions & 2 deletions .github/workflows/light-examples-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@ on:
- main
paths:
- "examples/**"
- "program-tests/sdk-anchor-test/**"
- "program-tests/sdk-pinocchio-test/**"
- "sdk-libs/**"
pull_request:
branches:
- "*"
paths:
- "examples/**"
- "program-tests/sdk-anchor-test/**"
- "program-tests/sdk-pinocchio-test/**"
- "sdk-libs/**"
types:
- opened
Expand All @@ -24,8 +28,8 @@ concurrency:
cancel-in-progress: true

jobs:
system-programs:
name: system-programs
examples-tests:
name: examples-tests
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
timeout-minutes: 60
Expand Down
89 changes: 89 additions & 0 deletions .github/workflows/sdk-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
on:
push:
branches:
- main
paths:
- "sdk-tests/**"
- "sdk-libs/**"
- "program-libs/**"
- ".github/workflows/sdk-tests.yml"
pull_request:
branches:
- "*"
paths:
- "sdk-tests/**"
- "sdk-libs/**"
- "program-libs/**"
- ".github/workflows/sdk-tests.yml"
types:
- opened
- synchronize
- reopened
- ready_for_review

name: sdk-tests

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

jobs:
sdk-tests:
name: sdk-tests
if: github.event.pull_request.draft == false
runs-on: warp-ubuntu-latest-x64-4x
timeout-minutes: 60

services:
redis:
image: redis:8.0.1
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
REDIS_URL: redis://localhost:6379
RUST_MIN_STACK: 8388608

steps:
- name: Checkout sources
uses: actions/checkout@v4

- name: Setup and build
uses: ./.github/actions/setup-and-build
with:
skip-components: "redis"

- name: Build CLI
run: |
source ./scripts/devenv.sh
npx nx build @lightprotocol/zk-compression-cli

- name: Build core programs
run: |
source ./scripts/devenv.sh
npx nx build @lightprotocol/programs

- name: Build and test all sdk-tests programs
run: |
source ./scripts/devenv.sh
# Increase stack size for SBF compilation to avoid regex_automata stack overflow
export RUST_MIN_STACK=16777216
# Remove -D warnings flag for SBF compilation to avoid compilation issues
export RUSTFLAGS=""

echo "Building and testing all sdk-tests programs sequentially..."
# Build and test each program one by one to ensure .so files exist

echo "Building and testing native-compressible"
cargo-test-sbf -p native-compressible

echo "Building and testing anchor-compressible"
cargo-test-sbf -p anchor-compressible

echo "Building and testing anchor-compressible-derived"
cargo-test-sbf -p anchor-compressible-derived
158 changes: 158 additions & 0 deletions AUTO_SEED_GENERATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
# 🎉 Automatic Seed Generation - Zero Manual Implementation

The `add_compressible_instructions_enhanced` macro now supports **completely automatic** seed generation for both PDA accounts and CToken accounts. **NO MORE MANUAL IMPLEMENTATION NEEDED!**

## ✅ **The New Developer Experience**

### **Before (Manual Hell):** 100+ lines of boilerplate

```rust
// Manual PDA seed functions
pub fn get_user_record_seeds(user: &Pubkey) -> (Vec<Vec<u8>>, Pubkey) { /* 10 lines */ }
pub fn get_game_session_seeds(session_id: u64) -> (Vec<Vec<u8>>, Pubkey) { /* 10 lines */ }
pub fn get_placeholder_record_seeds(placeholder_id: u64) -> (Vec<Vec<u8>>, Pubkey) { /* 10 lines */ }

// Manual CToken seed function
pub fn get_ctoken_signer_seeds(user: &Pubkey, mint: &Pubkey) -> (Vec<Vec<u8>>, Pubkey) { /* 15 lines */ }

// Manual CTokenSeedProvider trait implementation
impl ctoken_seed_system::CTokenSeedProvider for CTokenAccountVariant { /* 30+ lines */ }
```

### **After (Pure Magic):** 1 macro call

```rust
#[add_compressible_instructions_enhanced(
UserRecord = ("user_record", data.owner),
GameSession = ("game_session", data.session_id.to_le_bytes()),
PlaceholderRecord = ("placeholder_record", data.placeholder_id.to_le_bytes()),
CTokenSigner = ("ctoken_signer", ctx.fee_payer, ctx.mint)
)]
#[program]
pub mod my_program {
// Your instructions - zero seed boilerplate! 🎉
}
```

## 🔥 **Syntax Guide**

### **PDA Account Seeds**

For PDA accounts, use `data.field_name` to access account data:

```rust
UserRecord = ("user_record", data.owner),
GameSession = ("game_session", data.session_id.to_le_bytes()),
CustomAccount = ("custom", data.custom_field, data.another_field.to_le_bytes())
```

### **CToken Account Seeds**

For CToken accounts, use `ctx.field_name` to access context:

```rust
CTokenSigner = ("ctoken_signer", ctx.fee_payer, ctx.mint),
UserVault = ("user_vault", ctx.owner, ctx.mint),
CustomTokenAccount = ("custom_token", ctx.accounts.custom_field, ctx.mint)
```

### **Supported Expressions**

The macro supports any valid Rust expression:

```rust
// String literals
"user_record"

// Data field access (for PDAs)
data.owner // Pubkey field
data.session_id.to_le_bytes() // u64 to bytes
data.custom_field // Any field

// Context field access (for CTokens)
ctx.fee_payer // Standard context
ctx.mint // Standard context
ctx.owner // Standard context
ctx.accounts.user // Instruction account access

// Complex expressions
some_id.to_be_bytes()
custom_calculation()
```

## 🚀 **Real World Examples**

### **Gaming Platform**

```rust
#[add_compressible_instructions_enhanced(
UserProfile = ("user_profile", data.owner),
GameSession = ("game_session", data.session_id.to_le_bytes()),
Achievement = ("achievement", data.player, data.achievement_id.to_le_bytes()),
GameToken = ("game_token", ctx.fee_payer, ctx.mint),
RewardVault = ("reward_vault", ctx.accounts.game_session, ctx.mint)
)]
```

### **DeFi Protocol**

```rust
#[add_compressible_instructions_enhanced(
UserAccount = ("user_account", data.owner),
LendingPool = ("lending_pool", data.pool_id.to_le_bytes()),
Position = ("position", data.user, data.pool_id.to_le_bytes()),
LPToken = ("lp_token", ctx.fee_payer, ctx.mint),
RewardToken = ("reward_token", ctx.accounts.position, ctx.mint)
)]
```

### **NFT Marketplace**

```rust
#[add_compressible_instructions_enhanced(
Listing = ("listing", data.seller, data.nft_mint),
Bid = ("bid", data.bidder, data.listing_id.to_le_bytes()),
Escrow = ("escrow", data.buyer, data.seller, data.nft_mint),
EscrowToken = ("escrow_token", ctx.accounts.escrow, ctx.mint)
)]
```

## ⚡ **Key Benefits**

1. **🔥 Zero Boilerplate**: No manual seed functions or trait implementations
2. **🎯 Declarative**: Specify seeds directly in the macro
3. **🚀 Generic**: Works with any account structure and field types
4. **💪 Type-Safe**: Compile-time validation of seed specifications
5. **🔧 Flexible**: Support for complex expressions and field access patterns
6. **📚 Maintainable**: All seed logic centralized in one place
7. **⚡ Fast**: No runtime overhead, everything generated at compile time

## 🎊 **Migration Guide**

### **Step 1**: Remove manual implementations

```rust
// DELETE THESE:
// pub fn get_user_record_seeds(...) -> (Vec<Vec<u8>>, Pubkey) { ... }
// impl CTokenSeedProvider for CTokenAccountVariant { ... }
```

### **Step 2**: Add seed specifications to macro

```rust
// REPLACE THIS:
#[add_compressible_instructions_enhanced(UserRecord, GameSession)]

// WITH THIS:
#[add_compressible_instructions_enhanced(
UserRecord = ("user_record", data.owner),
GameSession = ("game_session", data.session_id.to_le_bytes())
)]
```

### **Step 3**: Enjoy zero-maintenance seed management! 🎉

---

**The manual implementation era is OVER.** 💀
**Welcome to the age of automatic seed generation!** 🚀
Loading