Skip to content
Closed
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
31 changes: 31 additions & 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 @@ -62,6 +62,7 @@ members = [
"sdk-tests/csdk-anchor-full-derived-test-sdk",
"sdk-tests/single-mint-test",
"sdk-tests/single-pda-test",
"sdk-tests/single-account-loader-test",
"sdk-tests/single-ata-test",
"sdk-tests/single-token-test",
"forester-utils",
Expand Down
10 changes: 5 additions & 5 deletions sdk-libs/macros/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This crate provides macros that enable rent-free compressed accounts on Solana w
| Macro | Type | Purpose |
|-------|------|---------|
| `#[derive(LightAccounts)]` | Derive | Generates `LightPreInit`/`LightFinalize` for Accounts structs |
| `#[rentfree_program]` | Attribute | Program-level auto-discovery and instruction generation |
| `#[light_program]` | Attribute | Program-level auto-discovery and instruction generation |
| `#[derive(LightCompressible)]` | Derive | Combined traits for compressible account data |
| `#[derive(Compressible)]` | Derive | Compression traits (HasCompressionInfo, CompressAs, Size) |
| `#[derive(CompressiblePack)]` | Derive | Pack/Unpack with Pubkey-to-index compression |
Expand All @@ -25,7 +25,7 @@ Detailed macro documentation is in the `docs/` directory:

- **`docs/CLAUDE.md`** - Documentation structure guide
- **`docs/rentfree.md`** - `#[derive(LightAccounts)]` and trait derives
- **`docs/rentfree_program/`** - `#[rentfree_program]` attribute macro (architecture.md + codegen.md)
- **`docs/light_program/`** - `#[light_program]` attribute macro (architecture.md + codegen.md)

## Source Structure

Expand All @@ -35,15 +35,15 @@ src/
├── rentfree/ # LightAccounts macro system
│ ├── account/ # Trait derive macros for account data structs
│ ├── accounts/ # #[derive(LightAccounts)] for Accounts structs
│ ├── program/ # #[rentfree_program] attribute macro
│ ├── program/ # #[light_program] attribute macro
│ └── shared_utils.rs # Common utilities
└── hasher/ # LightHasherSha derive macro
```

## Usage Example

```rust
use light_sdk_macros::{rentfree_program, LightAccounts, LightCompressible};
use light_sdk_macros::{light_program, LightAccounts, LightCompressible};

// State account with compression support
#[derive(Default, Debug, InitSpace, LightCompressible)]
Expand All @@ -67,7 +67,7 @@ pub struct Create<'info> {
}

// Program with auto-wrapped instructions
#[rentfree_program]
#[light_program]
#[program]
pub mod my_program {
pub fn create(ctx: Context<Create>, params: CreateParams) -> Result<()> {
Expand Down
14 changes: 7 additions & 7 deletions sdk-libs/macros/docs/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ Documentation for the rentfree macro system in `light-sdk-macros`. These macros
| **`CLAUDE.md`** | This file - documentation structure guide |
| **`../CLAUDE.md`** | Main entry point for sdk-libs/macros |
| **`rentfree.md`** | `#[derive(LightAccounts)]` macro and trait derives |
| **`rentfree_program/`** | `#[rentfree_program]` attribute macro |
| **`rentfree_program/architecture.md`** | Architecture overview, usage, generated items |
| **`rentfree_program/codegen.md`** | Technical implementation details (code generation) |
| **`light_program/`** | `#[light_program]` attribute macro |
| **`light_program/architecture.md`** | Architecture overview, usage, generated items |
| **`light_program/codegen.md`** | Technical implementation details (code generation) |
| **`accounts/`** | Field-level attributes for Accounts structs |
| **`account/`** | Trait derive macros for account data structs |

Expand Down Expand Up @@ -43,13 +43,13 @@ See also: `#[light_account(init)]` attribute documented in `rentfree.md`

- **Data struct traits**: Start with `account/light_compressible.md` for the all-in-one derive macro for compressible data structs
- **Building account structs**: Use `rentfree.md` for the accounts-level derive macro that marks fields for compression
- **Program-level integration**: Use `rentfree_program/architecture.md` for program-level auto-discovery and instruction generation
- **Implementation details**: Use `rentfree_program/codegen.md` for technical code generation details
- **Program-level integration**: Use `light_program/architecture.md` for program-level auto-discovery and instruction generation
- **Implementation details**: Use `light_program/codegen.md` for technical code generation details

### Macro Hierarchy

```
#[rentfree_program] <- Program-level (rentfree_program/)
#[light_program] <- Program-level (light_program/)
Comment on lines 51 to +52
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding a language identifier to the fenced code block.

The macro hierarchy diagram uses a plain fenced code block. While it's an ASCII diagram (not executable code), adding a language identifier like text or leaving it empty with triple backticks satisfies markdown linters and improves accessibility for screen readers.

📝 Suggested fix
-```
+```text
 #[light_program]          <- Program-level (light_program/)
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

51-51: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
In `@sdk-libs/macros/docs/CLAUDE.md` around lines 51 - 52, The fenced code block
containing the ASCII macro hierarchy entry "#[light_program]          <-
Program-level (light_program/)" should include a language identifier (e.g.,
text) to satisfy markdown linters and improve accessibility; update the fence
surrounding that block so it starts with three backticks plus an identifier (for
example "```text") while leaving the ASCII content unchanged.

|
+-- Discovers #[derive(LightAccounts)] structs
|
Expand Down Expand Up @@ -77,7 +77,7 @@ See also: `#[light_account(init)]` attribute documented in `rentfree.md`
sdk-libs/macros/src/rentfree/
├── account/ # Trait derive macros for account data structs
├── accounts/ # #[derive(LightAccounts)] implementation
├── program/ # #[rentfree_program] implementation
├── program/ # #[light_program] implementation
├── shared_utils.rs # Common utilities
└── mod.rs # Module exports
```
2 changes: 1 addition & 1 deletion sdk-libs/macros/docs/accounts/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,6 @@ When no `#[instruction]` attribute is present, the macro generates no-op impleme

## 6. Related Documentation

- **`sdk-libs/macros/docs/rentfree_program/`** - Program-level `#[rentfree_program]` attribute macro (architecture.md + codegen.md)
- **`sdk-libs/macros/docs/light_program/`** - Program-level `#[light_program]` attribute macro (architecture.md + codegen.md)
- **`sdk-libs/macros/README.md`** - Package overview
- **`sdk-libs/sdk/`** - Runtime SDK with `LightPreInit`, `LightFinalize` trait definitions
2 changes: 1 addition & 1 deletion sdk-libs/macros/docs/features/comparison.md
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ pub struct MyData {
1. **Add derives**: Add `RentFree`, `Compressible`, `HasCompressionInfo`
2. **Add compression_info**: Add field to data structs
3. **Add compress_as**: Annotate fields for hashing
4. **Update program attribute**: Add `#[rentfree_program]`
4. **Update program attribute**: Add `#[light_program]`
5. **Add Light accounts**: Include protocol programs in accounts struct
6. **Update token handling**: Convert `mint::*` to `#[light_account(init)]`

Expand Down
6 changes: 3 additions & 3 deletions sdk-libs/macros/docs/features/light-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ pub struct CreateMint<'info> {

---

### 5. `#[rentfree_program]`
### 5. `#[light_program]`

**Purpose**: Program-level attribute that generates compression lifecycle hooks.

Expand All @@ -139,7 +139,7 @@ pub struct CreateMint<'info> {

**Example**:
```rust
#[rentfree_program]
#[light_program]
#[program]
pub mod my_program {
use super::*;
Expand Down Expand Up @@ -463,7 +463,7 @@ pub struct UserProfile {
pub compression_info: CompressionInfo,
}

#[rentfree_program]
#[light_program]
#[program]
pub mod my_program {
use super::*;
Expand Down
8 changes: 4 additions & 4 deletions sdk-libs/macros/docs/light_program/architecture.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# `#[rentfree_program]` Attribute Macro
# `#[light_program]` Attribute Macro

## 1. Overview

The `#[rentfree_program]` attribute macro provides program-level auto-discovery and instruction wrapping for Light Protocol's rent-free compression system. It eliminates boilerplate by automatically generating compression infrastructure from your existing Anchor code.
The `#[light_program]` attribute macro provides program-level auto-discovery and instruction wrapping for Light Protocol's rent-free compression system. It eliminates boilerplate by automatically generating compression infrastructure from your existing Anchor code.

**Location**: `sdk-libs/macros/src/rentfree/program/`

## 2. Required Macros

| Location | Macro | Purpose |
|----------|-------|---------|
| Program module | `#[rentfree_program]` | Discovers fields, generates instructions, wraps handlers |
| Program module | `#[light_program]` | Discovers fields, generates instructions, wraps handlers |
| Accounts struct | `#[derive(LightAccounts)]` | Generates `LightPreInit`/`LightFinalize` trait impls |
| Account field | `#[light_account(init)]` | Marks PDA for compression |
| Account field | `#[light_account(token, authority=[...])]` | Marks token account for compression |
Expand Down Expand Up @@ -39,7 +39,7 @@ The `#[rentfree_program]` attribute macro provides program-level auto-discovery
The macro reads your crate at compile time to find compressible accounts:

```
#[rentfree_program]
#[light_program]
#[program]
pub mod my_program {
pub mod accounts; <-- Macro follows this to accounts.rs
Expand Down
12 changes: 6 additions & 6 deletions sdk-libs/macros/docs/light_program/codegen.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# `#[rentfree_program]` Code Generation
# `#[light_program]` Code Generation

Technical implementation details for the `#[rentfree_program]` attribute macro.
Technical implementation details for the `#[light_program]` attribute macro.

## 1. Source Code Structure

```
sdk-libs/macros/src/rentfree/program/
|-- mod.rs # Module exports, main entry point rentfree_program_impl
|-- instructions.rs # Main orchestration: codegen(), rentfree_program_impl()
|-- mod.rs # Module exports, main entry point light_program_impl
|-- instructions.rs # Main orchestration: codegen(), light_program_impl()
|-- parsing.rs # Core types (TokenSeedSpec, SeedElement, InstructionDataSpec)
| # Expression analysis, seed conversion, function wrapping
|-- compress.rs # CompressAccountsIdempotent generation
Expand Down Expand Up @@ -44,11 +44,11 @@ sdk-libs/macros/src/rentfree/
## 2. Code Generation Flow

```
#[rentfree_program]
#[light_program]
|
v
+-----------------------------+
| rentfree_program_impl() |
| light_program_impl() |
| (instructions.rs:405) |
+-----------------------------+
|
Expand Down
40 changes: 40 additions & 0 deletions sdk-libs/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,3 +452,43 @@ pub fn light_accounts_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
into_token_stream(light_pdas::accounts::derive_light_accounts(input))
}

/// Derives PodCompressionInfoField for Pod (zero-copy) structs.
///
/// This derive macro generates the `PodCompressionInfoField` trait implementation
/// for structs that use zero-copy serialization via `bytemuck::Pod`.
///
/// ## Requirements
///
/// 1. The struct must have `#[repr(C)]` attribute for predictable field layout
/// 2. The struct must have a `compression_info: CompressionInfo` field
/// (non-optional, using `light_compressible::compression_info::CompressionInfo`)
/// 3. The struct must implement `bytemuck::Pod` and `bytemuck::Zeroable`
///
/// ## Example
///
/// ```ignore
/// use light_sdk_macros::PodCompressionInfoField;
/// use light_compressible::compression_info::CompressionInfo;
/// use bytemuck::{Pod, Zeroable};
///
/// #[derive(Clone, Copy, Pod, Zeroable, PodCompressionInfoField)]
/// #[repr(C)]
/// pub struct MyPodAccount {
/// pub owner: [u8; 32],
/// pub data: u64,
/// pub compression_info: CompressionInfo,
/// }
/// ```
///
/// ## Differences from Borsh Compression
///
/// - Pod accounts use non-optional `CompressionInfo` (compression state is indicated
/// by `config_account_version`: 0 = uninitialized, >= 1 = initialized)
/// - Uses `core::mem::offset_of!()` for compile-time offset calculation
/// - More efficient for fixed-size accounts with zero-copy serialization
#[proc_macro_derive(PodCompressionInfoField)]
pub fn pod_compression_info_field(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
into_token_stream(light_pdas::account::traits::derive_pod_compression_info_field(input))
}
6 changes: 3 additions & 3 deletions sdk-libs/macros/src/light_pdas/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ rentfree/
│ ├── mod.rs # Entry point: derive_rentfree()
│ ├── parse.rs # Parsing #[light_account(init)], #[light_account(init)] attributes
│ └── codegen.rs # LightPreInit/LightFinalize trait generation
├── program/ # #[rentfree_program] implementation
│ ├── mod.rs # Entry point: rentfree_program_impl()
├── program/ # #[light_program] implementation
│ ├── mod.rs # Entry point: light_program_impl()
│ ├── instructions.rs # Instruction generation and handler wrapping
│ ├── crate_context.rs # Crate scanning for #[derive(Accounts)] structs
│ ├── variant_enum.rs # LightAccountVariant enum generation
Expand All @@ -39,7 +39,7 @@ Implements `#[derive(LightAccounts)]` for Anchor Accounts structs:

### `program/` - RentFree Program Macro
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Update section header to match the renamed macro.

The section header still says "RentFree Program Macro," but line 42 correctly documents this as the #[light_program] attribute macro. Update the header for consistency.

📝 Suggested section header update
-### `program/` - RentFree Program Macro
+### `program/` - Light Program Macro
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### `program/` - RentFree Program Macro
### `program/` - Light Program Macro
🤖 Prompt for AI Agents
In `@sdk-libs/macros/src/light_pdas/README.md` at line 40, The section header
"RentFree Program Macro" is outdated; update it to match the renamed macro by
changing the header to reference the #[light_program] attribute macro (e.g.,
"program/ - #[light_program] Program Macro" or similar) so the header and the
subsequent documentation for the `#[light_program]` attribute macro are
consistent; edit the README's "program/" section header to reflect
#[light_program] and ensure wording matches the existing description below.


Implements `#[rentfree_program]` attribute macro:
Implements `#[light_program]` attribute macro:

- **instructions.rs** - Main macro logic, generates compress/decompress handlers
- **crate_context.rs** - Scans crate for `#[derive(Accounts)]` structs
Expand Down
Loading