account_compression/
lib.rs

1#![allow(clippy::too_many_arguments)]
2#![allow(unexpected_cfgs)]
3pub mod errors;
4pub mod instructions;
5pub use instructions::*;
6pub mod state;
7pub use state::*;
8pub mod context;
9pub mod processor;
10pub mod utils;
11use anchor_lang::prelude::*;
12use errors::AccountCompressionErrorCode;
13use light_batched_merkle_tree::{
14    initialize_address_tree::InitAddressTreeAccountsInstructionData,
15    initialize_state_tree::InitStateTreeAccountsInstructionData,
16    merkle_tree::{InstructionDataBatchAppendInputs, InstructionDataBatchNullifyInputs},
17};
18
19declare_id!("compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq");
20
21#[cfg(not(feature = "no-entrypoint"))]
22solana_security_txt::security_txt! {
23    name: "account-compression",
24    project_url: "lightprotocol.com",
25    contacts: "email:security@lightprotocol.com",
26    policy: "https://github.com/Lightprotocol/light-protocol/blob/main/SECURITY.md",
27    source_code: "https://github.com/Lightprotocol/light-protocol"
28}
29
30#[program]
31pub mod account_compression {
32
33    use super::*;
34    use crate::processor::insert_into_queues::process_insert_into_queues;
35
36    pub fn initialize_address_merkle_tree_and_queue<'info>(
37        ctx: Context<'_, '_, '_, 'info, InitializeAddressMerkleTreeAndQueue<'info>>,
38        index: u64,
39        program_owner: Option<Pubkey>,
40        forester: Option<Pubkey>,
41        address_merkle_tree_config: AddressMerkleTreeConfig,
42        address_queue_config: AddressQueueConfig,
43    ) -> Result<()> {
44        process_initialize_address_merkle_tree_and_queue(
45            ctx,
46            index,
47            program_owner,
48            forester,
49            address_merkle_tree_config,
50            address_queue_config,
51        )
52    }
53
54    /// Updates the address Merkle tree with a new address.
55    pub fn update_address_merkle_tree<'info>(
56        ctx: Context<'_, '_, '_, 'info, UpdateAddressMerkleTree<'info>>,
57        // Index of the Merkle tree changelog.
58        changelog_index: u16,
59        indexed_changelog_index: u16,
60        // Index of the address to dequeue.
61        value: u16,
62        // Low address.
63        low_address_index: u64,
64        low_address_value: [u8; 32],
65        low_address_next_index: u64,
66        // Value of the next address.
67        low_address_next_value: [u8; 32],
68        // Merkle proof for updating the low address.
69        low_address_proof: [[u8; 32]; 16],
70    ) -> Result<()> {
71        process_update_address_merkle_tree(
72            ctx,
73            changelog_index,
74            indexed_changelog_index,
75            value,
76            low_address_value,
77            low_address_next_index,
78            low_address_next_value,
79            low_address_index,
80            low_address_proof,
81        )
82    }
83
84    pub fn rollover_address_merkle_tree_and_queue<'a, 'b, 'c: 'info, 'info>(
85        ctx: Context<'a, 'b, 'c, 'info, RolloverAddressMerkleTreeAndQueue<'info>>,
86    ) -> Result<()> {
87        process_rollover_address_merkle_tree_and_queue(ctx)
88    }
89
90    /// initialize group (a group can be used to give multiple programs access
91    /// to the same Merkle trees by registering the programs to the group)
92    pub fn initialize_group_authority<'info>(
93        ctx: Context<'_, '_, '_, 'info, InitializeGroupAuthority<'info>>,
94        authority: Pubkey,
95    ) -> Result<()> {
96        let seed_pubkey = ctx.accounts.seed.key();
97        set_group_authority(
98            &mut ctx.accounts.group_authority,
99            authority,
100            Some(seed_pubkey),
101        )?;
102        Ok(())
103    }
104
105    pub fn update_group_authority<'info>(
106        ctx: Context<'_, '_, '_, 'info, UpdateGroupAuthority<'info>>,
107        authority: Pubkey,
108    ) -> Result<()> {
109        set_group_authority(&mut ctx.accounts.group_authority, authority, None)
110    }
111
112    pub fn register_program_to_group<'info>(
113        ctx: Context<'_, '_, '_, 'info, RegisterProgramToGroup<'info>>,
114    ) -> Result<()> {
115        process_register_program(ctx)
116    }
117
118    pub fn deregister_program(_ctx: Context<DeregisterProgram>) -> Result<()> {
119        Ok(())
120    }
121
122    pub fn resize_registered_program_pda<'info>(
123        ctx: Context<'_, '_, '_, 'info, ResizeRegisteredProgramPda<'info>>,
124    ) -> Result<()> {
125        process_resize_registered_program_pda(ctx)
126    }
127
128    /// Initializes a new Merkle tree from config bytes.
129    /// Index is an optional identifier and not checked by the program.
130    pub fn initialize_state_merkle_tree_and_nullifier_queue<'info>(
131        ctx: Context<'_, '_, '_, 'info, InitializeStateMerkleTreeAndNullifierQueue<'info>>,
132        index: u64,
133        program_owner: Option<Pubkey>,
134        forester: Option<Pubkey>,
135        state_merkle_tree_config: StateMerkleTreeConfig,
136        nullifier_queue_config: NullifierQueueConfig,
137        // additional rent for the cpi context account
138        // so that it can be rolled over as well
139        additional_bytes: u64,
140    ) -> Result<()> {
141        if additional_bytes != 0 {
142            msg!("additional_bytes is not supported yet");
143            return err!(AccountCompressionErrorCode::UnsupportedAdditionalBytes);
144        }
145        process_initialize_state_merkle_tree_and_nullifier_queue(
146            ctx,
147            index,
148            program_owner,
149            forester,
150            state_merkle_tree_config,
151            nullifier_queue_config,
152            additional_bytes,
153        )
154    }
155
156    /// Inserts nullifiers, leaves, and addresses
157    /// into v1 and batched Merkle trees.
158    pub fn insert_into_queues<'a, 'b, 'c: 'info, 'info>(
159        ctx: Context<'a, 'b, 'c, 'info, GenericInstruction<'info>>,
160        bytes: Vec<u8>,
161    ) -> Result<()> {
162        process_insert_into_queues(&ctx, bytes)
163    }
164
165    pub fn nullify_leaves<'a, 'b, 'c: 'info, 'info>(
166        ctx: Context<'a, 'b, 'c, 'info, NullifyLeaves<'info>>,
167        change_log_indices: Vec<u64>,
168        leaves_queue_indices: Vec<u16>,
169        leaf_indices: Vec<u64>,
170        proofs: Vec<Vec<[u8; 32]>>,
171    ) -> Result<()> {
172        process_nullify_leaves(
173            &ctx,
174            &change_log_indices,
175            &leaves_queue_indices,
176            &leaf_indices,
177            &proofs,
178        )
179    }
180
181    pub fn rollover_state_merkle_tree_and_nullifier_queue<'a, 'b, 'c: 'info, 'info>(
182        ctx: Context<'a, 'b, 'c, 'info, RolloverStateMerkleTreeAndNullifierQueue<'info>>,
183    ) -> Result<()> {
184        process_rollover_state_merkle_tree_nullifier_queue_pair(ctx)
185    }
186
187    /// Initialize a batched state Merkle tree account and
188    /// an output queue account.
189    /// 1. append output state
190    ///     State is first inserted into the output queue with
191    ///     the instruction append_leaves_to_merkle_trees.
192    /// 2. batch append
193    ///     Leaves are inserted from the output queue into the
194    ///     state Merkle tree with the instruction batch_append.
195    /// 3. nullify (input) state
196    ///     State is nullified by inserting nullifiers into the
197    ///     input queue (part of the Merkle tree account).
198    ///     Nullifiers are inserted with the instruction
199    ///     insert_into_nullifier_queues.
200    /// 4. batch nullify
201    ///    Nullifiers are inserted from the input queue into the
202    ///    state Merkle tree with the instruction batch_nullify.
203    pub fn initialize_batched_state_merkle_tree<'info>(
204        ctx: Context<'_, '_, '_, 'info, InitializeBatchedStateMerkleTreeAndQueue<'info>>,
205        bytes: Vec<u8>,
206    ) -> Result<()> {
207        let params = InitStateTreeAccountsInstructionData::try_from_slice(&bytes)
208            .map_err(|_| AccountCompressionErrorCode::InputDeserializationFailed)?;
209        process_initialize_batched_state_merkle_tree(ctx, params)
210    }
211
212    /// Initialize a batched address Merkle tree account.
213    /// A batched address Merkle tree is an indexed Merkle tree.
214    /// Addresses are first inserted into a queue and inserted into
215    /// the indexed Merkle tree in batches with a zkp.
216    /// The queue is part of the address Merkle tree account.
217    /// 1. queue addresses
218    ///     Addresses are inserted into the queue with the instruction
219    ///     insert_addresses.
220    /// 2. update address tree
221    ///     The address tree is updated with the instruction
222    ///     batch_update_address_tree.
223    pub fn initialize_batched_address_merkle_tree<'info>(
224        ctx: Context<'_, '_, '_, 'info, InitializeBatchedAddressMerkleTree<'info>>,
225        bytes: Vec<u8>,
226    ) -> Result<()> {
227        let params = InitAddressTreeAccountsInstructionData::try_from_slice(&bytes)
228            .map_err(|_| AccountCompressionErrorCode::InputDeserializationFailed)?;
229        process_initialize_batched_address_merkle_tree(ctx, params)
230    }
231
232    /// Nullify a batch of leaves from the input queue
233    /// to a batched Merkle tree with a zkp.
234    pub fn batch_nullify<'a, 'b, 'c: 'info, 'info>(
235        ctx: Context<'a, 'b, 'c, 'info, BatchNullify<'info>>,
236        data: Vec<u8>,
237    ) -> Result<()> {
238        let instruction_data = InstructionDataBatchNullifyInputs::try_from_slice(&data)
239            .map_err(|_| AccountCompressionErrorCode::InputDeserializationFailed)?;
240        process_batch_nullify(&ctx, instruction_data)
241    }
242
243    /// Append a batch of leaves from an output queue
244    /// to a batched Merkle tree with a zkp.
245    pub fn batch_append<'a, 'b, 'c: 'info, 'info>(
246        ctx: Context<'a, 'b, 'c, 'info, BatchAppend<'info>>,
247        data: Vec<u8>,
248    ) -> Result<()> {
249        let instruction_data = InstructionDataBatchAppendInputs::try_from_slice(&data)
250            .map_err(|_| AccountCompressionErrorCode::InputDeserializationFailed)?;
251        process_batch_append_leaves(&ctx, instruction_data)
252    }
253
254    /// Insert a batch of addresses into a
255    /// batched address Merkle tree with a zkp.
256    pub fn batch_update_address_tree<'a, 'b, 'c: 'info, 'info>(
257        ctx: Context<'a, 'b, 'c, 'info, BatchUpdateAddressTree<'info>>,
258        data: Vec<u8>,
259    ) -> Result<()> {
260        let instruction_data = InstructionDataBatchNullifyInputs::try_from_slice(&data)
261            .map_err(|_| AccountCompressionErrorCode::InputDeserializationFailed)?;
262        process_batch_update_address_tree(&ctx, instruction_data)
263    }
264
265    /// Rollover batched address Merkle tree.
266    /// Rollover means creating a new Merkle tree accounts
267    /// with the parameters of the old account.
268    /// Rent is reimbursed from the old account to the payer.
269    pub fn rollover_batched_address_merkle_tree<'a, 'b, 'c: 'info, 'info>(
270        ctx: Context<'a, 'b, 'c, 'info, RolloverBatchedAddressMerkleTree<'info>>,
271        network_fee: Option<u64>,
272    ) -> Result<()> {
273        process_rollover_batched_address_merkle_tree(ctx, network_fee)
274    }
275
276    /// Rollover batched state Merkle tree.
277    /// Rollover means creating new queue and Merkle tree accounts
278    /// with the parameters of the old accounts.
279    /// Rent is reimbursed from the old output queue account to the payer.
280    pub fn rollover_batched_state_merkle_tree<'a, 'b, 'c: 'info, 'info>(
281        ctx: Context<'a, 'b, 'c, 'info, RolloverBatchedStateMerkleTree<'info>>,
282        additional_bytes: u64,
283        network_fee: Option<u64>,
284    ) -> Result<()> {
285        process_rollover_batched_state_merkle_tree(ctx, additional_bytes, network_fee)
286    }
287
288    /// Migrate state from a v1 state Merkle tree
289    /// to a v2 state Merkle tree.
290    pub fn migrate_state<'a, 'b, 'c: 'info, 'info>(
291        ctx: Context<'a, 'b, 'c, 'info, MigrateState<'info>>,
292        input: MigrateLeafParams,
293    ) -> Result<()> {
294        process_migrate_state(&ctx, input)
295    }
296}