-
Notifications
You must be signed in to change notification settings - Fork 64
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/better browser support #169
Open
CPerezz
wants to merge
13
commits into
main
Choose a base branch
from
feat/better_browser_support
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
39d4ee3
feat: Enable load_witness functionallity within FCircuit
CPerezz 039a400
feat: Enable browser-folding with passed-in witness
CPerezz 67a066d
chore: Add "browser" feature and leave CircomFCircuitBrowser under it
CPerezz 9bcf84c
chore: Address review leftovers
CPerezz 206984c
chore: Ammend review comments
CPerezz 0cf1aae
fix: leftover `parallel` feature code
CPerezz 47d908a
update: Remove `wasm` feature
CPerezz 5c67849
fix: Exclude constant 1 from zi_1 returned in browser::step_native
CPerezz 29ba23e
fix: Avoid whitespaces within features passed to CLI commands
CPerezz 291082e
fix: Clippy warns
CPerezz d2d543f
fix: CI feature typo
CPerezz 9946b86
Merge branch 'main' into feat/better_browser_support
CPerezz 63f599e
fix: Update CI package to test for WASM build to `frontends`
CPerezz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
use crate::frontend::FCircuit; | ||
use crate::frontend::FpVar::Var; | ||
use crate::Error; | ||
use ark_circom::circom::{CircomCircuit, R1CS as CircomR1CS}; | ||
use ark_circom::circom::{R1CSFile, R1CS}; | ||
use ark_ff::{BigInteger, PrimeField}; | ||
use ark_r1cs_std::alloc::AllocVar; | ||
use ark_r1cs_std::fields::fp::FpVar; | ||
use ark_relations::r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError}; | ||
use ark_std::fmt::Debug; | ||
use byteorder::{LittleEndian, ReadBytesExt}; | ||
use std::io::{BufReader, Cursor, Read}; | ||
use std::usize; | ||
|
||
/// This circuit is the one we will use in order to fold from the browser. | ||
/// | ||
/// A clear example on how to do all of this can be seen at: | ||
/// <https://github.com/CPerezz/wasm-sonobe-integration> | ||
#[derive(Clone, Debug)] | ||
pub struct CircomFCircuitBrowser<F: PrimeField> { | ||
pub state_len: usize, | ||
pub external_inputs_len: usize, | ||
pub witness: Vec<F>, | ||
pub r1cs: CircomR1CS<F>, | ||
} | ||
|
||
impl<F: PrimeField> FCircuit<F> for CircomFCircuitBrowser<F> { | ||
/// (r1cs_file_bytes, state_len, external_inputs_len) | ||
type Params = (Vec<u8>, usize, usize); | ||
|
||
fn new(params: Self::Params) -> Result<Self, Error> { | ||
let (r1cs_bytes, state_len, external_inputs_len) = params; | ||
let reader = BufReader::new(Cursor::new(&r1cs_bytes[..])); | ||
|
||
let mut r1cs: R1CS<F> = R1CSFile::<F>::new(reader) | ||
.expect("Error reading R1cs") | ||
.into(); | ||
|
||
// That's some weird magic. Ask @dmpierre | ||
r1cs.wire_mapping = None; | ||
|
||
Ok(Self { | ||
state_len, | ||
external_inputs_len, | ||
witness: vec![F::zero(); r1cs.num_variables], | ||
r1cs, | ||
}) | ||
} | ||
|
||
fn state_len(&self) -> usize { | ||
self.state_len | ||
} | ||
fn external_inputs_len(&self) -> usize { | ||
self.external_inputs_len | ||
} | ||
|
||
fn step_native( | ||
&self, | ||
_i: usize, | ||
z_i: Vec<F>, | ||
external_inputs: Vec<F>, | ||
) -> Result<Vec<F>, Error> { | ||
// Should we keep these? | ||
assert_eq!(z_i.len(), self.state_len()); | ||
assert_eq!(external_inputs.len(), self.external_inputs_len()); | ||
|
||
// Extracts the z_i1(next state) from the witness vector and external inputs. | ||
let z_i1 = z_i[1..1 + self.state_len()].to_vec(); | ||
Ok(z_i1) | ||
} | ||
|
||
fn generate_step_constraints( | ||
&self, | ||
cs: ConstraintSystemRef<F>, | ||
_i: usize, | ||
z_i: Vec<FpVar<F>>, | ||
_external_inputs: Vec<FpVar<F>>, | ||
) -> Result<Vec<FpVar<F>>, SynthesisError> { | ||
// Since public inputs are already allocated variables, we will tell `circom-compat` to not re-allocate those | ||
let mut already_allocated_public_inputs = vec![]; | ||
for var in z_i.iter() { | ||
match var { | ||
Var(var) => already_allocated_public_inputs.push(var.variable), | ||
_ => return Err(SynthesisError::Unsatisfiable), // allocated z_i should be Var | ||
} | ||
} | ||
|
||
// Initializes the CircomCircuit. | ||
let circom_circuit = CircomCircuit { | ||
r1cs: self.r1cs.clone(), | ||
witness: Some(self.witness.clone()), | ||
public_inputs_indexes: already_allocated_public_inputs, | ||
// Since public inputs are already allocated variables, we will tell `circom-compat` to not re-allocate those | ||
allocate_inputs_as_witnesses: true, | ||
}; | ||
|
||
// Generates the constraints for the circom_circuit. | ||
circom_circuit.generate_constraints(cs.clone())?; | ||
|
||
// Extracts the z_i1(next state) from the witness vector. | ||
let z_i1: Vec<FpVar<F>> = Vec::<FpVar<F>>::new_witness(cs.clone(), || { | ||
Ok(self.witness[1..1 + self.state_len()].to_vec()) | ||
})?; | ||
|
||
Ok(z_i1) | ||
} | ||
|
||
fn load_witness(&mut self, witness: Vec<F>) { | ||
self.witness = witness; | ||
} | ||
} | ||
|
||
/// Load Circom-generated witness from u8 array by a reader. | ||
/// | ||
/// This fn has been taken from <https://github.com/nalinbhardwaj/Nova-Scotia/blob/main/src/circom/file.rs> | ||
pub fn load_witness_from_bin_reader<R: Read, F: PrimeField>(mut reader: R) -> Vec<F> { | ||
let mut wtns_header = [0u8; 4]; | ||
reader.read_exact(&mut wtns_header).expect("read_error"); | ||
if wtns_header != [119, 116, 110, 115] { | ||
panic!("invalid file header"); | ||
} | ||
let version = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
if version > 2 { | ||
panic!("unsupported file version"); | ||
} | ||
let num_sections = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
if num_sections != 2 { | ||
panic!("invalid num sections"); | ||
} | ||
// read the first section | ||
let sec_type = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
if sec_type != 1 { | ||
panic!("invalid section type"); | ||
} | ||
let sec_size = reader.read_u64::<LittleEndian>().expect("read_error"); | ||
if sec_size != 4 + 32 + 4 { | ||
panic!("invalid section len") | ||
} | ||
let field_size: u32 = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
if field_size != 32 { | ||
panic!("invalid field byte size"); | ||
} | ||
let mut prime = vec![0u8; field_size as usize]; | ||
reader.read_exact(&mut prime).expect("read_error"); | ||
let witness_len: u32 = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
let sec_type = reader.read_u32::<LittleEndian>().expect("read_error"); | ||
if sec_type != 2 { | ||
panic!("invalid section type"); | ||
} | ||
let sec_size = reader.read_u64::<LittleEndian>().expect("read_error"); | ||
if sec_size != (witness_len * field_size) as u64 { | ||
panic!("invalid witness section size"); | ||
} | ||
let mut result = Vec::with_capacity(witness_len as usize); | ||
for _ in 0..witness_len { | ||
result.push(read_field::<&mut R, F>(&mut reader).expect("read_error")); | ||
} | ||
result | ||
} | ||
|
||
fn read_field<R: Read, F: PrimeField>( | ||
mut reader: R, | ||
) -> Result<F, ark_serialize::SerializationError> { | ||
let mut repr: Vec<u8> = F::ZERO.into_bigint().to_bytes_le(); | ||
for digit in repr.iter_mut() { | ||
*digit = reader.read_u8()?; | ||
} | ||
Ok(F::from_le_bytes_mod_order(&repr[..])) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like the formatting has some strange behaviour? Line 53 has 146 characters, while wrapping happens at line 78 at line 27.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. Unsure why this happens TBH. Let me try to fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hope 30a78d3 looks better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tried to solve it and makes the parser unhappy...
I don't think I can do much with this..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related: #169 (comment)