mpl_account_compression/state/
concurrent_merkle_tree_header.rs1use anchor_lang::prelude::*;
2use borsh::{BorshDeserialize, BorshSerialize};
3
4use spl_concurrent_merkle_tree::concurrent_merkle_tree::ConcurrentMerkleTree;
5use std::mem::size_of;
6
7use crate::error::AccountCompressionError;
8
9pub const CONCURRENT_MERKLE_TREE_HEADER_SIZE_V1: usize = 2 + 54;
10
11#[derive(Debug, Copy, Clone, PartialEq, BorshDeserialize, BorshSerialize)]
12#[repr(u8)]
13pub enum CompressionAccountType {
14 Uninitialized,
16
17 ConcurrentMerkleTree,
19}
20
21impl std::fmt::Display for CompressionAccountType {
22 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
23 write!(f, "{:?}", &self)
24 }
25}
26
27#[cfg(feature = "idl-build")]
28impl anchor_lang::IdlBuild for CompressionAccountType {}
29
30#[repr(C)]
43#[derive(AnchorDeserialize, AnchorSerialize)]
44pub struct ConcurrentMerkleTreeHeader {
45 pub account_type: CompressionAccountType,
47 pub header: ConcurrentMerkleTreeHeaderData,
49}
50
51#[repr(C)]
52#[derive(AnchorDeserialize, AnchorSerialize)]
53pub struct ConcurrentMerkleTreeHeaderDataV1 {
54 max_buffer_size: u32,
57
58 max_depth: u32,
62
63 authority: Pubkey,
66
67 creation_slot: u64,
70
71 _padding: [u8; 6],
74}
75
76#[repr(C)]
77#[derive(AnchorDeserialize, AnchorSerialize)]
78pub enum ConcurrentMerkleTreeHeaderData {
79 V1(ConcurrentMerkleTreeHeaderDataV1),
80}
81
82impl ConcurrentMerkleTreeHeader {
83 pub fn initialize(
84 &mut self,
85 max_depth: u32,
86 max_buffer_size: u32,
87 authority: &Pubkey,
88 creation_slot: u64,
89 ) {
90 self.account_type = CompressionAccountType::ConcurrentMerkleTree;
91
92 match self.header {
93 ConcurrentMerkleTreeHeaderData::V1(ref mut header) => {
94 assert_eq!(header.max_buffer_size, 0);
96 assert_eq!(header.max_depth, 0);
97 header.max_buffer_size = max_buffer_size;
98 header.max_depth = max_depth;
99 header.authority = *authority;
100 header.creation_slot = creation_slot;
101 }
102 }
103 }
104
105 pub fn get_max_depth(&self) -> u32 {
106 match &self.header {
107 ConcurrentMerkleTreeHeaderData::V1(header) => header.max_depth,
108 }
109 }
110
111 pub fn get_max_buffer_size(&self) -> u32 {
112 match &self.header {
113 ConcurrentMerkleTreeHeaderData::V1(header) => header.max_buffer_size,
114 }
115 }
116
117 pub fn get_creation_slot(&self) -> u64 {
118 match &self.header {
119 ConcurrentMerkleTreeHeaderData::V1(header) => header.creation_slot,
120 }
121 }
122
123 pub fn set_new_authority(&mut self, new_authority: &Pubkey) {
124 match self.header {
125 ConcurrentMerkleTreeHeaderData::V1(ref mut header) => {
126 header.authority = new_authority.clone();
127 msg!("Authority transferred to: {:?}", header.authority);
128 }
129 }
130 }
131
132 pub fn assert_valid(&self) -> Result<()> {
133 require_eq!(
134 self.account_type,
135 CompressionAccountType::ConcurrentMerkleTree,
136 AccountCompressionError::IncorrectAccountType,
137 );
138 Ok(())
139 }
140
141 pub fn assert_valid_authority(&self, expected_authority: &Pubkey) -> Result<()> {
142 self.assert_valid()?;
143 match &self.header {
144 ConcurrentMerkleTreeHeaderData::V1(header) => {
145 require_eq!(
146 header.authority,
147 *expected_authority,
148 AccountCompressionError::IncorrectAuthority,
149 );
150 }
151 }
152 Ok(())
153 }
154
155 pub fn assert_valid_leaf_index(&self, leaf_index: u32) -> Result<()> {
156 if leaf_index >= (1 << self.get_max_depth()) {
157 return Err(AccountCompressionError::LeafIndexOutOfBounds.into());
158 }
159 Ok(())
160 }
161}
162
163pub fn merkle_tree_get_size(header: &ConcurrentMerkleTreeHeader) -> Result<usize> {
164 match (header.get_max_depth(), header.get_max_buffer_size()) {
166 (3, 8) => Ok(size_of::<ConcurrentMerkleTree<3, 8>>()),
167 (5, 8) => Ok(size_of::<ConcurrentMerkleTree<5, 8>>()),
168 (6, 16) => Ok(size_of::<ConcurrentMerkleTree<6, 16>>()),
169 (7, 16) => Ok(size_of::<ConcurrentMerkleTree<7, 16>>()),
170 (8, 16) => Ok(size_of::<ConcurrentMerkleTree<8, 16>>()),
171 (9, 16) => Ok(size_of::<ConcurrentMerkleTree<9, 16>>()),
172 (10, 32) => Ok(size_of::<ConcurrentMerkleTree<10, 32>>()),
173 (11, 32) => Ok(size_of::<ConcurrentMerkleTree<11, 32>>()),
174 (12, 32) => Ok(size_of::<ConcurrentMerkleTree<12, 32>>()),
175 (13, 32) => Ok(size_of::<ConcurrentMerkleTree<13, 32>>()),
176 (14, 64) => Ok(size_of::<ConcurrentMerkleTree<14, 64>>()),
177 (14, 256) => Ok(size_of::<ConcurrentMerkleTree<14, 256>>()),
178 (14, 1024) => Ok(size_of::<ConcurrentMerkleTree<14, 1024>>()),
179 (14, 2048) => Ok(size_of::<ConcurrentMerkleTree<14, 2048>>()),
180 (15, 64) => Ok(size_of::<ConcurrentMerkleTree<15, 64>>()),
181 (16, 64) => Ok(size_of::<ConcurrentMerkleTree<16, 64>>()),
182 (17, 64) => Ok(size_of::<ConcurrentMerkleTree<17, 64>>()),
183 (18, 64) => Ok(size_of::<ConcurrentMerkleTree<18, 64>>()),
184 (19, 64) => Ok(size_of::<ConcurrentMerkleTree<19, 64>>()),
185 (20, 64) => Ok(size_of::<ConcurrentMerkleTree<20, 64>>()),
186 (20, 256) => Ok(size_of::<ConcurrentMerkleTree<20, 256>>()),
187 (20, 1024) => Ok(size_of::<ConcurrentMerkleTree<20, 1024>>()),
188 (20, 2048) => Ok(size_of::<ConcurrentMerkleTree<20, 2048>>()),
189 (24, 64) => Ok(size_of::<ConcurrentMerkleTree<24, 64>>()),
190 (24, 256) => Ok(size_of::<ConcurrentMerkleTree<24, 256>>()),
191 (24, 512) => Ok(size_of::<ConcurrentMerkleTree<24, 512>>()),
192 (24, 1024) => Ok(size_of::<ConcurrentMerkleTree<24, 1024>>()),
193 (24, 2048) => Ok(size_of::<ConcurrentMerkleTree<24, 2048>>()),
194 (26, 512) => Ok(size_of::<ConcurrentMerkleTree<26, 512>>()),
195 (26, 1024) => Ok(size_of::<ConcurrentMerkleTree<26, 1024>>()),
196 (26, 2048) => Ok(size_of::<ConcurrentMerkleTree<26, 2048>>()),
197 (30, 512) => Ok(size_of::<ConcurrentMerkleTree<30, 512>>()),
198 (30, 1024) => Ok(size_of::<ConcurrentMerkleTree<30, 1024>>()),
199 (30, 2048) => Ok(size_of::<ConcurrentMerkleTree<30, 2048>>()),
200 _ => {
201 msg!(
202 "Failed to get size of max depth {} and max buffer size {}",
203 header.get_max_depth(),
204 header.get_max_buffer_size()
205 );
206 err!(AccountCompressionError::ConcurrentMerkleTreeConstantsError)
207 }
208 }
209}