Skip to main content

light_client/indexer/types/
tree.rs

1use light_account::PackedAccounts;
2use light_compressed_account::TreeType;
3use solana_pubkey::Pubkey;
4
5use super::super::{
6    base58::{decode_base58_option_to_pubkey, decode_base58_to_fixed_array},
7    IndexerError,
8};
9
10#[derive(Clone, Copy, Default, Debug, PartialEq)]
11pub struct NextTreeInfo {
12    pub cpi_context: Option<Pubkey>,
13    pub queue: Pubkey,
14    pub tree: Pubkey,
15    pub tree_type: TreeType,
16}
17
18impl NextTreeInfo {
19    /// Get the index of the output tree in the packed accounts.
20    /// For StateV1, it returns the index of the tree account.
21    /// For StateV2, it returns the index of the queue account.
22    /// (For V2 trees new state is inserted into the output queue.
23    /// The forester updates the tree from the queue asynchronously.)
24    pub fn pack_output_tree_index(
25        &self,
26        packed_accounts: &mut PackedAccounts,
27    ) -> Result<u8, IndexerError> {
28        match self.tree_type {
29            TreeType::StateV1 => Ok(packed_accounts.insert_or_get(self.tree)),
30            TreeType::StateV2 => Ok(packed_accounts.insert_or_get(self.queue)),
31            _ => Err(IndexerError::InvalidPackTreeType),
32        }
33    }
34    pub fn from_api_model(
35        value: &photon_api::types::TreeContextInfo,
36    ) -> Result<Self, IndexerError> {
37        Self::try_from(value)
38    }
39}
40
41impl TryFrom<&photon_api::types::TreeContextInfo> for NextTreeInfo {
42    type Error = IndexerError;
43
44    fn try_from(value: &photon_api::types::TreeContextInfo) -> Result<Self, Self::Error> {
45        Ok(Self {
46            tree_type: TreeType::from(value.tree_type as u64),
47            tree: Pubkey::new_from_array(decode_base58_to_fixed_array(&value.tree)?),
48            queue: Pubkey::new_from_array(decode_base58_to_fixed_array(&value.queue)?),
49            cpi_context: decode_base58_option_to_pubkey(&value.cpi_context)?,
50        })
51    }
52}
53
54#[derive(Clone, Copy, Default, Debug, PartialEq)]
55pub struct TreeInfo {
56    pub cpi_context: Option<Pubkey>,
57    pub next_tree_info: Option<NextTreeInfo>,
58    pub queue: Pubkey,
59    pub tree: Pubkey,
60    pub tree_type: TreeType,
61}
62
63impl TreeInfo {
64    /// Get the index of the output tree in the packed accounts.
65    /// For StateV1, it returns the index of the tree account.
66    /// For StateV2, it returns the index of the queue account.
67    /// (For V2 trees new state is inserted into the output queue.
68    /// The forester updates the tree from the queue asynchronously.)
69    pub fn pack_output_tree_index(
70        &self,
71        packed_accounts: &mut PackedAccounts,
72    ) -> Result<u8, IndexerError> {
73        match self.tree_type {
74            TreeType::StateV1 => Ok(packed_accounts.insert_or_get(self.tree)),
75            TreeType::StateV2 => Ok(packed_accounts.insert_or_get(self.queue)),
76            _ => Err(IndexerError::InvalidPackTreeType),
77        }
78    }
79
80    pub fn get_output_pubkey(&self) -> Result<Pubkey, IndexerError> {
81        match self.tree_type {
82            TreeType::StateV1 => Ok(self.tree),
83            TreeType::StateV2 => Ok(self.queue),
84            _ => Err(IndexerError::InvalidPackTreeType),
85        }
86    }
87
88    pub fn from_api_model(
89        value: &photon_api::types::MerkleContextV2,
90    ) -> Result<Self, IndexerError> {
91        Ok(Self {
92            tree_type: TreeType::from(value.tree_type as u64),
93            tree: Pubkey::new_from_array(decode_base58_to_fixed_array(&value.tree)?),
94            queue: Pubkey::new_from_array(decode_base58_to_fixed_array(&value.queue)?),
95            cpi_context: decode_base58_option_to_pubkey(&value.cpi_context)?,
96            next_tree_info: value
97                .next_tree_context
98                .as_ref()
99                .map(NextTreeInfo::from_api_model)
100                .transpose()?,
101        })
102    }
103
104    pub fn to_light_merkle_context(
105        &self,
106        leaf_index: u32,
107        prove_by_index: bool,
108    ) -> light_compressed_account::compressed_account::MerkleContext {
109        use light_compressed_account::Pubkey;
110        light_compressed_account::compressed_account::MerkleContext {
111            merkle_tree_pubkey: Pubkey::new_from_array(self.tree.to_bytes()),
112            queue_pubkey: Pubkey::new_from_array(self.queue.to_bytes()),
113            leaf_index,
114            tree_type: self.tree_type,
115            prove_by_index,
116        }
117    }
118}
119
120#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
121pub struct StateMerkleTreeAccounts {
122    pub merkle_tree: Pubkey,
123    pub nullifier_queue: Pubkey,
124    pub cpi_context: Pubkey,
125    pub tree_type: TreeType,
126}
127
128#[allow(clippy::from_over_into)]
129impl Into<TreeInfo> for StateMerkleTreeAccounts {
130    fn into(self) -> TreeInfo {
131        TreeInfo {
132            tree: self.merkle_tree,
133            queue: self.nullifier_queue,
134            cpi_context: Some(self.cpi_context),
135            tree_type: self.tree_type,
136            next_tree_info: None,
137        }
138    }
139}
140
141#[derive(Debug, Clone, Copy)]
142pub struct AddressMerkleTreeAccounts {
143    pub merkle_tree: Pubkey,
144    pub queue: Pubkey,
145}