#![allow(dead_code, unused_imports)]
use std::ffi::CString;
use std::fs;
use std::path::{Path, PathBuf};
use std::slice;
const BYTES_PER_G1_POINT: usize = 48;
const BYTES_PER_G2_POINT: usize = 96;
fn main() {
generate_kzg_settings();
}
fn generate_kzg_settings() {
let out_dir = Path::new("src/kzg/");
let out_path = out_dir.join("generated.rs");
let in_path = Path::new("src/kzg/trusted_setup.txt");
println!("cargo:rerun-if-changed={}", in_path.display());
assert!(in_path.exists());
let contents = format_kzg_settings(in_path, out_dir);
fs::write(out_path, contents).unwrap();
}
fn format_kzg_settings(in_path: &Path, out_dir: &Path) -> String {
let contents = fs::read_to_string(in_path).unwrap();
let mut lines = contents.lines();
let n_g1 = lines.next().unwrap().parse::<usize>().unwrap();
let n_g2 = lines.next().unwrap().parse::<usize>().unwrap();
assert_eq!(n_g2, 65);
let mut g1_points = Vec::with_capacity(n_g1);
for _ in 0..n_g1 {
let line = lines.next().unwrap();
let mut bytes = [0; BYTES_PER_G1_POINT];
hex::decode_to_slice(line, &mut bytes).unwrap();
g1_points.push(bytes);
}
let mut g2_points = Vec::with_capacity(n_g2);
for _ in 0..n_g2 {
let line = lines.next().unwrap();
let mut bytes = [0; BYTES_PER_G2_POINT];
hex::decode_to_slice(line, &mut bytes).unwrap();
g2_points.push(bytes);
}
assert!(lines.next().is_none());
fs::write(out_dir.join("g1_points.bin"), into_flattened(g1_points)).unwrap();
fs::write(out_dir.join("g2_points.bin"), into_flattened(g2_points)).unwrap();
format!(
r#"// @generated by build.rs from {in_path:?}, do not modify manually.
pub use c_kzg::{{BYTES_PER_G1_POINT, BYTES_PER_G2_POINT}};
// Ensure that the build script constants are synced with the C bindings ones.
const _: [(); BYTES_PER_G1_POINT] = [(); {BYTES_PER_G1_POINT}];
const _: [(); BYTES_PER_G2_POINT] = [(); {BYTES_PER_G2_POINT}];
pub const NUM_G1_POINTS: usize = {n_g1};
pub const NUM_G2_POINTS: usize = {n_g2};
type G1Points = [[u8; BYTES_PER_G1_POINT]; NUM_G1_POINTS];
type G2Points = [[u8; BYTES_PER_G2_POINT]; NUM_G2_POINTS];
pub const G1_POINTS: &G1Points = {{
const BYTES: &[u8] = include_bytes!("./g1_points.bin");
assert!(BYTES.len() == core::mem::size_of::<G1Points>());
unsafe {{ &*BYTES.as_ptr().cast::<G1Points>() }}
}};
pub const G2_POINTS: &G2Points = {{
const BYTES: &[u8] = include_bytes!("./g2_points.bin");
assert!(BYTES.len() == core::mem::size_of::<G2Points>());
unsafe {{ &*BYTES.as_ptr().cast::<G2Points>() }}
}};
"#
)
}
#[inline]
fn into_flattened<T, const N: usize>(vec: Vec<[T; N]>) -> Vec<T> {
let (ptr, len, cap) = into_raw_parts(vec);
let (new_len, new_cap) = if core::mem::size_of::<T>() == 0 {
(len.checked_mul(N).expect("vec len overflow"), usize::MAX)
} else {
unsafe {
(
len.checked_mul(N).unwrap_unchecked(),
cap.checked_mul(N).unwrap_unchecked(),
)
}
};
unsafe { Vec::from_raw_parts(ptr.cast(), new_len, new_cap) }
}
#[inline(always)]
fn into_raw_parts<T>(vec: Vec<T>) -> (*mut T, usize, usize) {
let mut me = core::mem::ManuallyDrop::new(vec);
(me.as_mut_ptr(), me.len(), me.capacity())
}