Merge pull request #215 from Zokrates/patch/0.3.3
Add input binding checks on libsnark directives
This commit is contained in:
commit
fb911c46e3
13 changed files with 105 additions and 80 deletions
6
Cargo.lock
generated
6
Cargo.lock
generated
|
@ -623,7 +623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "zokrates_cli"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
@ -631,13 +631,13 @@ dependencies = [
|
|||
"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)",
|
||||
"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",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zokrates_core"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
dependencies = [
|
||||
"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)",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
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>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates.git"
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ fn main() {
|
|||
// cli specification using clap library
|
||||
let matches = App::new("ZoKrates")
|
||||
.setting(AppSettings::SubcommandRequiredElseHelp)
|
||||
.version("0.3.2")
|
||||
.version("0.3.3")
|
||||
.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!'")
|
||||
.subcommand(SubCommand::with_name("compile")
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_core"
|
||||
version = "0.3.2"
|
||||
version = "0.3.3"
|
||||
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
|
||||
repository = "https://github.com/JacobEberhardt/ZoKrates"
|
||||
readme = "README.md"
|
||||
|
|
|
@ -211,7 +211,9 @@ std::string r1cs_to_json(protoboard<FieldT> pb)
|
|||
r1cs_constraint_system<FieldT> constraints = pb.get_constraint_system();
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -492,7 +492,7 @@ impl Flattener {
|
|||
.into_iter()
|
||||
.map(|x| x.apply_direct_substitution(&replacement_map))
|
||||
.collect(),
|
||||
}
|
||||
};
|
||||
}
|
||||
FlatStatement::Definition(var, rhs) => {
|
||||
let new_var = self.issue_new_variable();
|
||||
|
|
|
@ -179,7 +179,7 @@ impl Importer {
|
|||
return Err(CompileError::ImportError(Error::new(format!(
|
||||
"Gadget {} not found",
|
||||
s
|
||||
))))
|
||||
))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ impl Importer {
|
|||
return Err(CompileError::ImportError(Error::new(format!(
|
||||
"Packing helper {} not found",
|
||||
s
|
||||
))))
|
||||
))));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -226,7 +226,7 @@ impl Importer {
|
|||
Err(err) => return Err(CompileError::ImportError(err.into())),
|
||||
},
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,14 +362,14 @@ pub fn parse_function_call<T: Field>(
|
|||
p = 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) => {
|
||||
return Err(Error {
|
||||
expected: vec![Token::Comma, Token::Close],
|
||||
got: t2,
|
||||
pos: p2,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +417,7 @@ pub fn parse_inline_array<T: Field>(
|
|||
expected: vec![Token::Comma, Token::RightBracket],
|
||||
got: t2,
|
||||
pos: p2,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Close],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e),
|
||||
|
@ -52,7 +52,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Open],
|
||||
got: t1,
|
||||
pos: p1,
|
||||
})
|
||||
});
|
||||
}
|
||||
}?;
|
||||
|
||||
|
@ -67,7 +67,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Close],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
Err(e) => return Err(e),
|
||||
|
@ -77,7 +77,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Open],
|
||||
got: t1,
|
||||
pos: p1,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
(t0, _, p0) => {
|
||||
|
@ -85,7 +85,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Arrow],
|
||||
got: t0,
|
||||
pos: p0,
|
||||
})
|
||||
});
|
||||
}
|
||||
}?;
|
||||
|
||||
|
@ -103,7 +103,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Unknown("".to_string())],
|
||||
got: t6,
|
||||
pos: p6,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
(t5, _, p5) => {
|
||||
|
@ -111,7 +111,7 @@ fn parse_function_header<T: Field>(
|
|||
expected: vec![Token::Colon],
|
||||
got: t5,
|
||||
pos: p5,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,7 @@ fn parse_function_arguments<T: Field>(
|
|||
expected: vec![Token::Comma, Token::Close],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ fn parse_function_arguments<T: Field>(
|
|||
expected: vec![Token::Comma, Token::Close],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ fn parse_function_arguments<T: Field>(
|
|||
],
|
||||
got: t4,
|
||||
pos: p4,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ fn parse_function_return_types<T: Field>(
|
|||
expected: vec![Token::Comma, Token::Close],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ fn parse_function_return_types<T: Field>(
|
|||
],
|
||||
got: t4,
|
||||
pos: p4,
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,14 +16,14 @@ pub fn parse_import<T: Field>(
|
|||
(Token::Path(code_path), s2, p2) => match next_token::<T>(&s2, &p2) {
|
||||
(Token::As, s3, p3) => match next_token(&s3, &p3) {
|
||||
(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) => {
|
||||
return Err(Error {
|
||||
expected: vec![Token::Ide("ide".to_string())],
|
||||
got: t4,
|
||||
pos: p4,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
(Token::Unknown(_), _, p3) => return Ok((Import::new(code_path), p3)),
|
||||
|
@ -35,7 +35,7 @@ pub fn parse_import<T: Field>(
|
|||
],
|
||||
got: t3,
|
||||
pos: p3,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
(t2, _, p2) => Err(Error {
|
||||
|
|
|
@ -47,7 +47,7 @@ pub fn parse_program<T: Field, R: BufRead>(reader: &mut R) -> Result<Prog<T>, Er
|
|||
expected: vec![Token::Def],
|
||||
got: t1,
|
||||
pos: p1,
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
None => break,
|
||||
|
|
|
@ -201,7 +201,7 @@ impl Checker {
|
|||
"Duplicate definition for function {} with signature {}",
|
||||
funct.id, funct.signature
|
||||
),
|
||||
})
|
||||
});
|
||||
}
|
||||
0 => {}
|
||||
_ => panic!("duplicate function declaration should have been caught"),
|
||||
|
|
|
@ -3,13 +3,14 @@ use flat_absy::{FlatExpression, FlatExpressionList, FlatFunction, FlatStatement}
|
|||
use flat_absy::{FlatParameter, FlatVariable};
|
||||
use helpers::{DirectiveStatement, Helper, LibsnarkGadgetHelper};
|
||||
use reduce::Reduce;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::BTreeMap;
|
||||
use types::{Signature, Type};
|
||||
|
||||
// for r1cs import, can be moved.
|
||||
// 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
|
||||
// constraints: [ // constraints verified by the witness
|
||||
// [
|
||||
|
@ -20,8 +21,9 @@ use types::{Signature, Type};
|
|||
// }
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct R1CS {
|
||||
pub input_count: usize,
|
||||
pub inputs: Vec<usize>,
|
||||
pub outputs: Vec<usize>,
|
||||
pub variable_count: usize,
|
||||
pub constraints: Vec<Constraint>,
|
||||
}
|
||||
|
||||
|
@ -106,38 +108,32 @@ impl<T: Field> Into<FlatFunction<T>> for DirectiveR1CS {
|
|||
fn into(self: DirectiveR1CS) -> FlatFunction<T> {
|
||||
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 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 variable_count = r1cs.variable_count;
|
||||
|
||||
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
|
||||
let mut statements: Vec<FlatStatement<T>> =
|
||||
r1cs.constraints.into_iter().map(|c| c.into()).collect();
|
||||
let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into());
|
||||
|
||||
// define the entire witness
|
||||
let variables = vec![0; variables_count]
|
||||
let variables = vec![0; variable_count]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| FlatVariable::new(i))
|
||||
.collect();
|
||||
|
||||
// define the inputs with dummy variables: arguments to the function and to the directive
|
||||
let input_variables: Vec<FlatVariable> = vec![0; r1cs.input_count]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| FlatVariable::new(i + variables_count))
|
||||
let input_variables: Vec<FlatVariable> = (0..r1cs.inputs.len())
|
||||
.map(|i| FlatVariable::new(i + variable_count))
|
||||
.collect();
|
||||
let arguments = input_variables
|
||||
.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
|
||||
match self.directive {
|
||||
LibsnarkGadgetHelper::Sha256Compress => {
|
||||
statements.insert(
|
||||
0,
|
||||
FlatStatement::Directive(DirectiveStatement {
|
||||
outputs: variables,
|
||||
inputs: inputs,
|
||||
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Compress),
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
LibsnarkGadgetHelper::Sha256Ethereum => {
|
||||
statements.insert(
|
||||
0,
|
||||
FlatStatement::Directive(DirectiveStatement {
|
||||
outputs: variables,
|
||||
inputs: inputs,
|
||||
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Ethereum),
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
let directive_statement = match self.directive {
|
||||
LibsnarkGadgetHelper::Sha256Compress => FlatStatement::Directive(DirectiveStatement {
|
||||
outputs: variables,
|
||||
inputs: inputs,
|
||||
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Compress),
|
||||
}),
|
||||
LibsnarkGadgetHelper::Sha256Ethereum => FlatStatement::Directive(DirectiveStatement {
|
||||
outputs: variables,
|
||||
inputs: inputs,
|
||||
helper: Helper::LibsnarkGadget(LibsnarkGadgetHelper::Sha256Ethereum),
|
||||
}),
|
||||
};
|
||||
|
||||
// insert a statement to return the subset of the witness
|
||||
statements.push(FlatStatement::Return(FlatExpressionList {
|
||||
let return_statement = FlatStatement::Return(FlatExpressionList {
|
||||
expressions: outputs,
|
||||
}));
|
||||
});
|
||||
|
||||
let statements = std::iter::once(directive_statement)
|
||||
.chain(input_binding_statements)
|
||||
.chain(constraint_statements)
|
||||
.chain(std::iter::once(return_statement))
|
||||
.collect();
|
||||
|
||||
FlatFunction {
|
||||
id: "main".to_owned(),
|
||||
|
@ -220,4 +211,36 @@ mod tests {
|
|||
let c: Constraint = serde_json::from_str(constraint).unwrap();
|
||||
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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue