use alloc::vec::Vec;
use crypto::{ElementHasher, Hasher, VectorCommitment};
use math::FieldElement;
use utils::{
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
};
use super::Table;
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Queries {
opening_proof: Vec<u8>,
values: Vec<u8>,
}
impl Queries {
pub fn new<H: Hasher, E: FieldElement, V: VectorCommitment<H>>(
opening_proof: V::MultiProof,
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_many(elements);
}
let opening_proof = opening_proof.to_bytes();
Queries { opening_proof, values }
}
pub fn parse<E, H, V>(
self,
domain_size: usize,
num_queries: usize,
values_per_query: usize,
) -> Result<(V::MultiProof, Table<E>), DeserializationError>
where
E: FieldElement,
H: ElementHasher<BaseField = E::BaseField>,
V: VectorCommitment<H>,
{
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 mut reader = SliceReader::new(&self.opening_proof);
let opening_proof = <V::MultiProof as Deserializable>::read_from(&mut reader)?;
if <V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof) != domain_size {
return Err(DeserializationError::InvalidValue(format!(
"expected a domain of size {} but was {}",
domain_size,
<V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof),
)));
}
if reader.has_more_bytes() {
return Err(DeserializationError::UnconsumedBytes);
}
Ok((opening_proof, query_values))
}
}
impl Serializable for Queries {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.values.write_into(target);
self.opening_proof.write_into(target);
}
fn get_size_hint(&self) -> usize {
self.opening_proof.len() + self.values.len() + 8
}
}
impl Deserializable for Queries {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let values = Vec::<_>::read_from(source)?;
let paths = Vec::<_>::read_from(source)?;
Ok(Queries { opening_proof: paths, values })
}
}