@@ -7,9 +7,13 @@ use crate::bellman_ce::pairing::{
77} ;
88use crate :: circom_circuit:: Constraint ;
99use byteorder:: { LittleEndian , ReadBytesExt } ;
10- use std:: io:: { Error , ErrorKind , Read , Result } ;
10+ use std:: {
11+ collections:: HashMap ,
12+ io:: { Error , ErrorKind , Read , Result , Seek , SeekFrom } ,
13+ } ;
1114
1215// R1CSFile's header
16+ #[ derive( Debug , Default ) ]
1317pub struct Header {
1418 pub field_size : u32 ,
1519 pub prime_size : Vec < u8 > ,
@@ -22,6 +26,7 @@ pub struct Header {
2226}
2327
2428// R1CSFile parse result
29+ #[ derive( Debug , Default ) ]
2530pub struct R1CSFile < E : Engine > {
2631 pub version : u32 ,
2732 pub header : Header ,
@@ -92,7 +97,7 @@ fn read_map<R: Read>(mut reader: R, size: u64, header: &Header) -> Result<Vec<u6
9297 Ok ( vec)
9398}
9499
95- pub fn from_reader < R : Read > ( mut reader : R ) -> Result < R1CSFile < Bn256 > > {
100+ pub fn from_reader < R : Read + Seek > ( mut reader : R ) -> Result < R1CSFile < Bn256 > > {
96101 let mut magic = [ 0u8 ; 4 ] ;
97102 reader. read_exact ( & mut magic) ?;
98103 if magic != [ 0x72 , 0x31 , 0x63 , 0x73 ] {
@@ -107,24 +112,38 @@ pub fn from_reader<R: Read>(mut reader: R) -> Result<R1CSFile<Bn256>> {
107112
108113 let num_sections = reader. read_u32 :: < LittleEndian > ( ) ?;
109114
110- // todo: rewrite this to support different section order and unknown sections
111- // todo: handle sec_size correctly
112- let sec_type = reader. read_u32 :: < LittleEndian > ( ) ?;
113- let sec_size = reader. read_u64 :: < LittleEndian > ( ) ?;
114- let header = read_header ( & mut reader, sec_size) ?;
115+ // section type -> file offset
116+ let mut section_offsets = HashMap :: < u32 , u64 > :: new ( ) ;
117+ let mut section_sizes = HashMap :: < u32 , u64 > :: new ( ) ;
118+
119+ // get file offset of each section
120+ for _ in 0 ..num_sections {
121+ let section_type = reader. read_u32 :: < LittleEndian > ( ) ?;
122+ let section_size = reader. read_u64 :: < LittleEndian > ( ) ?;
123+ let offset = reader. seek ( SeekFrom :: Current ( 0 ) ) ?;
124+ section_offsets. insert ( section_type, offset) ;
125+ section_sizes. insert ( section_type, section_size) ;
126+ reader. seek ( SeekFrom :: Current ( section_size as i64 ) ) ?;
127+ }
128+
129+ let header_type = 1 ;
130+ let constraint_type = 2 ;
131+ let wire2label_type = 3 ;
132+
133+ reader. seek ( SeekFrom :: Start ( * section_offsets. get ( & header_type) . unwrap ( ) ) ) ?;
134+ let header = read_header ( & mut reader, * section_sizes. get ( & header_type) . unwrap ( ) ) ?;
115135 if header. field_size != 32 {
116136 return Err ( Error :: new ( ErrorKind :: InvalidData , "This parser only supports 32-byte fields" ) ) ;
117137 }
118138 if header. prime_size != hex ! ( "010000f093f5e1439170b97948e833285d588181b64550b829a031e1724e6430" ) {
119139 return Err ( Error :: new ( ErrorKind :: InvalidData , "This parser only supports bn256" ) ) ;
120140 }
121- let sec_type = reader. read_u32 :: < LittleEndian > ( ) ?;
122- let sec_size = reader. read_u64 :: < LittleEndian > ( ) ?;
123- let constraints = read_constraints :: < & mut R , Bn256 > ( & mut reader, sec_size, & header) ?;
124141
125- let sec_type = reader. read_u32 :: < LittleEndian > ( ) ?;
126- let sec_size = reader. read_u64 :: < LittleEndian > ( ) ?;
127- let wire_mapping = read_map ( & mut reader, sec_size, & header) ?;
142+ reader. seek ( SeekFrom :: Start ( * section_offsets. get ( & constraint_type) . unwrap ( ) ) ) ?;
143+ let constraints = read_constraints :: < & mut R , Bn256 > ( & mut reader, * section_sizes. get ( & constraint_type) . unwrap ( ) , & header) ?;
144+
145+ reader. seek ( SeekFrom :: Start ( * section_offsets. get ( & wire2label_type) . unwrap ( ) ) ) ?;
146+ let wire_mapping = read_map ( & mut reader, * section_sizes. get ( & wire2label_type) . unwrap ( ) , & header) ?;
128147
129148 Ok ( R1CSFile {
130149 version,
@@ -136,6 +155,8 @@ pub fn from_reader<R: Read>(mut reader: R) -> Result<R1CSFile<Bn256>> {
136155
137156#[ cfg( test) ]
138157mod tests {
158+ use std:: io:: { BufReader , Cursor } ;
159+
139160 use super :: * ;
140161
141162 #[ test]
@@ -193,7 +214,8 @@ mod tests {
193214 ) ;
194215
195216 use crate :: bellman_ce:: pairing:: ff;
196- let file = from_reader ( & data[ ..] ) . unwrap ( ) ;
217+ let reader = BufReader :: new ( Cursor :: new ( & data[ ..] ) ) ;
218+ let file = from_reader ( reader) . unwrap ( ) ;
197219 assert_eq ! ( file. version, 1 ) ;
198220
199221 assert_eq ! ( file. header. field_size, 32 ) ;
0 commit comments