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}