winter_air/proof/
commitments.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::Hasher;
9use utils::{
10    ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable, SliceReader,
11};
12
13// COMMITMENTS
14// ================================================================================================
15/// Commitments made by the prover during commit phase of the protocol.
16///
17/// These commitments include:
18/// * Commitment to the extended execution trace, which may include commitments to one or more
19///   execution trace segments.
20/// * Commitment to the evaluations of constraint composition polynomial over LDE domain.
21/// * Commitments to the evaluations of polynomials at all FRI layers.
22///
23/// Internally, the commitments are stored as a sequence of bytes. Thus, to retrieve the
24/// commitments, [parse()](Commitments::parse) function should be used.
25#[derive(Debug, Clone, Default, Eq, PartialEq)]
26pub struct Commitments(Vec<u8>);
27
28impl Commitments {
29    // CONSTRUCTOR
30    // --------------------------------------------------------------------------------------------
31    /// Returns a new Commitments struct initialized with the provided commitments.
32    pub fn new<H: Hasher>(
33        trace_roots: Vec<H::Digest>,
34        constraint_root: H::Digest,
35        fri_roots: Vec<H::Digest>,
36    ) -> Self {
37        let mut bytes = Vec::new();
38        bytes.write_many(&trace_roots);
39        bytes.write(constraint_root);
40        bytes.write_many(&fri_roots);
41        Commitments(bytes)
42    }
43
44    // PUBLIC METHODS
45    // --------------------------------------------------------------------------------------------
46
47    /// Adds the specified commitment to the list of commitments.
48    pub fn add<H: Hasher>(&mut self, commitment: &H::Digest) {
49        commitment.write_into(&mut self.0);
50    }
51
52    // PARSING
53    // --------------------------------------------------------------------------------------------
54
55    /// Parses the serialized commitments into distinct parts.
56    ///
57    /// The parts are (in the order in which they appear in the tuple):
58    /// 1. Extended execution trace commitments.
59    /// 2. Constraint composition polynomial evaluation commitment.
60    /// 3. FRI layer commitments.
61    ///
62    /// # Errors
63    /// Returns an error if the bytes stored in self could not be parsed into the requested number
64    /// of commitments, or if there are any unconsumed bytes remaining after the parsing completes.
65    #[allow(clippy::type_complexity)]
66    pub fn parse<H: Hasher>(
67        self,
68        num_trace_segments: usize,
69        num_fri_layers: usize,
70    ) -> Result<(Vec<H::Digest>, H::Digest, Vec<H::Digest>), DeserializationError> {
71        let mut reader = SliceReader::new(&self.0);
72
73        // parse trace commitments
74        let trace_commitments = reader.read_many(num_trace_segments)?;
75
76        // parse constraint evaluation commitment:
77        let constraint_commitment = reader.read()?;
78
79        // read FRI commitments (+ 1 for remainder polynomial commitment)
80        let fri_commitments = reader.read_many(num_fri_layers + 1)?;
81
82        // make sure we consumed all available commitment bytes
83        if reader.has_more_bytes() {
84            return Err(DeserializationError::UnconsumedBytes);
85        }
86        Ok((trace_commitments, constraint_commitment, fri_commitments))
87    }
88}
89
90// SERIALIZATION
91// ================================================================================================
92
93impl Serializable for Commitments {
94    /// Serializes `self` and writes the resulting bytes into the `target`.
95    fn write_into<W: ByteWriter>(&self, target: &mut W) {
96        assert!(self.0.len() < u16::MAX as usize);
97        target.write_u16(self.0.len() as u16);
98        target.write_bytes(&self.0);
99    }
100
101    /// Returns an estimate of how many bytes are needed to represent self.
102    fn get_size_hint(&self) -> usize {
103        self.0.len() + 2
104    }
105}
106
107impl Deserializable for Commitments {
108    /// Reads commitments from the specified `source` and returns the result.
109    ///
110    /// # Errors
111    /// Returns an error of a valid Commitments struct could not be read from the specified
112    /// `source`.
113    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
114        let num_bytes = source.read_u16()? as usize;
115        let result = source.read_vec(num_bytes)?;
116        Ok(Commitments(result))
117    }
118}