rtvm_primitives/kzg/
trusted_setup_points.rs

1use core::fmt;
2use derive_more::{AsMut, AsRef, Deref, DerefMut};
3use std::boxed::Box;
4
5pub use c_kzg::{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT};
6
7/// Number of G1 Points.
8pub const NUM_G1_POINTS: usize = 4096;
9
10/// Number of G2 Points.
11pub const NUM_G2_POINTS: usize = 65;
12
13/// A newtype over list of G1 point from kzg trusted setup.
14#[derive(Debug, Clone, PartialEq, AsRef, AsMut, Deref, DerefMut)]
15#[repr(transparent)]
16pub struct G1Points(pub [[u8; BYTES_PER_G1_POINT]; NUM_G1_POINTS]);
17
18impl Default for G1Points {
19    fn default() -> Self {
20        Self([[0; BYTES_PER_G1_POINT]; NUM_G1_POINTS])
21    }
22}
23
24/// A newtype over list of G2 point from kzg trusted setup.
25#[derive(Debug, Clone, Eq, PartialEq, AsRef, AsMut, Deref, DerefMut)]
26#[repr(transparent)]
27pub struct G2Points(pub [[u8; BYTES_PER_G2_POINT]; NUM_G2_POINTS]);
28
29impl Default for G2Points {
30    fn default() -> Self {
31        Self([[0; BYTES_PER_G2_POINT]; NUM_G2_POINTS])
32    }
33}
34
35/// Default G1 points.
36pub const G1_POINTS: &G1Points = {
37    const BYTES: &[u8] = include_bytes!("./g1_points.bin");
38    assert!(BYTES.len() == core::mem::size_of::<G1Points>());
39    unsafe { &*BYTES.as_ptr().cast::<G1Points>() }
40};
41
42/// Default G2 points.
43pub const G2_POINTS: &G2Points = {
44    const BYTES: &[u8] = include_bytes!("./g2_points.bin");
45    assert!(BYTES.len() == core::mem::size_of::<G2Points>());
46    unsafe { &*BYTES.as_ptr().cast::<G2Points>() }
47};
48
49/// Parses the contents of a KZG trusted setup file into a list of G1 and G2 points.
50///
51/// These can then be used to create a KZG settings object with
52/// [`KzgSettings::load_trusted_setup`](c_kzg::KzgSettings::load_trusted_setup).
53pub fn parse_kzg_trusted_setup(
54    trusted_setup: &str,
55) -> Result<(Box<G1Points>, Box<G2Points>), KzgErrors> {
56    let mut lines = trusted_setup.lines();
57
58    // load number of points
59    let n_g1 = lines
60        .next()
61        .ok_or(KzgErrors::FileFormatError)?
62        .parse::<usize>()
63        .map_err(|_| KzgErrors::ParseError)?;
64    let n_g2 = lines
65        .next()
66        .ok_or(KzgErrors::FileFormatError)?
67        .parse::<usize>()
68        .map_err(|_| KzgErrors::ParseError)?;
69
70    if n_g1 != NUM_G1_POINTS {
71        return Err(KzgErrors::MismatchedNumberOfPoints);
72    }
73
74    if n_g2 != NUM_G2_POINTS {
75        return Err(KzgErrors::MismatchedNumberOfPoints);
76    }
77
78    // load g1 points
79    let mut g1_points = Box::<G1Points>::default();
80    for bytes in &mut g1_points.0 {
81        let line = lines.next().ok_or(KzgErrors::FileFormatError)?;
82        crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?;
83    }
84
85    // load g2 points
86    let mut g2_points = Box::<G2Points>::default();
87    for bytes in &mut g2_points.0 {
88        let line = lines.next().ok_or(KzgErrors::FileFormatError)?;
89        crate::hex::decode_to_slice(line, bytes).map_err(|_| KzgErrors::ParseError)?;
90    }
91
92    if lines.next().is_some() {
93        return Err(KzgErrors::FileFormatError);
94    }
95
96    Ok((g1_points, g2_points))
97}
98
99#[derive(Debug)]
100pub enum KzgErrors {
101    /// Failed to get current directory.
102    FailedCurrentDirectory,
103    /// The specified path does not exist.
104    PathNotExists,
105    /// Problems related to I/O.
106    IOError,
107    /// Not a valid file.
108    NotValidFile,
109    /// File is not properly formatted.
110    FileFormatError,
111    /// Not able to parse to usize.
112    ParseError,
113    /// Number of points does not match what is expected.
114    MismatchedNumberOfPoints,
115}
116
117impl fmt::Display for KzgErrors {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        let s = match self {
120            Self::FailedCurrentDirectory => "failed to get current directory",
121            Self::PathNotExists => "the specified path does not exist",
122            Self::IOError => "IO error",
123            Self::NotValidFile => "not a valid file",
124            Self::FileFormatError => "file is not properly formatted",
125            Self::ParseError => "could not parse as usize",
126            Self::MismatchedNumberOfPoints => "number of points does not match what is expected",
127        };
128        f.write_str(s)
129    }
130}
131
132#[cfg(feature = "std")]
133impl std::error::Error for KzgErrors {}