winter_air/proof/queries.rs
1// Copyright (c) Facebook, Inc. and its affiliates.
2//
3// This source code is licensed under the MIT license found in the
4// LICENSE file in the root directory of this source tree.
5
6use alloc::vec::Vec;
7
8use crypto::{ElementHasher, Hasher, VectorCommitment};
9use math::FieldElement;
10use utils::{
11 ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
12};
13
14use super::Table;
15
16// QUERIES
17// ================================================================================================
18/// Decommitments to evaluations of a set of functions at multiple points.
19///
20/// Given a set of functions evaluated over a domain *D*, a commitment is assumed to be a vector
21/// commitment where the *i*-th vector entry contains evaluations of all functions at
22/// *x<sub>i</sub>*. Thus, a query (i.e. a single decommitment) for position *i* includes
23/// evaluations of all functions at *x<sub>i</sub>*, accompanied by an opening proof of leaf *i*
24/// against the vector commitment string.
25///
26/// This struct can contain one or more queries. In cases when more than one query is stored,
27/// a batch opening proof is used in order to compress the individual opening proofs.
28///
29/// Internally, all opening proofs and query values are stored as a sequence of bytes. Thus, to
30/// retrieve query values and their corresponding opening proofs, [parse()](Queries::parse)
31/// function should be used.
32#[derive(Debug, Clone, Eq, PartialEq)]
33pub struct Queries {
34 opening_proof: Vec<u8>,
35 values: Vec<u8>,
36}
37
38impl Queries {
39 // CONSTRUCTOR
40 // --------------------------------------------------------------------------------------------
41 /// Returns queries constructed from evaluations of a set of functions at some number of points
42 /// in a domain and their corresponding batch opening proof.
43 ///
44 /// For each evaluation point, the same number of values must be provided.
45 ///
46 /// # Panics
47 /// Panics if:
48 /// * No queries were provided (`query_values` is an empty vector).
49 /// * Any of the queries does not contain any evaluations.
50 /// * Not all queries contain the same number of evaluations.
51 pub fn new<H: Hasher, E: FieldElement, V: VectorCommitment<H>>(
52 opening_proof: V::MultiProof,
53 query_values: Vec<Vec<E>>,
54 ) -> Self {
55 assert!(!query_values.is_empty(), "query values cannot be empty");
56 let elements_per_query = query_values[0].len();
57 assert_ne!(elements_per_query, 0, "a query must contain at least one evaluation");
58
59 // concatenate all elements together into a single vector of bytes
60 let num_queries = query_values.len();
61 let mut values = Vec::with_capacity(num_queries * elements_per_query * E::ELEMENT_BYTES);
62 for elements in query_values.iter() {
63 assert_eq!(
64 elements.len(),
65 elements_per_query,
66 "all queries must contain the same number of evaluations"
67 );
68 values.write_many(elements);
69 }
70 let opening_proof = opening_proof.to_bytes();
71
72 Queries { opening_proof, values }
73 }
74
75 // PARSER
76 // --------------------------------------------------------------------------------------------
77 /// Convert internally stored bytes into a set of query values and the corresponding batch
78 /// opening proof.
79 ///
80 /// # Panics
81 /// Panics if:
82 /// * `domain_size` is not a power of two.
83 /// * `num_queries` is zero.
84 /// * `values_per_query` is zero.
85 pub fn parse<E, H, V>(
86 self,
87 domain_size: usize,
88 num_queries: usize,
89 values_per_query: usize,
90 ) -> Result<(V::MultiProof, Table<E>), DeserializationError>
91 where
92 E: FieldElement,
93 H: ElementHasher<BaseField = E::BaseField>,
94 V: VectorCommitment<H>,
95 {
96 assert!(domain_size.is_power_of_two(), "domain size must be a power of two");
97 assert!(num_queries > 0, "there must be at least one query");
98 assert!(values_per_query > 0, "a query must contain at least one value");
99
100 // make sure we have enough bytes to read the expected number of queries
101 let num_query_bytes = E::ELEMENT_BYTES * values_per_query;
102 let expected_bytes = num_queries * num_query_bytes;
103 if self.values.len() != expected_bytes {
104 return Err(DeserializationError::InvalidValue(format!(
105 "expected {} query value bytes, but was {}",
106 expected_bytes,
107 self.values.len()
108 )));
109 }
110
111 // read bytes corresponding to each query and convert them into field elements.
112 let query_values = Table::<E>::from_bytes(&self.values, num_queries, values_per_query)?;
113
114 // build batch opening proof
115 let mut reader = SliceReader::new(&self.opening_proof);
116 let opening_proof = <V::MultiProof as Deserializable>::read_from(&mut reader)?;
117
118 // check that the opening proof matches the domain length
119 if <V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof) != domain_size {
120 return Err(DeserializationError::InvalidValue(format!(
121 "expected a domain of size {} but was {}",
122 domain_size,
123 <V as VectorCommitment<H>>::get_multiproof_domain_len(&opening_proof),
124 )));
125 }
126
127 if reader.has_more_bytes() {
128 return Err(DeserializationError::UnconsumedBytes);
129 }
130
131 Ok((opening_proof, query_values))
132 }
133}
134
135// SERIALIZATION
136// ================================================================================================
137
138impl Serializable for Queries {
139 /// Serializes `self` and writes the resulting bytes into the `target`.
140 fn write_into<W: ByteWriter>(&self, target: &mut W) {
141 // write value bytes
142 self.values.write_into(target);
143
144 // write path bytes
145 self.opening_proof.write_into(target);
146 }
147
148 /// Returns an estimate of how many bytes are needed to represent self.
149 fn get_size_hint(&self) -> usize {
150 self.opening_proof.len() + self.values.len() + 8
151 }
152}
153
154impl Deserializable for Queries {
155 /// Reads a query struct from the specified `source` and returns the result
156 ///
157 /// # Errors
158 /// Returns an error of a valid query struct could not be read from the specified source.
159 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
160 // read values
161 let values = Vec::<_>::read_from(source)?;
162
163 // read paths
164 let paths = Vec::<_>::read_from(source)?;
165
166 Ok(Queries { opening_proof: paths, values })
167 }
168}