Compressed Account Model
Overview to compressed accounts and comparison to Solana accounts.
Overview
Compressed accounts store state and are similar to regular Solana accounts but with five main differences:
Each compressed account can be identified by its hash
Each write to a compressed account changes its hash
An
addresscan optionally be set as a permanent unique ID of the compressed account.All compressed accounts are stored in sparse state trees. Only the tree's state root (i.e., a small fingerprint of all compressed accounts) is stored in the on-chain account space.
These differences make compressed accounts rent-free and allow the protocol to store state as calldata on the Solana ledger instead of the costly on-chain account space.
In a Nutshell
Transactions can use compressed account data inside Solana's virtual machine as if it were stored on-chain by combining state compression and zero-knowledge proofs:
Millions of compressed accounts are stored as hashes in Merkle tree leaves
All accounts stored in a Merkle tree are compressed into a single root hash
The root hash is stored in one Solana account for cryptographic verification
Compressed account state is recorded on the Solana ledger
The latest compressed account state is fetched from your RPC provider
Compressed account state is verified against the on-chain root hash with a validity proof
Merkle trees are provided by the protocol and Indexers generate validity proofs.
Developers don't configure state Merkle trees or generate validity proofs.
You will learn more about Merkle trees and validity proofs in the next section.
Compressed Account Structure
Compressed accounts include the core Solana account fields (owner, lamports, data) plus additional fields to index and store compressed state.
pub struct CompressedAccount {
pub address: Option<[u8; 32]>, // Optional persistent identifier
pub data: Option<CompressedAccountData>, // Account data
pub hash: [u8; 32], // Unique account hash
pub lamports: u64, // Account balance
pub owner: Pubkey, // Program that owns this account
}Address and Hash
Each compressed account can be identified by its hash, regardless of whether it has an address. By definition, whenever any data of a compressed account changes, its hash changes.
An address can serve as optional and additional persistent identifier.
It's represented as 32 bytes in the format of a
PublicKey.Addresses are optional, since ensuring that the address of a new account is unique incurs additional computational overhead.
Compressed Account Address Derivation
Compressed account addresses are derived similar to PDAs.
Like PDAs, compressed account addresses don't belong to a private key; rather, they're derived from the program that owns them.
The key difference to regular PDAs is that compressed accounts require an address tree parameter.
Address Merkle tree's store addresses of compressed accounts and ensure its uniqueness.
const seed = deriveAddressSeed(
[customSeed, signer.publicKey.toBytes()],
new web3.PublicKey(programId),
);
const address = deriveAddress(seed, addressTree);let (address, _) = derive_address(
&[b"custom_seed", keypair.pubkey().as_ref()],
&address_tree_info.tree,
&your_program::ID,
);Data Field
The data field contains the compressed account's program state:
pub struct CompressedAccountData {
pub discriminator: [u8; 8], // Type identifier for account data
pub data: Vec<u8>, // Serialized program state
pub data_hash: [u8; 32], // Hash of the data field
}discriminator: Identifies the data type for programs to correctly deserialize account data. Similar to Anchor's 8-byte account discriminator.data: Stores the account's current state as arbitrary bytes (e.g., serialized user data, balances, metadata).Compressed accounts have no fixed maximum size to store data like Solana's 10 MB.
Still, Solana's 1,232-byte transaction limit constrains practical data size to roughly 1 KB per account.
data_hash: Hash of thedatafield (32 bytes).When computing the compressed account hash for the state tree, the protocol uses this fixed-size hash instead of the variable-length data bytes.
Next Steps
Learn about the role of validity proofs and Merkle trees in the protocol.
Merkle Trees and Validity ProofsLast updated
Was this helpful?