-
Notifications
You must be signed in to change notification settings - Fork 7
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
Replace the ark-zkey witness calculator with the one of iden3 #273
Changes from all commits
b50749f
e7ef534
7b9d12d
26f8fe7
07e13b0
89342cf
6bd3bac
66abbb3
2ec0bf0
f5ef486
854ede7
32319a2
91113c5
9bed433
0157ff6
d8232a5
fce6d9d
a39d571
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// This file is based on the code by iden3. Its preimage can be found here: | ||
// https://github.com/iden3/circom-witnesscalc/blob/5cb365b6e4d9052ecc69d4567fcf5bc061c20e94/src/lib.rs | ||
|
||
pub mod graph; | ||
pub mod proto; | ||
pub mod storage; | ||
|
||
use ark_bn254::Fr; | ||
use graph::Node; | ||
use num_bigint::BigInt; | ||
use ruint::aliases::U256; | ||
use std::collections::HashMap; | ||
use storage::deserialize_witnesscalc_graph; | ||
|
||
pub type InputSignalsInfo = HashMap<String, (usize, usize)>; | ||
|
||
pub fn calc_witness<I: IntoIterator<Item = (String, Vec<BigInt>)>>( | ||
inputs: I, | ||
graph_data: &[u8], | ||
) -> Vec<Fr> { | ||
let inputs: HashMap<String, Vec<U256>> = inputs | ||
.into_iter() | ||
.map(|(key, value)| (key, value.iter().map(|v| U256::from(v)).collect())) | ||
.collect(); | ||
|
||
let (nodes, signals, input_mapping): (Vec<Node>, Vec<usize>, InputSignalsInfo) = | ||
deserialize_witnesscalc_graph(std::io::Cursor::new(graph_data)).unwrap(); | ||
|
||
let mut inputs_buffer = get_inputs_buffer(get_inputs_size(&nodes)); | ||
populate_inputs(&inputs, &input_mapping, &mut inputs_buffer); | ||
|
||
graph::evaluate(&nodes, inputs_buffer.as_slice(), &signals) | ||
} | ||
|
||
fn get_inputs_size(nodes: &[Node]) -> usize { | ||
let mut start = false; | ||
let mut max_index = 0usize; | ||
for &node in nodes.iter() { | ||
if let Node::Input(i) = node { | ||
if i > max_index { | ||
max_index = i; | ||
} | ||
start = true | ||
} else if start { | ||
break; | ||
} | ||
} | ||
max_index + 1 | ||
} | ||
|
||
fn populate_inputs( | ||
input_list: &HashMap<String, Vec<U256>>, | ||
inputs_info: &InputSignalsInfo, | ||
input_buffer: &mut [U256], | ||
) { | ||
for (key, value) in input_list { | ||
let (offset, len) = inputs_info[key]; | ||
if len != value.len() { | ||
panic!("Invalid input length for {}", key); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the justification for a panic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree, we need to get the results back, not panic There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
UPDATE: I have studied all 3 places, where panic! is used, and I think that these case are justified. It seems that these pieces of code panic in situations, which cannot happen with correctly written code and correctly generated execution graph regardless of the user's input. So the condition checks leading to these "panics" can be considered as some fundamental sanity checks. The same is true regarding those unwraps that I have studied. By the way, the project contains 3 iden3 files with unwraps and 20 previous files with them. Thus, using these unwraps seems to be consistent with the code style. In most cases the iden3 code uses returning Results, which is the evidence of their understanding the principles of using panic!. Thus, there is no need in rewriting these panic! and unwrap fragments. |
||
} | ||
|
||
for (i, v) in value.iter().enumerate() { | ||
input_buffer[offset + i] = *v; | ||
} | ||
} | ||
} | ||
|
||
/// Allocates inputs vec with position 0 set to 1 | ||
fn get_inputs_buffer(size: usize) -> Vec<U256> { | ||
let mut inputs = vec![U256::ZERO; size]; | ||
inputs[0] = U256::from(1); | ||
inputs | ||
} |
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.
Add error return, not unwrap
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.
Agree.See #273 (comment)