Thanks to visit codestin.com
Credit goes to lib.rs

12 breaking releases

new 0.18.0 Jan 20, 2026
0.17.1 Dec 7, 2025
0.16.0 Oct 24, 2025
0.13.0 Jun 15, 2025
0.3.0 Jul 23, 2024

#6 in #account-address

Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App Codestin Search App

815 downloads per month
Used in 9 crates (8 directly)

Apache-2.0

1MB
18K SLoC

Light SDK

Rust SDK with helpers to interact with ZK Compression on Solana.

Documentation is available at https://zkcompression.com

Source code: https://github.com/Lightprotocol/light-protocol/tree/main/programs/system

Audit

This code is unaudited. Use at your own risk.


lib.rs:

The base library to use Compressed Accounts in Solana on-chain Rust and Anchor programs.

Compressed Accounts store state as account hashes in State Merkle trees. and unique addresses in Address Merkle trees. Validity proofs (zero-knowledge proofs) verify that compressed account state exists and new addresses do not exist yet.

  • No rent exemption payment required.
  • Constant 128-byte validity proof per transaction for one or multiple compressed accounts and addresses.
  • Compressed account data is sent as instruction data when accessed.
  • State and address trees are managed by the protocol.

For full program examples, see the Program Examples. For detailed documentation, visit zkcompression.com. For pinocchio solana program development see light-sdk-pinocchio. For rust client development see light-client. For rust program testing see light-program-test. For local test validator with light system programs see Light CLI.

Using Compressed Accounts in Solana Programs

  1. Instruction
    • CompressedAccountMeta - Compressed account metadata structs for instruction data.
    • PackedAccounts - Abstraction to prepare accounts offchain for instructions with compressed accounts.
    • ValidityProof - Proves that new addresses don't exist yet, and compressed account state exists.
  2. Compressed Account in Program
  3. Cpi

Client Program Interaction Flow

 ├─ 𝐂𝐥𝐢𝐞𝐧𝐭
 │  ├─ Get ValidityProof from RPC.
 │  ├─ pack accounts with PackedAccounts into PackedAddressTreeInfo and PackedStateTreeInfo.
 │  ├─ pack CompressedAccountMeta.
 │  ├─ Build Instruction from PackedAccounts and CompressedAccountMetas.
 │  └─ Send transaction.
 │
 └─ 𝐂𝐮𝐬𝐭𝐨𝐦 𝐏𝐫𝐨𝐠𝐫𝐚𝐦
    ├─ CpiAccounts parse accounts consistent with PackedAccounts.
    ├─ LightAccount instantiates from CompressedAccountMeta.
    │
    └─ 𝐋𝐢𝐠𝐡𝐭 𝐒𝐲𝐬𝐭𝐞𝐦 𝐏𝐫𝐨𝐠𝐫𝐚𝐦 𝐂𝐏𝐈
       ├─ Verify ValidityProof.
       ├─ Update State Merkle tree.
       ├─ Update Address Merkle tree.
       └─ Complete atomic state transition.

Features

  1. anchor - Derives AnchorSerialize, AnchorDeserialize instead of BorshSerialize, BorshDeserialize.

  2. v2

    • available on devnet, localnet, and light-program-test.
    • Support for optimized v2 light system program instructions.
  3. cpi-context - Enables CPI context operations for batched compressed account operations.

    • available on devnet, localnet, and light-program-test.
    • Enables the use of one validity proof across multiple cpis from different programs in one instruction.
    • For example spending compressed tokens (owned by the ctoken program) and updating a compressed pda (owned by a custom program) with one validity proof.
    • An instruction should not use more than one validity proof.
    • Requires the v2 feature.

Example Solana program code to create a compressed account

use anchor_lang::{prelude::*, Discriminator};
use light_sdk::{
    account::LightAccount,
    address::v1::derive_address,
    cpi::{v1::LightSystemProgramCpi, CpiAccounts, InvokeLightSystemProgram, LightCpiInstruction},
    derive_light_cpi_signer,
    instruction::{account_meta::CompressedAccountMeta, PackedAddressTreeInfo},
    CpiSigner, LightDiscriminator, LightHasher, ValidityProof,
};

declare_id!("2tzfijPBGbrR5PboyFUFKzfEoLTwdDSHUjANCw929wyt");

pub const LIGHT_CPI_SIGNER: CpiSigner =
    derive_light_cpi_signer!("2tzfijPBGbrR5PboyFUFKzfEoLTwdDSHUjANCw929wyt");

#[program]
pub mod counter {

    use super::*;

    pub fn create_compressed_account<'info>(
        ctx: Context<'_, '_, '_, 'info, CreateCompressedAccount<'info>>,
        proof: ValidityProof,
        address_tree_info: PackedAddressTreeInfo,
        output_tree_index: u8,
    ) -> Result<()> {
        let light_cpi_accounts = CpiAccounts::new(
            ctx.accounts.fee_payer.as_ref(),
            ctx.remaining_accounts,
            crate::LIGHT_CPI_SIGNER,
        )?;

        let (address, address_seed) = derive_address(
            &[b"counter", ctx.accounts.fee_payer.key().as_ref()],
            &address_tree_info.get_tree_pubkey(&light_cpi_accounts)?,
            &crate::ID,
        );
        let new_address_params = address_tree_info
            .into_new_address_params_packed(address_seed);

        let mut my_compressed_account = LightAccount::<CounterAccount>::new_init(
            &crate::ID,
            Some(address),
            output_tree_index,
        );

        my_compressed_account.owner = ctx.accounts.fee_payer.key();

        LightSystemProgramCpi::new_cpi(crate::LIGHT_CPI_SIGNER, proof)
            .with_light_account(my_compressed_account)?
            .with_new_addresses(&[new_address_params])
            .invoke(light_cpi_accounts)
    }
}

#[derive(Accounts)]
pub struct CreateCompressedAccount<'info> {
   #[account(mut)]
   pub fee_payer: Signer<'info>,
}

#[derive(Clone, Debug, Default, LightDiscriminator)]
pub struct CounterAccount {
   pub owner: Pubkey,
   pub counter: u64
}

Dependencies

~9–14MB
~284K SLoC