light_merkle_tree_metadata/
queue.rs1use bytemuck::{Pod, Zeroable};
2use light_compressed_account::{pubkey::Pubkey, QueueType};
3use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
4
5use crate::{
6 access::AccessMetadata, errors::MerkleTreeMetadataError, rollover::RolloverMetadata,
7 AnchorDeserialize, AnchorSerialize,
8};
9
10#[repr(C)]
11#[derive(
12 AnchorDeserialize,
13 AnchorSerialize,
14 Debug,
15 PartialEq,
16 Default,
17 Pod,
18 Zeroable,
19 Clone,
20 Copy,
21 Immutable,
22 FromBytes,
23 IntoBytes,
24 KnownLayout,
25)]
26pub struct QueueMetadata {
27 pub access_metadata: AccessMetadata,
28 pub rollover_metadata: RolloverMetadata,
29 pub associated_merkle_tree: Pubkey,
31 pub next_queue: Pubkey,
33 pub queue_type: u64,
34}
35
36pub fn check_queue_type(
37 queue_type: &u64,
38 expected_queue_type: &QueueType,
39) -> Result<(), MerkleTreeMetadataError> {
40 if *queue_type != (*expected_queue_type) as u64 {
41 Err(MerkleTreeMetadataError::InvalidQueueType)
42 } else {
43 Ok(())
44 }
45}
46
47impl QueueMetadata {
48 pub fn init(
49 &mut self,
50 access_metadata: AccessMetadata,
51 rollover_metadata: RolloverMetadata,
52 associated_merkle_tree: Pubkey,
53 queue_type: QueueType,
54 ) {
55 self.access_metadata = access_metadata;
56 self.rollover_metadata = rollover_metadata;
57 self.associated_merkle_tree = associated_merkle_tree;
58 self.queue_type = queue_type as u64;
59 }
60
61 pub fn rollover(
62 &mut self,
63 old_associated_merkle_tree: Pubkey,
64 next_queue: Pubkey,
65 ) -> Result<(), MerkleTreeMetadataError> {
66 if self.associated_merkle_tree != old_associated_merkle_tree {
67 return Err(MerkleTreeMetadataError::MerkleTreeAndQueueNotAssociated);
68 }
69
70 self.rollover_metadata.rollover()?;
71 self.next_queue = next_queue;
72
73 Ok(())
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::access;
81
82 fn create_queue_metadata(
84 associated_merkle_tree: Pubkey,
85 queue_type: QueueType,
86 ) -> QueueMetadata {
87 QueueMetadata {
88 access_metadata: AccessMetadata {
89 owner: Pubkey::new_unique(),
90 program_owner: Pubkey::new_unique(),
91 forester: Pubkey::new_unique(),
92 },
93 rollover_metadata: RolloverMetadata {
94 index: 0,
95 rollover_fee: 1000,
96 rollover_threshold: 95,
97 network_fee: 10,
98 rolledover_slot: u64::MAX,
99 close_threshold: 200,
100 additional_bytes: 0,
101 },
102 associated_merkle_tree,
103 next_queue: Pubkey::default(),
104 queue_type: queue_type as u64,
105 }
106 }
107
108 #[test]
109 fn test_check_queue_type_valid() {
110 let valid_queue_type = QueueType::NullifierV1;
111 assert!(check_queue_type(&(valid_queue_type as u64), &valid_queue_type).is_ok());
112 }
113
114 #[test]
115 fn test_check_queue_type_invalid() {
116 let queue_type = QueueType::NullifierV1;
117 let expected_queue_type = QueueType::AddressV1;
118 assert!(matches!(
119 check_queue_type(&(queue_type as u64), &expected_queue_type),
120 Err(MerkleTreeMetadataError::InvalidQueueType)
121 ));
122 }
123
124 #[test]
125 fn test_init_method() {
126 let associated_merkle_tree = Pubkey::new_unique();
127 let queue_type = QueueType::InputStateV2;
128 let access_metadata = access::AccessMetadata {
129 owner: Pubkey::new_unique(),
130 program_owner: Pubkey::new_unique(),
131 forester: Pubkey::new_unique(),
132 };
133 let rollover_metadata = RolloverMetadata {
134 index: 1,
135 rollover_fee: 1000,
136 rollover_threshold: 95,
137 network_fee: 10,
138 rolledover_slot: u64::MAX,
139 close_threshold: 200,
140 additional_bytes: 1,
141 };
142 let mut queue_metadata = QueueMetadata::default();
143 queue_metadata.init(
144 access_metadata,
145 rollover_metadata,
146 associated_merkle_tree,
147 queue_type,
148 );
149 assert_eq!(queue_metadata.access_metadata, access_metadata);
150 assert_eq!(queue_metadata.rollover_metadata, rollover_metadata);
151 assert_eq!(
152 queue_metadata.associated_merkle_tree,
153 associated_merkle_tree
154 );
155 assert_eq!(queue_metadata.queue_type, queue_type as u64);
156 }
157
158 #[test]
159 fn test_rollover_method_valid() {
160 let associated_merkle_tree = Pubkey::new_unique();
161 let next_queue = Pubkey::new_unique();
162 let mut queue_metadata =
163 create_queue_metadata(associated_merkle_tree, QueueType::NullifierV1);
164
165 assert!(queue_metadata
167 .rollover(associated_merkle_tree, next_queue)
168 .is_ok());
169 assert_eq!(queue_metadata.next_queue, next_queue);
170 }
171
172 #[test]
173 fn test_rollover_method_invalid_merkle_tree() {
174 let associated_merkle_tree = Pubkey::new_unique();
175 let wrong_tree = Pubkey::new_unique();
176 let next_queue = Pubkey::new_unique();
177 let mut queue_metadata =
178 create_queue_metadata(associated_merkle_tree, QueueType::NullifierV1);
179
180 assert!(matches!(
182 queue_metadata.rollover(wrong_tree, next_queue),
183 Err(MerkleTreeMetadataError::MerkleTreeAndQueueNotAssociated)
184 ));
185 }
186
187 #[test]
188 fn test_rollover_method_not_configured() {
189 let associated_merkle_tree = Pubkey::new_unique();
190 let mut queue_metadata =
191 create_queue_metadata(associated_merkle_tree, QueueType::NullifierV1);
192
193 queue_metadata.rollover_metadata.rollover_threshold = u64::MAX;
195 assert!(matches!(
196 queue_metadata.rollover_metadata.rollover(),
197 Err(MerkleTreeMetadataError::RolloverNotConfigured)
198 ));
199 }
200
201 #[test]
202 fn test_rollover_method_already_rolled_over() {
203 let associated_merkle_tree = Pubkey::new_unique();
204 let mut queue_metadata =
205 create_queue_metadata(associated_merkle_tree, QueueType::NullifierV1);
206
207 queue_metadata.rollover_metadata.rolledover_slot = 10;
209 assert!(matches!(
210 queue_metadata.rollover_metadata.rollover(),
211 Err(MerkleTreeMetadataError::MerkleTreeAlreadyRolledOver)
212 ));
213 }
214
215 #[test]
216 fn test_queue_type_from() {
217 assert_eq!(QueueType::NullifierV1, QueueType::from(1));
218 assert_eq!(QueueType::AddressV1, QueueType::from(2));
219 assert_eq!(QueueType::InputStateV2, QueueType::from(3));
220 assert_eq!(QueueType::AddressV2, QueueType::from(4));
221 assert_eq!(QueueType::OutputStateV2, QueueType::from(5));
222 }
223
224 #[should_panic = "Invalid queue type"]
225 #[test]
226 fn test_queue_type_from_invalid() {
227 let _ = QueueType::from(0);
228 }
229}