1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Merge pull request #215 from Zokrates/patch/0.3.3

Add input binding checks on libsnark directives
This commit is contained in:
JacobEberhardt 2019-01-07 16:44:08 +01:00 committed by GitHub
commit fb911c46e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 105 additions and 80 deletions

6
Cargo.lock generated
View file

@ -623,7 +623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]] [[package]]
name = "zokrates_cli" name = "zokrates_cli"
version = "0.3.2" version = "0.3.3"
dependencies = [ dependencies = [
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -631,13 +631,13 @@ dependencies = [
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
"zokrates_core 0.3.2", "zokrates_core 0.3.3",
"zokrates_fs_resolver 0.3.2", "zokrates_fs_resolver 0.3.2",
] ]
[[package]] [[package]]
name = "zokrates_core" name = "zokrates_core"
version = "0.3.2" version = "0.3.3"
dependencies = [ dependencies = [
"assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "assert_cli 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "bimap 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "zokrates_cli" name = "zokrates_cli"
version = "0.3.2" version = "0.3.3"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>", "Thibaut Schaeffer <thibaut@schaeff.fr>"] authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>", "Thibaut Schaeffer <thibaut@schaeff.fr>"]
repository = "https://github.com/JacobEberhardt/ZoKrates.git" repository = "https://github.com/JacobEberhardt/ZoKrates.git"

View file

@ -39,7 +39,7 @@ fn main() {
// cli specification using clap library // cli specification using clap library
let matches = App::new("ZoKrates") let matches = App::new("ZoKrates")
.setting(AppSettings::SubcommandRequiredElseHelp) .setting(AppSettings::SubcommandRequiredElseHelp)
.version("0.3.2") .version("0.3.3")
.author("Jacob Eberhardt, Thibaut Schaeffer, Dennis Kuhnert") .author("Jacob Eberhardt, Thibaut Schaeffer, Dennis Kuhnert")
.about("Supports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.\n'I know that I show nothing!'") .about("Supports generation of zkSNARKs from high level language code including Smart Contracts for proof verification on the Ethereum Blockchain.\n'I know that I show nothing!'")
.subcommand(SubCommand::with_name("compile") .subcommand(SubCommand::with_name("compile")

View file

@ -1,6 +1,6 @@
[package] [package]
name = "zokrates_core" name = "zokrates_core"
version = "0.3.2" version = "0.3.3"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"] authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
repository = "https://github.com/JacobEberhardt/ZoKrates" repository = "https://github.com/JacobEberhardt/ZoKrates"
readme = "README.md" readme = "README.md"

View file

@ -211,7 +211,9 @@ std::string r1cs_to_json(protoboard<FieldT> pb)
r1cs_constraint_system<FieldT> constraints = pb.get_constraint_system(); r1cs_constraint_system<FieldT> constraints = pb.get_constraint_system();
std::stringstream ss; std::stringstream ss;
ss << "{\"input_count\":512, \"outputs\":[513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768],\"constraints\":["; ss << "{\"variable_count\":";
ss << pb.num_variables() + 1; // ~one is not counted in pb.num_variables()
ss << ",\"inputs\":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370,371,372,373,374,375,376,377,378,379,380,381,382,383,384,385,386,387,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,438,439,440,441,442,443,444,445,446,447,448,449,450,451,452,453,454,455,456,457,458,459,460,461,462,463,464,465,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512], \"outputs\":[513,514,515,516,517,518,519,520,521,522,523,524,525,526,527,528,529,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586,587,588,589,590,591,592,593,594,595,596,597,598,599,600,601,602,603,604,605,606,607,608,609,610,611,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,627,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675,676,677,678,679,680,681,682,683,684,685,686,687,688,689,690,691,692,693,694,695,696,697,698,699,700,701,702,703,704,705,706,707,708,709,710,711,712,713,714,715,716,717,718,719,720,721,722,723,724,725,726,727,728,729,730,731,732,733,734,735,736,737,738,739,740,741,742,743,744,745,746,747,748,749,750,751,752,753,754,755,756,757,758,759,760,761,762,763,764,765,766,767,768],\"constraints\":[";
for (size_t c = 0; c < constraints.num_constraints(); ++c) for (size_t c = 0; c < constraints.num_constraints(); ++c)
{ {

View file

@ -492,7 +492,7 @@ impl Flattener {
.into_iter() .into_iter()
.map(|x| x.apply_direct_substitution(&replacement_map)) .map(|x| x.apply_direct_substitution(&replacement_map))
.collect(), .collect(),
} };
} }
FlatStatement::Definition(var, rhs) => { FlatStatement::Definition(var, rhs) => {
let new_var = self.issue_new_variable(); let new_var = self.issue_new_variable();

View file

@ -179,7 +179,7 @@ impl Importer {
return Err(CompileError::ImportError(Error::new(format!( return Err(CompileError::ImportError(Error::new(format!(
"Gadget {} not found", "Gadget {} not found",
s s
)))) ))));
} }
} }
} }
@ -207,7 +207,7 @@ impl Importer {
return Err(CompileError::ImportError(Error::new(format!( return Err(CompileError::ImportError(Error::new(format!(
"Packing helper {} not found", "Packing helper {} not found",
s s
)))) ))));
} }
} }
} else { } else {
@ -226,7 +226,7 @@ impl Importer {
Err(err) => return Err(CompileError::ImportError(err.into())), Err(err) => return Err(CompileError::ImportError(err.into())),
}, },
None => { None => {
return Err(Error::new("Can't resolve import without a resolver").into()) return Err(Error::new("Can't resolve import without a resolver").into());
} }
} }
} }

View file

@ -362,14 +362,14 @@ pub fn parse_function_call<T: Field>(
p = p2; p = p2;
} }
(Token::Close, s2, p2) => { (Token::Close, s2, p2) => {
return parse_term1(Expression::FunctionCall(ide, args), s2, p2) return parse_term1(Expression::FunctionCall(ide, args), s2, p2);
} }
(t2, _, p2) => { (t2, _, p2) => {
return Err(Error { return Err(Error {
expected: vec![Token::Comma, Token::Close], expected: vec![Token::Comma, Token::Close],
got: t2, got: t2,
pos: p2, pos: p2,
}) });
} }
} }
} }
@ -417,7 +417,7 @@ pub fn parse_inline_array<T: Field>(
expected: vec![Token::Comma, Token::RightBracket], expected: vec![Token::Comma, Token::RightBracket],
got: t2, got: t2,
pos: p2, pos: p2,
}) });
} }
} }
} }

View file

@ -42,7 +42,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Close], expected: vec![Token::Close],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
}, },
Err(e) => return Err(e), Err(e) => return Err(e),
@ -52,7 +52,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Open], expected: vec![Token::Open],
got: t1, got: t1,
pos: p1, pos: p1,
}) });
} }
}?; }?;
@ -67,7 +67,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Close], expected: vec![Token::Close],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
}, },
Err(e) => return Err(e), Err(e) => return Err(e),
@ -77,7 +77,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Open], expected: vec![Token::Open],
got: t1, got: t1,
pos: p1, pos: p1,
}) });
} }
}, },
(t0, _, p0) => { (t0, _, p0) => {
@ -85,7 +85,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Arrow], expected: vec![Token::Arrow],
got: t0, got: t0,
pos: p0, pos: p0,
}) });
} }
}?; }?;
@ -103,7 +103,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Unknown("".to_string())], expected: vec![Token::Unknown("".to_string())],
got: t6, got: t6,
pos: p6, pos: p6,
}) });
} }
}, },
(t5, _, p5) => { (t5, _, p5) => {
@ -111,7 +111,7 @@ fn parse_function_header<T: Field>(
expected: vec![Token::Colon], expected: vec![Token::Colon],
got: t5, got: t5,
pos: p5, pos: p5,
}) });
} }
} }
} }
@ -167,7 +167,7 @@ fn parse_function_arguments<T: Field>(
expected: vec![Token::Comma, Token::Close], expected: vec![Token::Comma, Token::Close],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
} }
} }
@ -188,7 +188,7 @@ fn parse_function_arguments<T: Field>(
expected: vec![Token::Comma, Token::Close], expected: vec![Token::Comma, Token::Close],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
} }
} }
@ -202,7 +202,7 @@ fn parse_function_arguments<T: Field>(
], ],
got: t4, got: t4,
pos: p4, pos: p4,
}) });
} }
} }
} }
@ -231,7 +231,7 @@ fn parse_function_return_types<T: Field>(
expected: vec![Token::Comma, Token::Close], expected: vec![Token::Comma, Token::Close],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
} }
} }
@ -245,7 +245,7 @@ fn parse_function_return_types<T: Field>(
], ],
got: t4, got: t4,
pos: p4, pos: p4,
}) });
} }
} }
} }

View file

@ -16,14 +16,14 @@ pub fn parse_import<T: Field>(
(Token::Path(code_path), s2, p2) => match next_token::<T>(&s2, &p2) { (Token::Path(code_path), s2, p2) => match next_token::<T>(&s2, &p2) {
(Token::As, s3, p3) => match next_token(&s3, &p3) { (Token::As, s3, p3) => match next_token(&s3, &p3) {
(Token::Ide(id), _, p4) => { (Token::Ide(id), _, p4) => {
return Ok((Import::new_with_alias(code_path, &id), p4)) return Ok((Import::new_with_alias(code_path, &id), p4));
} }
(t4, _, p4) => { (t4, _, p4) => {
return Err(Error { return Err(Error {
expected: vec![Token::Ide("ide".to_string())], expected: vec![Token::Ide("ide".to_string())],
got: t4, got: t4,
pos: p4, pos: p4,
}) });
} }
}, },
(Token::Unknown(_), _, p3) => return Ok((Import::new(code_path), p3)), (Token::Unknown(_), _, p3) => return Ok((Import::new(code_path), p3)),
@ -35,7 +35,7 @@ pub fn parse_import<T: Field>(
], ],
got: t3, got: t3,
pos: p3, pos: p3,
}) });
} }
}, },
(t2, _, p2) => Err(Error { (t2, _, p2) => Err(Error {

View file

@ -47,7 +47,7 @@ pub fn parse_program<T: Field, R: BufRead>(reader: &mut R) -> Result<Prog<T>, Er
expected: vec![Token::Def], expected: vec![Token::Def],
got: t1, got: t1,
pos: p1, pos: p1,
}) });
} }
}, },
None => break, None => break,

View file

@ -201,7 +201,7 @@ impl Checker {
"Duplicate definition for function {} with signature {}", "Duplicate definition for function {} with signature {}",
funct.id, funct.signature funct.id, funct.signature
), ),
}) });
} }
0 => {} 0 => {}
_ => panic!("duplicate function declaration should have been caught"), _ => panic!("duplicate function declaration should have been caught"),

View file

@ -3,13 +3,14 @@ use flat_absy::{FlatExpression, FlatExpressionList, FlatFunction, FlatStatement}
use flat_absy::{FlatParameter, FlatVariable}; use flat_absy::{FlatParameter, FlatVariable};
use helpers::{DirectiveStatement, Helper, LibsnarkGadgetHelper}; use helpers::{DirectiveStatement, Helper, LibsnarkGadgetHelper};
use reduce::Reduce; use reduce::Reduce;
use std::collections::{BTreeMap, HashSet}; use std::collections::BTreeMap;
use types::{Signature, Type}; use types::{Signature, Type};
// for r1cs import, can be moved. // for r1cs import, can be moved.
// r1cs data structure reflecting JSON standard format: // r1cs data structure reflecting JSON standard format:
// { // {
// input_count: count, // # of inputs to pass // variable_count: 435,
// inputs: [offset_1, offset_33], // # of inputs to pass
// outputs: [offset_42, offset_63, offset_55], // indices of the outputs in the witness // outputs: [offset_42, offset_63, offset_55], // indices of the outputs in the witness
// constraints: [ // constraints verified by the witness // constraints: [ // constraints verified by the witness
// [ // [
@ -20,8 +21,9 @@ use types::{Signature, Type};
// } // }
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct R1CS { pub struct R1CS {
pub input_count: usize, pub inputs: Vec<usize>,
pub outputs: Vec<usize>, pub outputs: Vec<usize>,
pub variable_count: usize,
pub constraints: Vec<Constraint>, pub constraints: Vec<Constraint>,
} }
@ -106,38 +108,32 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
fn into(self: DirectiveR1CS) -> FlatFunction<T> { fn into(self: DirectiveR1CS) -> FlatFunction<T> {
let r1cs = self.r1cs; let r1cs = self.r1cs;
// determine the number of variables, assuming there is no i so that column i is only zeroes in a, b and c let variable_count = r1cs.variable_count;
let mut variables_set = HashSet::new();
for constraint in r1cs.constraints.iter() {
for (key, _) in &constraint.a {
variables_set.insert(key.clone());
}
for (key, _) in &constraint.b {
variables_set.insert(key.clone());
}
for (key, _) in &constraint.c {
variables_set.insert(key.clone());
}
}
let variables_count = variables_set.len(); let input_binding_statements = std::iter::once(FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(T::from(1)),
))
.chain(r1cs.inputs.iter().enumerate().map(|(index, i)| {
FlatStatement::Condition(
FlatVariable::new(*i).into(),
FlatVariable::new(index + variable_count).into(),
)
}));
// insert flattened statements to represent constraints // insert flattened statements to represent constraints
let mut statements: Vec<FlatStatement<T>> = let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into());
r1cs.constraints.into_iter().map(|c| c.into()).collect();
// define the entire witness // define the entire witness
let variables = vec![0; variables_count] let variables = vec![0; variable_count]
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, _)| FlatVariable::new(i)) .map(|(i, _)| FlatVariable::new(i))
.collect(); .collect();
// define the inputs with dummy variables: arguments to the function and to the directive // define the inputs with dummy variables: arguments to the function and to the directive
let input_variables: Vec<FlatVariable> = vec![0; r1cs.input_count] let input_variables: Vec<FlatVariable> = (0..r1cs.inputs.len())
.iter() .map(|i| FlatVariable::new(i + variable_count))
.enumerate()
.map(|(i, _)| FlatVariable::new(i + variables_count))
.collect(); .collect();
let arguments = input_variables let arguments = input_variables
.iter() .iter()
@ -164,34 +160,29 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
}; };
// insert a directive to set the witness based on the libsnark gadget and inputs // insert a directive to set the witness based on the libsnark gadget and inputs
match self.directive { let directive_statement = match self.directive {
LibsnarkGadgetHelper::Sha256Compress => { LibsnarkGadgetHelper::Sha256Compress => FlatStatement::Directive(DirectiveStatement {
statements.insert( outputs: variables,
0, inputs: inputs,
FlatStatement::Directive(DirectiveStatement { helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Compress),
outputs: variables, }),
inputs: inputs, LibsnarkGadgetHelper::Sha256Ethereum => FlatStatement::Directive(DirectiveStatement {
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Compress), outputs: variables,
}), inputs: inputs,
); helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Ethereum),
} }),
};
LibsnarkGadgetHelper::Sha256Ethereum => {
statements.insert(
0,
FlatStatement::Directive(DirectiveStatement {
outputs: variables,
inputs: inputs,
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Ethereum),
}),
);
}
}
// insert a statement to return the subset of the witness // insert a statement to return the subset of the witness
statements.push(FlatStatement::Return(FlatExpressionList { let return_statement = FlatStatement::Return(FlatExpressionList {
expressions: outputs, expressions: outputs,
})); });
let statements = std::iter::once(directive_statement)
.chain(input_binding_statements)
.chain(constraint_statements)
.chain(std::iter::once(return_statement))
.collect();
FlatFunction { FlatFunction {
id: "main".to_owned(), id: "main".to_owned(),
@ -220,4 +211,36 @@ mod tests {
let c: Constraint = serde_json::from_str(constraint).unwrap(); let c: Constraint = serde_json::from_str(constraint).unwrap();
let _statement: FlatStatement<FieldPrime> = c.into(); let _statement: FlatStatement<FieldPrime> = c.into();
} }
#[test]
fn generate_sha256_constraints() {
use flat_absy::FlatProg;
use libsnark::get_sha256_constraints;
let r1cs: R1CS = serde_json::from_str(&get_sha256_constraints()).unwrap();
let v_count = r1cs.variable_count;
let dr1cs: DirectiveR1CS = DirectiveR1CS {
r1cs,
directive: LibsnarkGadgetHelper::Sha256Compress,
};
let compiled: FlatProg<FieldPrime> = FlatProg::from(dr1cs);
// libsnark variable #0: index 0 should equal 1
assert_eq!(
compiled.functions[0].statements[1],
FlatStatement::Condition(
FlatVariable::new(0).into(),
FlatExpression::Number(FieldPrime::from(1))
)
);
// libsnark input #0: index 1 should equal zokrates input #0: index v_count
assert_eq!(
compiled.functions[0].statements[2],
FlatStatement::Condition(
FlatVariable::new(1).into(),
FlatVariable::new(v_count).into()
)
);
}
} }