alloy_eips/eip4844/
trusted_setup_points.rs

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