halo2_axiom/
helpers.rs

1use crate::poly::Polynomial;
2use ff::PrimeField;
3use halo2curves::{serde::SerdeObject, CurveAffine};
4use std::io;
5
6/// This enum specifies how various types are serialized and deserialized.
7#[derive(Clone, Copy, Debug)]
8pub enum SerdeFormat {
9    /// Curve elements are serialized in compressed form.
10    /// Field elements are serialized in standard form, with endianness specified by the
11    /// `PrimeField` implementation.
12    Processed,
13    /// Curve elements are serialized in uncompressed form. Field elements are serialized
14    /// in their internal Montgomery representation.
15    /// When deserializing, checks are performed to ensure curve elements indeed lie on the curve and field elements
16    /// are less than modulus.
17    RawBytes,
18    /// Serialization is the same as `RawBytes`, but no checks are performed.
19    RawBytesUnchecked,
20}
21
22// Keep this trait for compatibility with IPA serialization
23pub(crate) trait CurveRead: CurveAffine {
24    /// Reads a compressed element from the buffer and attempts to parse it
25    /// using `from_bytes`.
26    fn read<R: io::Read>(reader: &mut R) -> io::Result<Self> {
27        let mut compressed = Self::Repr::default();
28        reader.read_exact(compressed.as_mut())?;
29        Option::from(Self::from_bytes(&compressed))
30            .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Invalid point encoding in proof"))
31    }
32}
33impl<C: CurveAffine> CurveRead for C {}
34
35pub trait SerdeCurveAffine: CurveAffine + SerdeObject {
36    /// Reads an element from the buffer and parses it according to the `format`:
37    /// - `Processed`: Reads a compressed curve element and decompress it
38    /// - `RawBytes`: Reads an uncompressed curve element with coordinates in Montgomery form.
39    /// Checks that field elements are less than modulus, and then checks that the point is on the curve.
40    /// - `RawBytesUnchecked`: Reads an uncompressed curve element with coordinates in Montgomery form;
41    /// does not perform any checks
42    fn read<R: io::Read>(reader: &mut R, format: SerdeFormat) -> io::Result<Self> {
43        match format {
44            SerdeFormat::Processed => <Self as CurveRead>::read(reader),
45            SerdeFormat::RawBytes => <Self as SerdeObject>::read_raw(reader),
46            SerdeFormat::RawBytesUnchecked => Ok(<Self as SerdeObject>::read_raw_unchecked(reader)),
47        }
48    }
49    /// Writes a curve element according to `format`:
50    /// - `Processed`: Writes a compressed curve element
51    /// - Otherwise: Writes an uncompressed curve element with coordinates in Montgomery form
52    fn write<W: io::Write>(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> {
53        match format {
54            SerdeFormat::Processed => writer.write_all(self.to_bytes().as_ref()),
55            _ => self.write_raw(writer),
56        }
57    }
58}
59impl<C: CurveAffine + SerdeObject> SerdeCurveAffine for C {}
60
61pub trait SerdePrimeField: PrimeField + SerdeObject {
62    /// Reads a field element as bytes from the buffer according to the `format`:
63    /// - `Processed`: Reads a field element in standard form, with endianness specified by the
64    /// `PrimeField` implementation, and checks that the element is less than the modulus.
65    /// - `RawBytes`: Reads a field element from raw bytes in its internal Montgomery representations,
66    /// and checks that the element is less than the modulus.
67    /// - `RawBytesUnchecked`: Reads a field element in Montgomery form and performs no checks.
68    fn read<R: io::Read>(reader: &mut R, format: SerdeFormat) -> io::Result<Self> {
69        match format {
70            SerdeFormat::Processed => {
71                let mut compressed = Self::Repr::default();
72                reader.read_exact(compressed.as_mut()).unwrap();
73                Option::from(Self::from_repr(compressed)).ok_or_else(|| {
74                    io::Error::new(io::ErrorKind::Other, "Invalid prime field point encoding")
75                })
76            }
77            SerdeFormat::RawBytes => <Self as SerdeObject>::read_raw(reader),
78            SerdeFormat::RawBytesUnchecked => Ok(<Self as SerdeObject>::read_raw_unchecked(reader)),
79        }
80    }
81
82    /// Writes a field element as bytes to the buffer according to the `format`:
83    /// - `Processed`: Writes a field element in standard form, with endianness specified by the
84    /// `PrimeField` implementation.
85    /// - Otherwise: Writes a field element into raw bytes in its internal Montgomery representation,
86    /// WITHOUT performing the expensive Montgomery reduction.
87    fn write<W: io::Write>(&self, writer: &mut W, format: SerdeFormat) -> io::Result<()> {
88        match format {
89            SerdeFormat::Processed => writer.write_all(self.to_repr().as_ref()),
90            _ => self.write_raw(writer),
91        }
92    }
93}
94impl<F: PrimeField + SerdeObject> SerdePrimeField for F {}
95
96/// Convert a slice of `bool` into a `u8`.
97///
98/// Panics if the slice has length greater than 8.
99pub fn pack(bits: &[bool]) -> u8 {
100    let mut value = 0u8;
101    assert!(bits.len() <= 8);
102    for (bit_index, bit) in bits.iter().enumerate() {
103        value |= (*bit as u8) << bit_index;
104    }
105    value
106}
107
108/// Writes the first `bits.len()` bits of a `u8` into `bits`.
109pub fn unpack(byte: u8, bits: &mut [bool]) {
110    for (bit_index, bit) in bits.iter_mut().enumerate() {
111        *bit = (byte >> bit_index) & 1 == 1;
112    }
113}
114
115/// Reads a vector of polynomials from buffer
116pub(crate) fn read_polynomial_vec<R: io::Read, F: SerdePrimeField, B>(
117    reader: &mut R,
118    format: SerdeFormat,
119) -> Vec<Polynomial<F, B>> {
120    let mut len = [0u8; 4];
121    reader.read_exact(&mut len).unwrap();
122    let len = u32::from_be_bytes(len);
123
124    (0..len)
125        .map(|_| Polynomial::<F, B>::read(reader, format))
126        .collect()
127}
128
129/// Writes a slice of polynomials to buffer
130pub(crate) fn write_polynomial_slice<W: io::Write, F: SerdePrimeField, B>(
131    slice: &[Polynomial<F, B>],
132    writer: &mut W,
133    format: SerdeFormat,
134) {
135    writer
136        .write_all(&(slice.len() as u32).to_be_bytes())
137        .unwrap();
138    for poly in slice.iter() {
139        poly.write(writer, format);
140    }
141}
142
143/// Gets the total number of bytes of a slice of polynomials, assuming all polynomials are the same length
144pub(crate) fn polynomial_slice_byte_length<F: PrimeField, B>(slice: &[Polynomial<F, B>]) -> usize {
145    let field_len = F::default().to_repr().as_ref().len();
146    4 + slice.len() * (4 + field_len * slice.get(0).map(|poly| poly.len()).unwrap_or(0))
147}