taceo_circom_types/
binfile.rs1use std::{
2 io::{Cursor, Read},
3 marker::PhantomData,
4};
5
6use ark_ec::pairing::Pairing;
7use ark_serialize::SerializationError;
8use byteorder::{LittleEndian, ReadBytesExt};
9use thiserror::Error;
10
11use crate::traits::CircomArkworksPairingBridge;
12
13pub(crate) type ZkeyParserResult<T> = std::result::Result<T, ZkeyParserError>;
14
15#[derive(Debug, Error)]
17pub enum ZkeyParserError {
18 #[error(transparent)]
20 SerializationError(#[from] SerializationError),
21 #[error("invalid modulus found in header for chosen curve")]
23 InvalidPrimeInHeader,
24 #[error("Unexpected field size for curve in header. Expected {0} but got {1}")]
26 UnexpectedByteSize(u32, u32),
27 #[error(transparent)]
29 IoError(#[from] std::io::Error),
30 #[error("bin file corrupted: \"{0}\"")]
32 CorruptedBinFile(String),
33}
34
35#[derive(Debug)]
36pub(crate) struct BinFile<P: Pairing + CircomArkworksPairingBridge> {
37 #[expect(dead_code)]
38 ftype: String,
39 #[expect(dead_code)]
40 version: u32,
41 sections: Vec<Vec<u8>>,
42 phantom_data: PhantomData<P>,
43}
44
45impl<P: Pairing + CircomArkworksPairingBridge> BinFile<P> {
46 pub(crate) fn new<R: Read>(reader: &mut R) -> ZkeyParserResult<Self> {
47 tracing::debug!("reading bin file");
48 let mut magic = [0u8; 4];
49 reader.read_exact(&mut magic)?;
50 let ftype = std::str::from_utf8(&magic[..])
51 .map_err(|_| ZkeyParserError::CorruptedBinFile("cannot parse magic number".to_owned()))?
52 .to_string();
53 tracing::debug!("file type for binfile: \"{ftype}\"");
54
55 let version = reader.read_u32::<LittleEndian>()?;
56 tracing::debug!("binfile version {}", version);
57
58 let num_sections: usize = reader
59 .read_u32::<LittleEndian>()?
60 .try_into()
61 .expect("u32 fits into usize");
62 tracing::debug!("we got {} sections in binfile", num_sections);
63 let mut sections = vec![vec![]; num_sections];
64
65 for _ in 0..num_sections {
66 let section_id: usize = reader
67 .read_u32::<LittleEndian>()?
68 .try_into()
69 .expect("u32 fits into usize");
70 let section_length: usize = reader
71 .read_u64::<LittleEndian>()?
72 .try_into()
73 .expect("u64 fits into usize");
74
75 let section = &mut sections[section_id - 1];
76 if !section.is_empty() {
77 return Err(ZkeyParserError::CorruptedBinFile(
78 "sections are empty!".to_owned(),
79 ));
80 }
81 section.resize(section_length, 0);
82 reader.read_exact(section)?;
83 }
84 tracing::debug!("successfully read bin file!");
85 Ok(Self {
86 ftype,
87 version,
88 sections,
89 phantom_data: PhantomData::<P>,
90 })
91 }
92
93 pub(crate) fn take_section(&mut self, id: usize) -> Cursor<Vec<u8>> {
94 Cursor::new(std::mem::take(&mut self.sections[id - 1]))
95 }
96
97 #[cfg(feature = "plonk")]
98 pub(crate) fn take_section_raw(&mut self, id: usize) -> Vec<u8> {
99 std::mem::take(&mut self.sections[id - 1])
100 }
101}