Here's a generic State Compression protocol that allows programs to compress state up <= 300 bytes in total size (arbitrary limit imposed by transaction size when updating state).
This proposal is built on top of SRFC #16 and SRFC #13
It can be expensive to cover the cost of storing state on-chain. This is especially true for businesses that intend to cover the costs for consumers when interacting with on-chain programs.
The use of SPL Account Compression solves this, however the lack of general infrastructure to index generic usage beyond Metaplex's compressed NFTs has stagnated development.
Compressed NFTs (cNFTs) have demonstrated exponential cost savings for NFT developers and applications and we seek to expand these cost savings to all programs.
Concretely, the problem with generic indexing was that there was no way to link state data with the 32 byte hash that SPL Account compression uses to update it's internal concurrent merkle tree.
This proposal describes basic infrastructure for programs and indexers to support compression of state up to 300 bytes
by linking application data via emit_cpi!
calls with Create/Update/Deleta payloads described in sRFC #16.
This specification describes requirements around CPI events and a view function that allows indexers to render compressed state into JSON.
- Issuing compressed state
Issuing compressed state requires that program data be linked with the 32 byte hash that SPL Account Compression
instruction has in it's append
instruction.
This is done by emitting a CPI event with the following structure (CudCreate follows from SRFC #16).
Application data must fit into the data
field, which is recommended to be less than 300 bytes.
emit_cpi!(CudCreate {
/// Unique key to identify the compressed state
asset_id: Pubkey
/// Owner of the data
authority: Pubkey,
/// Additional keys to use when indexing the compressed state
pubkeys: Pubkey[],
/// The data to compress
data: Vec<u8>
})
This emission must be followed with a call to SPL Account Compression's append
instruction to be
a considered a valid issuance of compressed state & thus indexed appropriately.
Indexers can deserialize this data
field by complying with step #4.
- Updating compressed state
Updating compressed state requires both being able to recreate the old state as well as serializing the new state.
Updating compressed state requires the following payload to be emitted
emit_cpi!(CudUpdate {
/// Unique key to identify the compressed state
asset_id: Pubkey
/// Owner of the data
authority: Pubkey,
/// Additional keys to use when indexing the compressed state
pubkeys: Pubkey[],
/// Updated data to compress
data: Vec<u8>
})
This emission must be followed with a call to SPL Account Compression's replace_leaf
instruction
to be considered a valid update of compressed state & thus indexed appropriately.
- Deleting compressed state
Deleting compressed state only requires replacing existing data with [0u8; 32]
as the new leaf value.
Deleting compressed state requires the following payload to be emitted
emit_cpi!(CudDelete {
/// Unique key to identify the compressed state
asset_id: Pubkey
})
This emission must be followed with a call to SPL Account Compression's replace_leaf
instruction
with a new leaf value consisting of [0u8; 32]
to be considered a valid update of compressed state & thus indexed appropriately.
- Viewing compressed state
Application data can be shown as JSON by sending a transaction to a simulated view function on the program that has the following structure.
pub fn get_asset_data(ctx: Context<GetAssetData>, data: Vec<u8>) -> Result<()> {
// Deserialize payload data into JSON here
anchor_lang::solana_program::program::set_return_data(&json_data.as_bytes());
Ok(())
}
#[derive(Accounts)]
pub struct GetAssetData<'info> {
/// CHECK:
authority: AccountInfo<'info>,
/// CHECK:
asset_id: AccountInfo<'info>,
}
Pros:
- Cost savings for developers and users
- Indexing with SRFC #17 allows for indexing of compressed state
Cons:
- This specification currently is unable to process state that exceeds 300 bytes in a single transaction
The following program compressed-state
shows an example of a program that creates & updates compressed state
using SPL account compression.
This repo requires anchor
version >= 0.27.0, which is only available by compiling anchor
from source.
- Install TS dependencies:
yarn
- Compile
coral-xyz/anchor
onmaster
and symlink the build to./eanchor
vialn -s /path/to/anchor/target/debug|release/anchor ./eanchor
- Run the tests:
./eanchor test