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#[repr(C)]
40#[derive(AnchorDeserialize, AnchorSerialize)]
41pub struct ConcurrentMerkleTreeHeader {
42 pub account_type: CompressionAccountType,
44 pub header: ConcurrentMerkleTreeHeaderData,
46}
47
48#[repr(C)]
49#[derive(AnchorDeserialize, AnchorSerialize)]
50pub struct ConcurrentMerkleTreeHeaderDataV1 {
51 max_buffer_size: u32,
54
55 max_depth: u32,
59
60 authority: Pubkey,
63
64 creation_slot: u64,
67
68 _padding: [u8; 6],
71}
72
73#[repr(C)]
74#[derive(AnchorDeserialize, AnchorSerialize)]
75pub enum ConcurrentMerkleTreeHeaderData {
76 V1(ConcurrentMerkleTreeHeaderDataV1),
77}
78
79impl ConcurrentMerkleTreeHeader {
80 pub fn initialize(
81 &mut self,
82 max_depth: u32,
83 max_buffer_size: u32,
84 authority: &Pubkey,
85 creation_slot: u64,
86 ) {
87 self.account_type = CompressionAccountType::ConcurrentMerkleTree;
88
89 match self.header {
90 ConcurrentMerkleTreeHeaderData::V1(ref mut header) => {
91 assert_eq!(header.max_buffer_size, 0);
93 assert_eq!(header.max_depth, 0);
94 header.max_buffer_size = max_buffer_size;
95 header.max_depth = max_depth;
96 header.authority = *authority;
97 header.creation_slot = creation_slot;
98 }
99 }
100 }
101
102 pub fn get_max_depth(&self) -> u32 {
103 match &self.header {
104 ConcurrentMerkleTreeHeaderData::V1(header) => header.max_depth,
105 }
106 }
107
108 pub fn get_max_buffer_size(&self) -> u32 {
109 match &self.header {
110 ConcurrentMerkleTreeHeaderData::V1(header) => header.max_buffer_size,
111 }
112 }
113
114 pub fn get_creation_slot(&self) -> u64 {
115 match &self.header {
116 ConcurrentMerkleTreeHeaderData::V1(header) => header.creation_slot,
117 }
118 }
119
120 pub fn set_new_authority(&mut self, new_authority: &Pubkey) {
121 match self.header {
122 ConcurrentMerkleTreeHeaderData::V1(ref mut header) => {
123 header.authority = new_authority.clone();
124 msg!("Authority transferred to: {:?}", header.authority);
125 }
126 }
127 }
128
129 pub fn assert_valid(&self) -> Result<()> {
130 require_eq!(
131 self.account_type,
132 CompressionAccountType::ConcurrentMerkleTree,
133 AccountCompressionError::IncorrectAccountType,
134 );
135 Ok(())
136 }
137
138 pub fn assert_valid_authority(&self, expected_authority: &Pubkey) -> Result<()> {
139 self.assert_valid()?;
140 match &self.header {
141 ConcurrentMerkleTreeHeaderData::V1(header) => {
142 require_eq!(
143 header.authority,
144 *expected_authority,
145 AccountCompressionError::IncorrectAuthority,
146 );
147 }
148 }
149 Ok(())
150 }
151
152 pub fn assert_valid_leaf_index(&self, leaf_index: u32) -> Result<()> {
153 if leaf_index >= (1 << self.get_max_depth()) {
154 return Err(AccountCompressionError::LeafIndexOutOfBounds.into());
155 }
156 Ok(())
157 }
158}
159
160pub fn merkle_tree_get_size(header: &ConcurrentMerkleTreeHeader) -> Result<usize> {
161 match (header.get_max_depth(), header.get_max_buffer_size()) {
163 (3, 8) => Ok(size_of::<ConcurrentMerkleTree<3, 8>>()),
164 (5, 8) => Ok(size_of::<ConcurrentMerkleTree<5, 8>>()),
165 (6, 16) => Ok(size_of::<ConcurrentMerkleTree<6, 16>>()),
166 (7, 16) => Ok(size_of::<ConcurrentMerkleTree<7, 16>>()),
167 (8, 16) => Ok(size_of::<ConcurrentMerkleTree<8, 16>>()),
168 (9, 16) => Ok(size_of::<ConcurrentMerkleTree<9, 16>>()),
169 (10, 32) => Ok(size_of::<ConcurrentMerkleTree<10, 32>>()),
170 (11, 32) => Ok(size_of::<ConcurrentMerkleTree<11, 32>>()),
171 (12, 32) => Ok(size_of::<ConcurrentMerkleTree<12, 32>>()),
172 (13, 32) => Ok(size_of::<ConcurrentMerkleTree<13, 32>>()),
173 (14, 64) => Ok(size_of::<ConcurrentMerkleTree<14, 64>>()),
174 (14, 256) => Ok(size_of::<ConcurrentMerkleTree<14, 256>>()),
175 (14, 1024) => Ok(size_of::<ConcurrentMerkleTree<14, 1024>>()),
176 (14, 2048) => Ok(size_of::<ConcurrentMerkleTree<14, 2048>>()),
177 (15, 64) => Ok(size_of::<ConcurrentMerkleTree<15, 64>>()),
178 (16, 64) => Ok(size_of::<ConcurrentMerkleTree<16, 64>>()),
179 (17, 64) => Ok(size_of::<ConcurrentMerkleTree<17, 64>>()),
180 (18, 64) => Ok(size_of::<ConcurrentMerkleTree<18, 64>>()),
181 (19, 64) => Ok(size_of::<ConcurrentMerkleTree<19, 64>>()),
182 (20, 64) => Ok(size_of::<ConcurrentMerkleTree<20, 64>>()),
183 (20, 256) => Ok(size_of::<ConcurrentMerkleTree<20, 256>>()),
184 (20, 1024) => Ok(size_of::<ConcurrentMerkleTree<20, 1024>>()),
185 (20, 2048) => Ok(size_of::<ConcurrentMerkleTree<20, 2048>>()),
186 (24, 64) => Ok(size_of::<ConcurrentMerkleTree<24, 64>>()),
187 (24, 256) => Ok(size_of::<ConcurrentMerkleTree<24, 256>>()),
188 (24, 512) => Ok(size_of::<ConcurrentMerkleTree<24, 512>>()),
189 (24, 1024) => Ok(size_of::<ConcurrentMerkleTree<24, 1024>>()),
190 (24, 2048) => Ok(size_of::<ConcurrentMerkleTree<24, 2048>>()),
191 (26, 512) => Ok(size_of::<ConcurrentMerkleTree<26, 512>>()),
192 (26, 1024) => Ok(size_of::<ConcurrentMerkleTree<26, 1024>>()),
193 (26, 2048) => Ok(size_of::<ConcurrentMerkleTree<26, 2048>>()),
194 (30, 512) => Ok(size_of::<ConcurrentMerkleTree<30, 512>>()),
195 (30, 1024) => Ok(size_of::<ConcurrentMerkleTree<30, 1024>>()),
196 (30, 2048) => Ok(size_of::<ConcurrentMerkleTree<30, 2048>>()),
197 _ => {
198 msg!(
199 "Failed to get size of max depth {} and max buffer size {}",
200 header.get_max_depth(),
201 header.get_max_buffer_size()
202 );
203 err!(AccountCompressionError::ConcurrentMerkleTreeConstantsError)
204 }
205 }
206}