use super::Table;
use crypto::{BatchMerkleProof, ElementHasher, Hasher};
use math::{log2, FieldElement};
use utils::{
collections::Vec, ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
SliceReader,
};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Queries {
paths: Vec<u8>,
values: Vec<u8>,
}
impl Queries {
pub fn new<H: Hasher, E: FieldElement>(
merkle_proof: BatchMerkleProof<H>,
query_values: Vec<Vec<E>>,
) -> Self {
assert!(!query_values.is_empty(), "query values cannot be empty");
let elements_per_query = query_values[0].len();
assert_ne!(
elements_per_query, 0,
"a query must contain at least one evaluation"
);
let num_queries = query_values.len();
let mut values = Vec::with_capacity(num_queries * elements_per_query * E::ELEMENT_BYTES);
for elements in query_values.iter() {
assert_eq!(
elements.len(),
elements_per_query,
"all queries must contain the same number of evaluations"
);
values.write(elements);
}
let paths = merkle_proof.serialize_nodes();
Queries { paths, values }
}
pub fn parse<H, E>(
self,
domain_size: usize,
num_queries: usize,
values_per_query: usize,
) -> Result<(BatchMerkleProof<H>, Table<E>), DeserializationError>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
{
assert!(
domain_size.is_power_of_two(),
"domain size must be a power of two"
);
assert!(num_queries > 0, "there must be at least one query");
assert!(
values_per_query > 0,
"a query must contain at least one value"
);
let num_query_bytes = E::ELEMENT_BYTES * values_per_query;
let expected_bytes = num_queries * num_query_bytes;
if self.values.len() != expected_bytes {
return Err(DeserializationError::InvalidValue(format!(
"expected {} query value bytes, but was {}",
expected_bytes,
self.values.len()
)));
}
let query_values = Table::<E>::from_bytes(&self.values, num_queries, values_per_query)?;
let hashed_queries = query_values
.rows()
.map(|row| H::hash_elements(row))
.collect();
let mut reader = SliceReader::new(&self.paths);
let tree_depth = log2(domain_size) as u8;
let merkle_proof = BatchMerkleProof::deserialize(&mut reader, hashed_queries, tree_depth)?;
if reader.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
Ok((merkle_proof, query_values))
}
}
impl Serializable for Queries {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
target.write_u32(self.values.len() as u32);
target.write_u8_slice(&self.values);
target.write_u32(self.paths.len() as u32);
target.write_u8_slice(&self.paths);
}
}
impl Deserializable for Queries {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let num_value_bytes = source.read_u32()?;
let values = source.read_u8_vec(num_value_bytes as usize)?;
let num_paths_bytes = source.read_u32()?;
let paths = source.read_u8_vec(num_paths_bytes as usize)?;
Ok(Queries { paths, values })
}
}