Skip to main content

light_sdk/instruction/
tree_info.rs

1pub use light_compressed_account::compressed_account::{MerkleContext, PackedMerkleContext};
2use light_sdk_types::instruction::PackedAddressTreeInfo;
3
4#[cfg(not(target_os = "solana"))]
5use super::PackedAccounts;
6use crate::{AccountInfo, AnchorDeserialize, AnchorSerialize, Pubkey};
7
8#[derive(Debug, Clone, Copy, AnchorDeserialize, AnchorSerialize, PartialEq, Default)]
9pub struct AddressTreeInfo {
10    pub tree: Pubkey,
11    pub queue: Pubkey,
12}
13
14#[cfg(not(target_os = "solana"))]
15#[deprecated(since = "0.13.0", note = "please use PackedStateTreeInfo")]
16pub fn pack_merkle_contexts<'a, I>(
17    merkle_contexts: I,
18    remaining_accounts: &'a mut PackedAccounts,
19) -> impl Iterator<Item = PackedMerkleContext> + 'a
20where
21    I: Iterator<Item = &'a MerkleContext> + 'a,
22{
23    #[allow(deprecated)]
24    merkle_contexts.map(|x| pack_merkle_context(x, remaining_accounts))
25}
26
27#[cfg(not(target_os = "solana"))]
28#[deprecated(since = "0.13.0", note = "please use PackedStateTreeInfo")]
29pub fn pack_merkle_context(
30    merkle_context: &MerkleContext,
31    remaining_accounts: &mut PackedAccounts,
32) -> PackedMerkleContext {
33    let MerkleContext {
34        merkle_tree_pubkey,
35        queue_pubkey,
36        leaf_index,
37        prove_by_index,
38        ..
39    } = merkle_context;
40    let merkle_tree_pubkey_index =
41        remaining_accounts.insert_or_get(merkle_tree_pubkey.to_bytes().into());
42    let queue_pubkey_index = remaining_accounts.insert_or_get(queue_pubkey.to_bytes().into());
43
44    PackedMerkleContext {
45        merkle_tree_pubkey_index,
46        queue_pubkey_index,
47        leaf_index: *leaf_index,
48        prove_by_index: *prove_by_index,
49    }
50}
51
52/// Returns an iterator of [`PackedAddressTreeInfo`] and fills up
53/// `remaining_accounts` based on the given `merkle_contexts`.
54#[cfg(not(target_os = "solana"))]
55pub fn pack_address_tree_infos<'a>(
56    address_tree_infos: &'a [AddressTreeInfo],
57    root_index: &'a [u16],
58    remaining_accounts: &'a mut PackedAccounts,
59) -> impl Iterator<Item = PackedAddressTreeInfo> + 'a {
60    address_tree_infos
61        .iter()
62        .zip(root_index)
63        .map(move |(x, root_index)| pack_address_tree_info(x, remaining_accounts, *root_index))
64}
65
66/// Returns a [`PackedAddressTreeInfo`] and fills up `remaining_accounts`
67/// based on the given `merkle_context`.
68/// Packs Merkle tree account first.
69/// Packs queue account second.
70#[cfg(not(target_os = "solana"))]
71pub fn pack_address_tree_info(
72    address_tree_info: &AddressTreeInfo,
73    remaining_accounts: &mut PackedAccounts,
74    root_index: u16,
75) -> PackedAddressTreeInfo {
76    let AddressTreeInfo { tree, queue } = address_tree_info;
77    let address_merkle_tree_pubkey_index = remaining_accounts.insert_or_get(*tree);
78    let address_queue_pubkey_index = remaining_accounts.insert_or_get(*queue);
79
80    PackedAddressTreeInfo {
81        address_merkle_tree_pubkey_index,
82        address_queue_pubkey_index,
83        root_index,
84    }
85}
86
87pub fn unpack_address_tree_infos(
88    address_tree_infos: &[PackedAddressTreeInfo],
89    remaining_accounts: &[AccountInfo],
90) -> Vec<AddressTreeInfo> {
91    let mut result = Vec::with_capacity(address_tree_infos.len());
92    for x in address_tree_infos {
93        let address_merkle_tree_pubkey =
94            *remaining_accounts[x.address_merkle_tree_pubkey_index as usize].key;
95        let address_queue_pubkey = *remaining_accounts[x.address_queue_pubkey_index as usize].key;
96        result.push(AddressTreeInfo {
97            tree: address_merkle_tree_pubkey,
98            queue: address_queue_pubkey,
99        });
100    }
101    result
102}
103
104pub fn unpack_address_tree_info(
105    address_tree_info: PackedAddressTreeInfo,
106    remaining_accounts: &[AccountInfo],
107) -> AddressTreeInfo {
108    unpack_address_tree_infos(&[address_tree_info], remaining_accounts)[0]
109}
110
111#[cfg(test)]
112mod test {
113
114    use light_compressed_account::Pubkey;
115
116    use super::*;
117
118    #[test]
119    fn test_pack_merkle_context() {
120        let mut remaining_accounts = PackedAccounts::default();
121
122        let merkle_tree_pubkey = Pubkey::new_unique();
123        let queue_pubkey = Pubkey::new_unique();
124        let merkle_context = MerkleContext {
125            merkle_tree_pubkey,
126            queue_pubkey,
127            leaf_index: 69,
128            prove_by_index: false,
129            ..Default::default()
130        };
131
132        #[allow(deprecated)]
133        let packed_merkle_context = pack_merkle_context(&merkle_context, &mut remaining_accounts);
134        assert_eq!(
135            packed_merkle_context,
136            PackedMerkleContext {
137                merkle_tree_pubkey_index: 0,
138                queue_pubkey_index: 1,
139                leaf_index: 69,
140                prove_by_index: false,
141            }
142        )
143    }
144
145    #[test]
146    fn test_pack_merkle_contexts() {
147        let mut remaining_accounts = PackedAccounts::default();
148        use light_compressed_account::Pubkey;
149        let merkle_contexts = &[
150            MerkleContext {
151                merkle_tree_pubkey: Pubkey::new_unique(),
152                queue_pubkey: Pubkey::new_unique(),
153                leaf_index: 10,
154                prove_by_index: false,
155                ..Default::default()
156            },
157            MerkleContext {
158                merkle_tree_pubkey: Pubkey::new_unique(),
159                queue_pubkey: Pubkey::new_unique(),
160                leaf_index: 11,
161                prove_by_index: true,
162                ..Default::default()
163            },
164            MerkleContext {
165                merkle_tree_pubkey: Pubkey::new_unique(),
166                queue_pubkey: Pubkey::new_unique(),
167                leaf_index: 12,
168                prove_by_index: false,
169                ..Default::default()
170            },
171        ];
172
173        #[allow(deprecated)]
174        let packed_merkle_contexts =
175            pack_merkle_contexts(merkle_contexts.iter(), &mut remaining_accounts);
176        assert_eq!(
177            packed_merkle_contexts.collect::<Vec<_>>(),
178            &[
179                PackedMerkleContext {
180                    merkle_tree_pubkey_index: 0,
181                    queue_pubkey_index: 1,
182                    leaf_index: 10,
183                    prove_by_index: false
184                },
185                PackedMerkleContext {
186                    merkle_tree_pubkey_index: 2,
187                    queue_pubkey_index: 3,
188                    leaf_index: 11,
189                    prove_by_index: true
190                },
191                PackedMerkleContext {
192                    merkle_tree_pubkey_index: 4,
193                    queue_pubkey_index: 5,
194                    leaf_index: 12,
195                    prove_by_index: false,
196                }
197            ]
198        );
199    }
200
201    #[test]
202    fn test_pack_address_tree_info() {
203        use solana_pubkey::Pubkey;
204        let mut remaining_accounts = PackedAccounts::default();
205
206        let address_tree_info = AddressTreeInfo {
207            tree: Pubkey::new_unique(),
208            queue: Pubkey::new_unique(),
209        };
210
211        let packed_address_tree_info =
212            pack_address_tree_info(&address_tree_info, &mut remaining_accounts, 2);
213        assert_eq!(
214            packed_address_tree_info,
215            PackedAddressTreeInfo {
216                address_merkle_tree_pubkey_index: 0,
217                address_queue_pubkey_index: 1,
218                root_index: 2,
219            }
220        )
221    }
222
223    #[test]
224    fn test_pack_address_tree_infos() {
225        let mut remaining_accounts = PackedAccounts::default();
226        use solana_pubkey::Pubkey;
227        let address_tree_infos = [
228            AddressTreeInfo {
229                tree: Pubkey::new_unique(),
230                queue: Pubkey::new_unique(),
231            },
232            AddressTreeInfo {
233                tree: Pubkey::new_unique(),
234                queue: Pubkey::new_unique(),
235            },
236            AddressTreeInfo {
237                tree: Pubkey::new_unique(),
238                queue: Pubkey::new_unique(),
239            },
240        ];
241
242        let packed_address_tree_infos =
243            pack_address_tree_infos(&address_tree_infos, &[6, 7, 8], &mut remaining_accounts);
244        assert_eq!(
245            packed_address_tree_infos.collect::<Vec<_>>(),
246            &[
247                PackedAddressTreeInfo {
248                    address_merkle_tree_pubkey_index: 0,
249                    address_queue_pubkey_index: 1,
250                    root_index: 6,
251                },
252                PackedAddressTreeInfo {
253                    address_merkle_tree_pubkey_index: 2,
254                    address_queue_pubkey_index: 3,
255                    root_index: 7,
256                },
257                PackedAddressTreeInfo {
258                    address_merkle_tree_pubkey_index: 4,
259                    address_queue_pubkey_index: 5,
260                    root_index: 8,
261                }
262            ]
263        );
264    }
265}