use super::super::IndexerError;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct OutputQueueData {
pub leaf_indices: Vec<u64>,
pub account_hashes: Vec<[u8; 32]>,
pub old_leaves: Vec<[u8; 32]>,
pub first_queue_index: u64,
pub next_index: u64,
pub leaves_hash_chains: Vec<[u8; 32]>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct InputQueueData {
pub leaf_indices: Vec<u64>,
pub account_hashes: Vec<[u8; 32]>,
pub current_leaves: Vec<[u8; 32]>,
pub tx_hashes: Vec<[u8; 32]>,
pub nullifiers: Vec<[u8; 32]>,
pub first_queue_index: u64,
pub leaves_hash_chains: Vec<[u8; 32]>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct StateQueueData {
pub nodes: Vec<u64>,
pub node_hashes: Vec<[u8; 32]>,
pub initial_root: [u8; 32],
pub root_seq: u64,
pub output_queue: Option<OutputQueueData>,
pub input_queue: Option<InputQueueData>,
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct AddressQueueData {
pub addresses: Vec<[u8; 32]>,
pub low_element_values: Vec<[u8; 32]>,
pub low_element_next_values: Vec<[u8; 32]>,
pub low_element_indices: Vec<u64>,
pub low_element_next_indices: Vec<u64>,
pub nodes: Vec<u64>,
pub node_hashes: Vec<[u8; 32]>,
pub initial_root: [u8; 32],
pub leaves_hash_chains: Vec<[u8; 32]>,
pub subtrees: Vec<[u8; 32]>,
pub start_index: u64,
pub root_seq: u64,
}
impl AddressQueueData {
pub fn reconstruct_proof(
&self,
address_idx: usize,
tree_height: u8,
) -> Result<Vec<[u8; 32]>, IndexerError> {
let leaf_index = *self.low_element_indices.get(address_idx).ok_or_else(|| {
IndexerError::MissingResult {
context: "reconstruct_proof".to_string(),
message: format!(
"address_idx {} out of bounds for low_element_indices (len {})",
address_idx,
self.low_element_indices.len(),
),
}
})?;
let mut proof = Vec::with_capacity(tree_height as usize);
let mut pos = leaf_index;
for level in 0..tree_height {
let sibling_pos = if pos.is_multiple_of(2) {
pos + 1
} else {
pos - 1
};
let sibling_idx = Self::encode_node_index(level, sibling_pos);
let hash_idx = self
.nodes
.iter()
.position(|&n| n == sibling_idx)
.ok_or_else(|| IndexerError::MissingResult {
context: "reconstruct_proof".to_string(),
message: format!(
"Missing proof node at level {} position {} (encoded: {})",
level, sibling_pos, sibling_idx
),
})?;
let hash =
self.node_hashes
.get(hash_idx)
.ok_or_else(|| IndexerError::MissingResult {
context: "reconstruct_proof".to_string(),
message: format!(
"node_hashes index {} out of bounds (len {})",
hash_idx,
self.node_hashes.len(),
),
})?;
proof.push(*hash);
pos /= 2;
}
Ok(proof)
}
pub fn reconstruct_all_proofs(
&self,
tree_height: u8,
) -> Result<Vec<Vec<[u8; 32]>>, IndexerError> {
(0..self.addresses.len())
.map(|i| self.reconstruct_proof(i, tree_height))
.collect()
}
#[inline]
fn encode_node_index(level: u8, position: u64) -> u64 {
((level as u64) << 56) | position
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct QueueElementsResult {
pub state_queue: Option<StateQueueData>,
pub address_queue: Option<AddressQueueData>,
}