light_compressed_account/instruction_data/
data.rs

1use std::collections::HashMap;
2
3use light_zero_copy::ZeroCopyMut;
4
5use crate::{
6    compressed_account::{CompressedAccount, PackedCompressedAccountWithMerkleContext},
7    discriminators::DISCRIMINATOR_INVOKE,
8    instruction_data::{compressed_proof::CompressedProof, traits::LightInstructionData},
9    AnchorDeserialize, AnchorSerialize, InstructionDiscriminator, Pubkey,
10};
11
12#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
13pub struct InstructionDataInvoke {
14    pub proof: Option<CompressedProof>,
15    pub input_compressed_accounts_with_merkle_context:
16        Vec<PackedCompressedAccountWithMerkleContext>,
17    pub output_compressed_accounts: Vec<OutputCompressedAccountWithPackedContext>,
18    pub relay_fee: Option<u64>,
19    pub new_address_params: Vec<NewAddressParamsPacked>,
20    pub compress_or_decompress_lamports: Option<u64>,
21    pub is_compress: bool,
22}
23
24impl InstructionDataInvoke {
25    pub fn new(proof: Option<CompressedProof>) -> Self {
26        Self {
27            proof,
28            ..Default::default()
29        }
30    }
31
32    pub fn with_input_compressed_accounts_with_merkle_context(
33        mut self,
34        input_compressed_accounts_with_merkle_context: &[PackedCompressedAccountWithMerkleContext],
35    ) -> Self {
36        if !input_compressed_accounts_with_merkle_context.is_empty() {
37            self.input_compressed_accounts_with_merkle_context
38                .extend_from_slice(input_compressed_accounts_with_merkle_context);
39        }
40        self
41    }
42
43    pub fn with_output_compressed_accounts(
44        mut self,
45        output_compressed_accounts: &[OutputCompressedAccountWithPackedContext],
46    ) -> Self {
47        if !output_compressed_accounts.is_empty() {
48            self.output_compressed_accounts
49                .extend_from_slice(output_compressed_accounts);
50        }
51        self
52    }
53
54    pub fn with_new_addresses(mut self, new_address_params: &[NewAddressParamsPacked]) -> Self {
55        if !new_address_params.is_empty() {
56            self.new_address_params
57                .extend_from_slice(new_address_params);
58        }
59        self
60    }
61
62    pub fn compress_lamports(mut self, lamports: u64) -> Self {
63        self.compress_or_decompress_lamports = Some(lamports);
64        self.is_compress = true;
65        self
66    }
67
68    pub fn decompress_lamports(mut self, lamports: u64) -> Self {
69        self.compress_or_decompress_lamports = Some(lamports);
70        self.is_compress = false;
71        self
72    }
73}
74
75impl InstructionDiscriminator for InstructionDataInvoke {
76    fn discriminator(&self) -> &'static [u8] {
77        &DISCRIMINATOR_INVOKE
78    }
79}
80
81impl LightInstructionData for InstructionDataInvoke {}
82
83#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
84pub struct OutputCompressedAccountWithContext {
85    pub compressed_account: CompressedAccount,
86    pub merkle_tree: Pubkey,
87}
88
89#[repr(C)]
90#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize, ZeroCopyMut)]
91pub struct OutputCompressedAccountWithPackedContext {
92    pub compressed_account: CompressedAccount,
93    pub merkle_tree_index: u8,
94}
95
96#[repr(C)]
97#[derive(
98    Debug, PartialEq, Default, Clone, Copy, AnchorDeserialize, AnchorSerialize, ZeroCopyMut,
99)]
100pub struct NewAddressParamsPacked {
101    pub seed: [u8; 32],
102    pub address_queue_account_index: u8,
103    pub address_merkle_tree_account_index: u8,
104    pub address_merkle_tree_root_index: u16,
105}
106
107#[repr(C)]
108#[derive(
109    Debug, PartialEq, Default, Clone, Copy, AnchorDeserialize, AnchorSerialize, ZeroCopyMut,
110)]
111pub struct NewAddressParamsAssignedPacked {
112    pub seed: [u8; 32],
113    pub address_queue_account_index: u8,
114    pub address_merkle_tree_account_index: u8,
115    pub address_merkle_tree_root_index: u16,
116    pub assigned_to_account: bool,
117    pub assigned_account_index: u8,
118}
119
120impl NewAddressParamsAssignedPacked {
121    pub fn new(address_params: NewAddressParamsPacked, index: Option<u8>) -> Self {
122        Self {
123            seed: address_params.seed,
124            address_queue_account_index: address_params.address_queue_account_index,
125            address_merkle_tree_account_index: address_params.address_merkle_tree_account_index,
126            address_merkle_tree_root_index: address_params.address_merkle_tree_root_index,
127            assigned_to_account: index.is_some(),
128            assigned_account_index: index.unwrap_or_default(),
129        }
130    }
131
132    pub fn assigned_account_index(&self) -> Option<u8> {
133        if self.assigned_to_account {
134            Some(self.assigned_account_index)
135        } else {
136            None
137        }
138    }
139}
140
141#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
142pub struct NewAddressParams {
143    pub seed: [u8; 32],
144    pub address_queue_pubkey: Pubkey,
145    pub address_merkle_tree_pubkey: Pubkey,
146    pub address_merkle_tree_root_index: u16,
147}
148
149#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
150pub struct NewAddressParamsAssigned {
151    pub seed: [u8; 32],
152    pub address_queue_pubkey: Pubkey,
153    pub address_merkle_tree_pubkey: Pubkey,
154    pub address_merkle_tree_root_index: u16,
155    pub assigned_account_index: Option<u8>,
156}
157
158#[repr(C)]
159#[derive(
160    Debug, PartialEq, Default, Clone, Copy, AnchorDeserialize, AnchorSerialize, ZeroCopyMut,
161)]
162pub struct PackedReadOnlyAddress {
163    pub address: [u8; 32],
164    pub address_merkle_tree_root_index: u16,
165    pub address_merkle_tree_account_index: u8,
166}
167
168#[derive(Debug, PartialEq, Default, Clone, AnchorDeserialize, AnchorSerialize)]
169pub struct ReadOnlyAddress {
170    pub address: [u8; 32],
171    pub address_merkle_tree_pubkey: Pubkey,
172    pub address_merkle_tree_root_index: u16,
173}
174// TODO: move
175pub fn pack_pubkey(pubkey: &Pubkey, hash_set: &mut HashMap<Pubkey, u8>) -> u8 {
176    match hash_set.get(pubkey) {
177        Some(index) => *index,
178        None => {
179            let index = hash_set.len() as u8;
180            hash_set.insert(*pubkey, index);
181            index
182        }
183    }
184}
185
186pub fn pack_pubkey_usize(pubkey: &Pubkey, hash_set: &mut HashMap<Pubkey, usize>) -> u8 {
187    match hash_set.get(pubkey) {
188        Some(index) => (*index) as u8,
189        None => {
190            let index = hash_set.len();
191            hash_set.insert(*pubkey, index);
192            index as u8
193        }
194    }
195}