diff --git a/Cargo.lock b/Cargo.lock index a7dec8f..e7134bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1346,7 +1346,7 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "plonkit" -version = "0.1.5" +version = "0.1.6" dependencies = [ "anyhow", "bellman_vk_codegen", diff --git a/Cargo.toml b/Cargo.toml index 0896a95..a1e62ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "plonkit" -version = "0.1.5" +version = "0.1.6" authors = [ "Roman Semenov ", "Zhuo Zhang ", "Haoyu LIN " ] description = "Library for working with circom circuits in plonk proof system" homepage = "https://github.com/fluidex/plonkit" diff --git a/README.md b/README.md index ec0c60e..4a323cd 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ A zkSNARK toolkit to work with [circom](https://github.com/iden3/circom) zkSNARKs DSL in [plonk](https://eprint.iacr.org/2019/953) proof system. Based on [zkutil](https://github.com/poma/zkutil) and [bellman_ce](https://github.com/matter-labs/bellman). ## Prerequisites -+ https://github.com/fluidex/snarkit + +1. install [circom](https://docs.circom.io/getting-started/installation/) into $PATH +2. install snarkit2 into $PATH: `npm install -g snarkit2` ## Features @@ -75,7 +77,7 @@ circuit.circom input.json setup_2^20.key # generate witness for this circuit # another option here is use the snarkjs/circom cli like contrib/process_circom_circuit.sh -> npx snarkit check . --witness_type bin --backend wasm +> snarkit2 check . --witness_type bin --backend wasm # Generate a snark proof using the universal setup monomial-form SRS diff --git a/package.json b/package.json index b8966a2..a3aa9a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plonkit", - "version": "0.1.5", + "version": "0.1.6", "description": "A zkSNARK toolkit to work with circom zkSNARKs DSL in plonk proof system", "main": "index.js", "scripts": { diff --git a/src/bin/main.rs b/src/bin/main.rs index f706c99..a03683a 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -18,7 +18,7 @@ use plonkit::recursive; /// A zkSNARK toolkit to work with circom zkSNARKs DSL in plonk proof system #[derive(Clap)] -#[clap(version = "0.0.4")] +#[clap(version = "0.1.6")] struct Opts { #[clap(subcommand)] command: SubCommand, diff --git a/src/r1cs_file.rs b/src/r1cs_file.rs index 42b2d1e..d00e557 100644 --- a/src/r1cs_file.rs +++ b/src/r1cs_file.rs @@ -7,9 +7,13 @@ use crate::bellman_ce::pairing::{ }; use crate::circom_circuit::Constraint; use byteorder::{LittleEndian, ReadBytesExt}; -use std::io::{Error, ErrorKind, Read, Result}; +use std::{ + collections::HashMap, + io::{Error, ErrorKind, Read, Result, Seek, SeekFrom}, +}; // R1CSFile's header +#[derive(Debug, Default)] pub struct Header { pub field_size: u32, pub prime_size: Vec, @@ -22,6 +26,7 @@ pub struct Header { } // R1CSFile parse result +#[derive(Debug, Default)] pub struct R1CSFile { pub version: u32, pub header: Header, @@ -92,7 +97,7 @@ fn read_map(mut reader: R, size: u64, header: &Header) -> Result(mut reader: R) -> Result> { +pub fn from_reader(mut reader: R) -> Result> { let mut magic = [0u8; 4]; reader.read_exact(&mut magic)?; if magic != [0x72, 0x31, 0x63, 0x73] { @@ -107,24 +112,38 @@ pub fn from_reader(mut reader: R) -> Result> { let num_sections = reader.read_u32::()?; - // todo: rewrite this to support different section order and unknown sections - // todo: handle sec_size correctly - let sec_type = reader.read_u32::()?; - let sec_size = reader.read_u64::()?; - let header = read_header(&mut reader, sec_size)?; + // section type -> file offset + let mut section_offsets = HashMap::::new(); + let mut section_sizes = HashMap::::new(); + + // get file offset of each section + for _ in 0..num_sections { + let section_type = reader.read_u32::()?; + let section_size = reader.read_u64::()?; + let offset = reader.seek(SeekFrom::Current(0))?; + section_offsets.insert(section_type, offset); + section_sizes.insert(section_type, section_size); + reader.seek(SeekFrom::Current(section_size as i64))?; + } + + let header_type = 1; + let constraint_type = 2; + let wire2label_type = 3; + + reader.seek(SeekFrom::Start(*section_offsets.get(&header_type).unwrap()))?; + let header = read_header(&mut reader, *section_sizes.get(&header_type).unwrap())?; if header.field_size != 32 { return Err(Error::new(ErrorKind::InvalidData, "This parser only supports 32-byte fields")); } if header.prime_size != hex!("010000f093f5e1439170b97948e833285d588181b64550b829a031e1724e6430") { return Err(Error::new(ErrorKind::InvalidData, "This parser only supports bn256")); } - let sec_type = reader.read_u32::()?; - let sec_size = reader.read_u64::()?; - let constraints = read_constraints::<&mut R, Bn256>(&mut reader, sec_size, &header)?; - let sec_type = reader.read_u32::()?; - let sec_size = reader.read_u64::()?; - let wire_mapping = read_map(&mut reader, sec_size, &header)?; + reader.seek(SeekFrom::Start(*section_offsets.get(&constraint_type).unwrap()))?; + let constraints = read_constraints::<&mut R, Bn256>(&mut reader, *section_sizes.get(&constraint_type).unwrap(), &header)?; + + reader.seek(SeekFrom::Start(*section_offsets.get(&wire2label_type).unwrap()))?; + let wire_mapping = read_map(&mut reader, *section_sizes.get(&wire2label_type).unwrap(), &header)?; Ok(R1CSFile { version, @@ -136,6 +155,8 @@ pub fn from_reader(mut reader: R) -> Result> { #[cfg(test)] mod tests { + use std::io::{BufReader, Cursor}; + use super::*; #[test] @@ -193,7 +214,8 @@ mod tests { ); use crate::bellman_ce::pairing::ff; - let file = from_reader(&data[..]).unwrap(); + let reader = BufReader::new(Cursor::new(&data[..])); + let file = from_reader(reader).unwrap(); assert_eq!(file.version, 1); assert_eq!(file.header.field_size, 32); diff --git a/src/reader.rs b/src/reader.rs index 71ee4c7..db345f5 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -3,7 +3,7 @@ use byteorder::{LittleEndian, ReadBytesExt}; use itertools::Itertools; use std::collections::BTreeMap; use std::fs::{File, OpenOptions}; -use std::io::{BufRead, BufReader, Read}; +use std::io::{BufRead, BufReader, Read, Seek}; use std::str; use crate::bellman_ce::{ @@ -224,7 +224,7 @@ fn load_r1cs_from_bin_file(filename: &str) -> (R1CS, Vec) { } /// load r1cs from bin by a reader -fn load_r1cs_from_bin(reader: R) -> (R1CS, Vec) { +fn load_r1cs_from_bin(reader: R) -> (R1CS, Vec) { let file = crate::r1cs_file::from_reader(reader).expect("unable to read."); let num_inputs = (1 + file.header.n_pub_in + file.header.n_pub_out) as usize; let num_variables = file.header.n_wires as usize;