light_client/indexer/types/
queue.rs1use super::super::IndexerError;
2
3#[derive(Debug, Clone, PartialEq, Default)]
4pub struct OutputQueueData {
5 pub leaf_indices: Vec<u64>,
6 pub account_hashes: Vec<[u8; 32]>,
7 pub old_leaves: Vec<[u8; 32]>,
8 pub first_queue_index: u64,
9 pub next_index: u64,
11 pub leaves_hash_chains: Vec<[u8; 32]>,
13}
14
15#[derive(Debug, Clone, PartialEq, Default)]
17pub struct InputQueueData {
18 pub leaf_indices: Vec<u64>,
19 pub account_hashes: Vec<[u8; 32]>,
20 pub current_leaves: Vec<[u8; 32]>,
21 pub tx_hashes: Vec<[u8; 32]>,
22 pub nullifiers: Vec<[u8; 32]>,
24 pub first_queue_index: u64,
25 pub leaves_hash_chains: Vec<[u8; 32]>,
27}
28
29#[derive(Debug, Clone, PartialEq, Default)]
31pub struct StateQueueData {
32 pub nodes: Vec<u64>,
35 pub node_hashes: Vec<[u8; 32]>,
36 pub initial_root: [u8; 32],
38 pub root_seq: u64,
40 pub output_queue: Option<OutputQueueData>,
42 pub input_queue: Option<InputQueueData>,
44}
45
46#[derive(Debug, Clone, PartialEq, Default)]
49pub struct AddressQueueData {
50 pub addresses: Vec<[u8; 32]>,
51 pub low_element_values: Vec<[u8; 32]>,
52 pub low_element_next_values: Vec<[u8; 32]>,
53 pub low_element_indices: Vec<u64>,
54 pub low_element_next_indices: Vec<u64>,
55 pub nodes: Vec<u64>,
57 pub node_hashes: Vec<[u8; 32]>,
59 pub initial_root: [u8; 32],
60 pub leaves_hash_chains: Vec<[u8; 32]>,
61 pub subtrees: Vec<[u8; 32]>,
62 pub start_index: u64,
63 pub root_seq: u64,
64}
65
66impl AddressQueueData {
67 pub fn reconstruct_proof(
70 &self,
71 address_idx: usize,
72 tree_height: u8,
73 ) -> Result<Vec<[u8; 32]>, IndexerError> {
74 let leaf_index = *self.low_element_indices.get(address_idx).ok_or_else(|| {
75 IndexerError::MissingResult {
76 context: "reconstruct_proof".to_string(),
77 message: format!(
78 "address_idx {} out of bounds for low_element_indices (len {})",
79 address_idx,
80 self.low_element_indices.len(),
81 ),
82 }
83 })?;
84 let mut proof = Vec::with_capacity(tree_height as usize);
85 let mut pos = leaf_index;
86
87 for level in 0..tree_height {
88 let sibling_pos = if pos.is_multiple_of(2) {
89 pos + 1
90 } else {
91 pos - 1
92 };
93 let sibling_idx = Self::encode_node_index(level, sibling_pos);
94
95 let hash_idx = self
96 .nodes
97 .iter()
98 .position(|&n| n == sibling_idx)
99 .ok_or_else(|| IndexerError::MissingResult {
100 context: "reconstruct_proof".to_string(),
101 message: format!(
102 "Missing proof node at level {} position {} (encoded: {})",
103 level, sibling_pos, sibling_idx
104 ),
105 })?;
106 let hash =
107 self.node_hashes
108 .get(hash_idx)
109 .ok_or_else(|| IndexerError::MissingResult {
110 context: "reconstruct_proof".to_string(),
111 message: format!(
112 "node_hashes index {} out of bounds (len {})",
113 hash_idx,
114 self.node_hashes.len(),
115 ),
116 })?;
117 proof.push(*hash);
118 pos /= 2;
119 }
120
121 Ok(proof)
122 }
123
124 pub fn reconstruct_all_proofs(
126 &self,
127 tree_height: u8,
128 ) -> Result<Vec<Vec<[u8; 32]>>, IndexerError> {
129 (0..self.addresses.len())
130 .map(|i| self.reconstruct_proof(i, tree_height))
131 .collect()
132 }
133
134 #[inline]
136 fn encode_node_index(level: u8, position: u64) -> u64 {
137 ((level as u64) << 56) | position
138 }
139}
140
141#[derive(Debug, Clone, PartialEq, Default)]
143pub struct QueueElementsResult {
144 pub state_queue: Option<StateQueueData>,
145 pub address_queue: Option<AddressQueueData>,
146}