diff --git a/.circleci/config.yml b/.circleci/config.yml
index 78e4d63c..9d4ca794 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -26,7 +26,7 @@ jobs:
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" ./build.sh
- run:
name: Run tests
- command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release
+ command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --test-threads=1
- run:
name: Run integration tests
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --ignored
diff --git a/Cargo.lock b/Cargo.lock
index 93001cb3..8a6103c7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -623,7 +623,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "zokrates_cli"
-version = "0.3.1"
+version = "0.3.2"
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.1",
- "zokrates_fs_resolver 0.3.1",
+ "zokrates_core 0.3.2",
+ "zokrates_fs_resolver 0.3.2",
]
[[package]]
name = "zokrates_core"
-version = "0.3.1"
+version = "0.3.2"
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)",
@@ -658,7 +658,7 @@ dependencies = [
[[package]]
name = "zokrates_fs_resolver"
-version = "0.3.1"
+version = "0.3.2"
[metadata]
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
diff --git a/README.md b/README.md
index 7ec29708..25505365 100644
--- a/README.md
+++ b/README.md
@@ -1,25 +1,25 @@
-# Zokrates
+# ZoKrates
[](https://gitter.im/ZoKrates/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)


-Zokrates is a toolbox for zkSNARKs on Ethereum.
+ZoKrates is a toolbox for zkSNARKs on Ethereum.
_This is a proof-of-concept implementation. It has not been tested for production._
## Getting Started
-Have a look at the documentation [zokrates.github.io](https://zokrates.github.io/) for more informations about using Zokrates.
+Have a look at the [documentation](https://zokrates.github.io/) for more information about using ZoKrates.
A getting started tutorial can be found [here](https://zokrates.github.io/sha256example.html).
## Getting Help
-If you run into problems, Zokrates has a Gitter room. You can come ask for help at [gitter.im/ZoKrates/Lobby](https://gitter.im/ZoKrates/Lobby).
+If you run into problems, ZoKrates has a Gitter room. You can come ask for help on [Gitter](https://gitter.im/ZoKrates/Lobby).
## License
@@ -27,4 +27,6 @@ ZoKrates is released under the GNU Lesser General Public License v3.
## Contributing
+We happily welcome contributions. You can either pick an existing issue, or reach out on [Gitter](https://gitter.im/ZoKrates/Lobby).
+
Unless you explicitly state otherwise, any contribution you intentionally submit for inclusion in the work shall be licensed as above, without any additional terms or conditions.
diff --git a/zokrates_book/src/sha256example.md b/zokrates_book/src/sha256example.md
index eec971b4..dbf6d368 100644
--- a/zokrates_book/src/sha256example.md
+++ b/zokrates_book/src/sha256example.md
@@ -76,7 +76,7 @@ First, Victor has to specify what hash he is interested in. Therefore, we have t
```zokrates
import "LIBSNARK/sha256packed"
-def main(field a, field b, field c, field d) -> (field):
+def main(private field a, private field b, private field c, private field d) -> (field):
h0, h1 = sha256packed(a, b, c, d)
h0 == 263561599766550617289250058199814760685
h1 == 65303172752238645975888084098459749904
@@ -135,4 +135,4 @@ At this point, you’ve successfully ran you first zkSNARK on the Ethereum block
>
>In general, multiple parties may be interested in verifying the correctness of Alice's statement. For example, in the zero-knowledge based cryptocurrency Zcash, each node needs to be able to validate the correctness of transactions. In order to generalize the setup phase to these multi-party use-cases a tricky process, commonly referred to as “trusted setup” or "ceremony" needs to be conducted.
>
->ZoKrates would welcome ideas to add support for such ceremonies!
\ No newline at end of file
+>ZoKrates would welcome ideas to add support for such ceremonies!
diff --git a/zokrates_cli/Cargo.toml b/zokrates_cli/Cargo.toml
index 8fc4e2ce..e996099e 100644
--- a/zokrates_cli/Cargo.toml
+++ b/zokrates_cli/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "zokrates_cli"
-version = "0.3.1"
+version = "0.3.2"
authors = ["Jacob Eberhardt ", "Dennis Kuhnert ", "Thibaut Schaeffer "]
repository = "https://github.com/JacobEberhardt/ZoKrates.git"
diff --git a/zokrates_cli/src/bin.rs b/zokrates_cli/src/bin.rs
index ea5fb1dc..a0f77c95 100644
--- a/zokrates_cli/src/bin.rs
+++ b/zokrates_cli/src/bin.rs
@@ -41,7 +41,7 @@ fn main() {
// cli specification using clap library
let matches = App::new("ZoKrates")
.setting(AppSettings::SubcommandRequiredElseHelp)
- .version("0.3.1")
+ .version("0.3.2")
.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")
diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml
index 6ba8d14d..5c8a9899 100644
--- a/zokrates_core/Cargo.toml
+++ b/zokrates_core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "zokrates_core"
-version = "0.3.1"
+version = "0.3.2"
authors = ["Jacob Eberhardt ", "Dennis Kuhnert "]
repository = "https://github.com/JacobEberhardt/ZoKrates"
readme = "README.md"
diff --git a/zokrates_core/src/flat_absy/mod.rs b/zokrates_core/src/flat_absy/mod.rs
index 18373806..b163434d 100644
--- a/zokrates_core/src/flat_absy/mod.rs
+++ b/zokrates_core/src/flat_absy/mod.rs
@@ -272,7 +272,6 @@ pub enum FlatExpression {
Identifier(FlatVariable),
Add(Box>, Box>),
Sub(Box>, Box>),
- Div(Box>, Box>),
Mult(Box>, Box>),
}
@@ -313,10 +312,6 @@ impl FlatExpression {
box e1.apply_substitution(substitution, should_fallback),
box e2.apply_substitution(substitution, should_fallback),
),
- FlatExpression::Div(e1, e2) => FlatExpression::Div(
- box e1.apply_substitution(substitution, should_fallback),
- box e2.apply_substitution(substitution, should_fallback),
- ),
}
}
@@ -330,7 +325,6 @@ impl FlatExpression {
FlatExpression::Add(ref x, ref y) => x.solve(inputs) + y.solve(inputs),
FlatExpression::Sub(ref x, ref y) => x.solve(inputs) - y.solve(inputs),
FlatExpression::Mult(ref x, ref y) => x.solve(inputs) * y.solve(inputs),
- FlatExpression::Div(ref x, ref y) => x.solve(inputs) / y.solve(inputs),
}
}
@@ -340,14 +334,12 @@ impl FlatExpression {
FlatExpression::Add(ref x, ref y) | FlatExpression::Sub(ref x, ref y) => {
x.is_linear() && y.is_linear()
}
- FlatExpression::Mult(ref x, ref y) | FlatExpression::Div(ref x, ref y) => {
- match (x.clone(), y.clone()) {
- (box FlatExpression::Number(_), box FlatExpression::Number(_))
- | (box FlatExpression::Number(_), box FlatExpression::Identifier(_))
- | (box FlatExpression::Identifier(_), box FlatExpression::Number(_)) => true,
- _ => false,
- }
- }
+ FlatExpression::Mult(ref x, ref y) => match (x.clone(), y.clone()) {
+ (box FlatExpression::Number(_), box FlatExpression::Number(_))
+ | (box FlatExpression::Number(_), box FlatExpression::Identifier(_))
+ | (box FlatExpression::Identifier(_), box FlatExpression::Number(_)) => true,
+ _ => false,
+ },
}
}
}
@@ -360,7 +352,6 @@ impl fmt::Display for FlatExpression {
FlatExpression::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
FlatExpression::Sub(ref lhs, ref rhs) => write!(f, "({} - {})", lhs, rhs),
FlatExpression::Mult(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
- FlatExpression::Div(ref lhs, ref rhs) => write!(f, "({} / {})", lhs, rhs),
}
}
}
@@ -373,11 +364,16 @@ impl fmt::Debug for FlatExpression {
FlatExpression::Add(ref lhs, ref rhs) => write!(f, "Add({:?}, {:?})", lhs, rhs),
FlatExpression::Sub(ref lhs, ref rhs) => write!(f, "Sub({:?}, {:?})", lhs, rhs),
FlatExpression::Mult(ref lhs, ref rhs) => write!(f, "Mult({:?}, {:?})", lhs, rhs),
- FlatExpression::Div(ref lhs, ref rhs) => write!(f, "Div({:?}, {:?})", lhs, rhs),
}
}
}
+impl From for FlatExpression {
+ fn from(v: FlatVariable) -> FlatExpression {
+ FlatExpression::Identifier(v)
+ }
+}
+
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct FlatExpressionList {
pub expressions: Vec>,
diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs
index 9226390e..b542f516 100644
--- a/zokrates_core/src/flatten/mod.rs
+++ b/zokrates_core/src/flatten/mod.rs
@@ -692,17 +692,47 @@ impl Flattener {
statements_flattened,
right,
);
- let new_left = {
+ let new_left: FlatExpression = {
let id = self.use_sym();
statements_flattened.push(FlatStatement::Definition(id, left_flattened));
- FlatExpression::Identifier(id)
+ id.into()
};
- let new_right = {
+ let new_right: FlatExpression = {
let id = self.use_sym();
statements_flattened.push(FlatStatement::Definition(id, right_flattened));
- FlatExpression::Identifier(id)
+ id.into()
};
- FlatExpression::Div(box new_left, box new_right)
+
+ let invb = self.use_sym();
+ let inverse = self.use_sym();
+
+ // # invb = 1/b
+ statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new(
+ vec![invb],
+ Helper::Rust(RustHelper::Div),
+ vec![FlatExpression::Number(T::one()), new_right.clone()],
+ )));
+
+ // assert(invb * b == 1)
+ statements_flattened.push(FlatStatement::Condition(
+ FlatExpression::Number(T::one()),
+ FlatExpression::Mult(box invb.into(), box new_right.clone().into()),
+ ));
+
+ // # c = a/b
+ statements_flattened.push(FlatStatement::Directive(DirectiveStatement::new(
+ vec![inverse],
+ Helper::Rust(RustHelper::Div),
+ vec![new_left.clone(), new_right.clone()],
+ )));
+
+ // assert(c * b == a)
+ statements_flattened.push(FlatStatement::Condition(
+ new_left.into(),
+ FlatExpression::Mult(box new_right, box inverse.into()),
+ ));
+
+ inverse.into()
}
FieldElementExpression::Pow(box base, box exponent) => {
match exponent {
@@ -1935,6 +1965,121 @@ mod tests {
flattener.flatten_field_expression(&functions_flattened, &vec![], &mut vec![], expression);
}
+ #[test]
+ fn div() {
+ // a = 5 / b / b
+ let mut flattener = Flattener::new(FieldPrime::get_required_bits());
+ let mut functions_flattened = vec![];
+ let arguments_flattened = vec![];
+ let mut statements_flattened = vec![];
+
+ let definition = TypedStatement::Definition(
+ TypedAssignee::Identifier(Variable::field_element("b")),
+ FieldElementExpression::Number(FieldPrime::from(42)).into(),
+ );
+
+ let statement = TypedStatement::Definition(
+ TypedAssignee::Identifier(Variable::field_element("a")),
+ FieldElementExpression::Div(
+ box FieldElementExpression::Div(
+ box FieldElementExpression::Number(FieldPrime::from(5)),
+ box FieldElementExpression::Identifier(String::from("b")),
+ ),
+ box FieldElementExpression::Identifier(String::from("b")),
+ )
+ .into(),
+ );
+
+ flattener.flatten_statement(
+ &mut functions_flattened,
+ &arguments_flattened,
+ &mut statements_flattened,
+ definition,
+ );
+
+ flattener.flatten_statement(
+ &mut functions_flattened,
+ &arguments_flattened,
+ &mut statements_flattened,
+ statement,
+ );
+
+ // define b
+ let b = FlatVariable::new(0);
+ // define new wires for members of Div
+ let five = FlatVariable::new(1);
+ let b0 = FlatVariable::new(2);
+ // Define inverse of denominator to prevent div by 0
+ let invb0 = FlatVariable::new(3);
+ // Define inverse
+ let sym_0 = FlatVariable::new(4);
+ // Define result, which is first member to next Div
+ let sym_1 = FlatVariable::new(5);
+ // Define second member
+ let b1 = FlatVariable::new(6);
+ // Define inverse of denominator to prevent div by 0
+ let invb1 = FlatVariable::new(7);
+ // Define inverse
+ let sym_2 = FlatVariable::new(8);
+ // Define left hand side
+ let a = FlatVariable::new(9);
+
+ assert_eq!(
+ statements_flattened,
+ vec![
+ FlatStatement::Definition(b, FlatExpression::Number(FieldPrime::from(42))),
+ // inputs to first div (5/b)
+ FlatStatement::Definition(five, FlatExpression::Number(FieldPrime::from(5))),
+ FlatStatement::Definition(b0, b.into()),
+ // check div by 0
+ FlatStatement::Directive(DirectiveStatement::new(
+ vec![invb0],
+ Helper::Rust(RustHelper::Div),
+ vec![FlatExpression::Number(FieldPrime::from(1)), b0.into()]
+ )),
+ FlatStatement::Condition(
+ FlatExpression::Number(FieldPrime::from(1)),
+ FlatExpression::Mult(box invb0.into(), box b0.into()),
+ ),
+ // execute div
+ FlatStatement::Directive(DirectiveStatement::new(
+ vec![sym_0],
+ Helper::Rust(RustHelper::Div),
+ vec![five, b0]
+ )),
+ FlatStatement::Condition(
+ five.into(),
+ FlatExpression::Mult(box b0.into(), box sym_0.into()),
+ ),
+ // inputs to second div (res/b)
+ FlatStatement::Definition(sym_1, sym_0.into()),
+ FlatStatement::Definition(b1, b.into()),
+ // check div by 0
+ FlatStatement::Directive(DirectiveStatement::new(
+ vec![invb1],
+ Helper::Rust(RustHelper::Div),
+ vec![FlatExpression::Number(FieldPrime::from(1)), b1.into()]
+ )),
+ FlatStatement::Condition(
+ FlatExpression::Number(FieldPrime::from(1)),
+ FlatExpression::Mult(box invb1.into(), box b1.into()),
+ ),
+ // execute div
+ FlatStatement::Directive(DirectiveStatement::new(
+ vec![sym_2],
+ Helper::Rust(RustHelper::Div),
+ vec![sym_1, b1]
+ )),
+ FlatStatement::Condition(
+ sym_1.into(),
+ FlatExpression::Mult(box b1.into(), box sym_2.into()),
+ ),
+ // result
+ FlatStatement::Definition(a, sym_2.into()),
+ ]
+ );
+ }
+
#[test]
fn field_array() {
// foo = [ , , ]
diff --git a/zokrates_core/src/helpers/mod.rs b/zokrates_core/src/helpers/mod.rs
index e7de0a23..a939174e 100644
--- a/zokrates_core/src/helpers/mod.rs
+++ b/zokrates_core/src/helpers/mod.rs
@@ -17,16 +17,17 @@ pub struct DirectiveStatement {
}
impl DirectiveStatement {
- pub fn new(outputs: Vec, helper: Helper, inputs: Vec) -> Self {
+ pub fn new>>(
+ outputs: Vec,
+ helper: Helper,
+ inputs: Vec,
+ ) -> Self {
let (in_len, out_len) = helper.get_signature();
assert_eq!(in_len, inputs.len());
assert_eq!(out_len, outputs.len());
DirectiveStatement {
helper,
- inputs: inputs
- .into_iter()
- .map(|i| FlatExpression::Identifier(i))
- .collect(),
+ inputs: inputs.into_iter().map(|i| i.into()).collect(),
outputs,
}
}
diff --git a/zokrates_core/src/helpers/rust.rs b/zokrates_core/src/helpers/rust.rs
index 254e86b2..016e94b5 100644
--- a/zokrates_core/src/helpers/rust.rs
+++ b/zokrates_core/src/helpers/rust.rs
@@ -7,6 +7,7 @@ pub enum RustHelper {
Identity,
ConditionEq,
Bits,
+ Div,
}
impl fmt::Display for RustHelper {
@@ -15,6 +16,7 @@ impl fmt::Display for RustHelper {
RustHelper::Identity => write!(f, "Identity"),
RustHelper::ConditionEq => write!(f, "ConditionEq"),
RustHelper::Bits => write!(f, "Bits"),
+ RustHelper::Div => write!(f, "Div"),
}
}
}
@@ -25,6 +27,7 @@ impl Signed for RustHelper {
RustHelper::Identity => (1, 1),
RustHelper::ConditionEq => (1, 2),
RustHelper::Bits => (1, 254),
+ RustHelper::Div => (2, 1),
}
}
}
@@ -52,6 +55,7 @@ impl Executable for RustHelper {
assert_eq!(num, T::zero());
Ok(res)
}
+ RustHelper::Div => Ok(vec![inputs[0].clone() / inputs[1].clone()]),
}
}
}
diff --git a/zokrates_core/src/parser/parse/expression.rs b/zokrates_core/src/parser/parse/expression.rs
index 9247def9..2df658c3 100644
--- a/zokrates_core/src/parser/parse/expression.rs
+++ b/zokrates_core/src/parser/parse/expression.rs
@@ -240,6 +240,19 @@ fn parse_factor1(
}
}
+// parse an identifier or select or function call
+fn parse_identified1(
+ x: String,
+ input: String,
+ position: Position,
+) -> Result<(Expression, String, Position), Error> {
+ match next_token::(&input, &position) {
+ (Token::Open, s1, p1) => parse_function_call(x, s1, p1),
+ (Token::LeftBracket, s1, p1) => parse_array_select(x, s1, p1),
+ _ => Ok((Expression::Identifier(x), input, position)),
+ }
+}
+
fn parse_factor(
input: &String,
pos: &Position,
@@ -257,10 +270,9 @@ fn parse_factor(
},
Err(err) => Err(err),
},
- (Token::Ide(x), s1, p1) => match next_token::(&s1, &p1) {
- (Token::Open, s2, p2) => parse_function_call(x, s2, p2),
- (Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2),
- _ => parse_factor1(Expression::Identifier(x), s1, p1),
+ (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
+ Ok((e2, s2, p2)) => parse_factor1(e2, s2, p2),
+ e => e,
},
(Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1),
(t1, _, p1) => Err(Error {
@@ -338,10 +350,7 @@ pub fn parse_function_call(
match next_token::(&s, &p) {
// no arguments
(Token::Close, s1, p1) => {
- match parse_term1(Expression::FunctionCall(ide, args), s1, p1) {
- Ok((e2, s2, p2)) => return parse_expr1(e2, s2, p2),
- Err(err) => return Err(err),
- }
+ return parse_term1(Expression::FunctionCall(ide, args), s1, p1);
}
// at least one argument
(_, _, _) => match parse_expr(&s, &p) {
@@ -353,10 +362,7 @@ pub fn parse_function_call(
p = p2;
}
(Token::Close, s2, p2) => {
- match parse_term1(Expression::FunctionCall(ide, args), s2, p2) {
- Ok((e3, s3, p3)) => return parse_expr1(e3, s3, p3),
- Err(err) => return Err(err),
- }
+ return parse_term1(Expression::FunctionCall(ide, args), s2, p2)
}
(t2, _, p2) => {
return Err(Error {
@@ -430,14 +436,11 @@ pub fn parse_array_select(
match next_token::(&input, &pos) {
(_, _, _) => match parse_expr(&input, &pos) {
Ok((e1, s1, p1)) => match next_token::(&s1, &p1) {
- (Token::RightBracket, s2, p2) => match parse_term1(
+ (Token::RightBracket, s2, p2) => parse_term1(
Expression::Select(box Expression::Identifier(ide), box e1),
s2,
p2,
- ) {
- Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
- Err(err) => Err(err),
- },
+ ),
(t2, _, p2) => Err(Error {
expected: vec![Token::RightBracket],
got: t2,
@@ -469,13 +472,12 @@ pub fn parse_expr(
},
Err(err) => Err(err),
},
- (Token::Ide(x), s1, p1) => match next_token::(&s1, &p1) {
- (Token::Open, s2, p2) => parse_function_call(x, s2, p2),
- (Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2),
- _ => match parse_term1(Expression::Identifier(x), s1, p1) {
- Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
- Err(err) => Err(err),
+ (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
+ Ok((e2, s2, p2)) => match parse_term1(e2, s2, p2) {
+ Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
+ e => e,
},
+ e => e,
},
(Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) {
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
@@ -495,6 +497,169 @@ mod tests {
use super::*;
use field::FieldPrime;
+ mod terms {
+ use super::*;
+
+ #[test]
+ fn parse_number_sum() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 + 2 + 3");
+ let expr = Expression::Add(
+ box Expression::Add(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Number(FieldPrime::from(2)),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_number_sub() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 - 2 - 3");
+ let expr = Expression::Sub(
+ box Expression::Sub(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Number(FieldPrime::from(2)),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_function_call_single_sub() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 - f(a)");
+ let expr = Expression::Sub(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::FunctionCall(
+ String::from("f"),
+ vec![Expression::Identifier(String::from("a"))],
+ ),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_function_call_sub() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 - f() - 3");
+ let expr = Expression::Sub(
+ box Expression::Sub(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::FunctionCall(String::from("f"), vec![]),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_function_call_add() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 + f() + 3");
+ let expr = Expression::Add(
+ box Expression::Add(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::FunctionCall(String::from("f"), vec![]),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_select_sub() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 - f[2] - 3");
+ let expr = Expression::Sub(
+ box Expression::Sub(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Select(
+ box Expression::Identifier(String::from("f")),
+ box Expression::Number(FieldPrime::from(2)),
+ ),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_select_add() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 + f[2] + 3");
+ let expr = Expression::Add(
+ box Expression::Add(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Select(
+ box Expression::Identifier(String::from("f")),
+ box Expression::Number(FieldPrime::from(2)),
+ ),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_identifier_sub() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 - f - 3");
+ let expr = Expression::Sub(
+ box Expression::Sub(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Identifier(String::from("f")),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+
+ #[test]
+ fn parse_identifier_add() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("1 + f + 3");
+ let expr = Expression::Add(
+ box Expression::Add(
+ box Expression::Number(FieldPrime::from(1)),
+ box Expression::Identifier(String::from("f")),
+ ),
+ box Expression::Number(FieldPrime::from(3)),
+ );
+ assert_eq!(
+ Ok((expr, String::from(""), pos.col(string.len() as isize))),
+ parse_expr(&string, &pos)
+ );
+ }
+ }
+
#[test]
fn parse_if_then_else_ok() {
let pos = Position { line: 45, col: 121 };
diff --git a/zokrates_core/src/parser/parse/statement.rs b/zokrates_core/src/parser/parse/statement.rs
index 51d8e991..b5612b72 100644
--- a/zokrates_core/src/parser/parse/statement.rs
+++ b/zokrates_core/src/parser/parse/statement.rs
@@ -389,73 +389,79 @@ fn parse_statement1(
Err(err) => Err(err),
},
(Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) {
- Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
- (Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) {
- Ok((e5, s5, p5)) => match next_token(&s5, &p5) {
- (Token::InlineComment(_), ref s6, _) => {
- assert_eq!(s6, "");
- Ok((vec![Statement::Condition(e3, e5)], s5, p5))
- }
- (Token::Unknown(ref t6), ref s6, _) if t6 == "" => {
- assert_eq!(s6, "");
- Ok((vec![Statement::Condition(e3, e5)], s5, p5))
- }
- (t6, _, p6) => Err(Error {
- expected: vec![
- Token::Add,
- Token::Sub,
- Token::Pow,
- Token::Mult,
- Token::Div,
- Token::Unknown("".to_string()),
- ],
- got: t6,
- pos: p6,
- }),
+ Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
+ Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
+ (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
+ Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
+ (Token::InlineComment(_), ref s7, _) => {
+ assert_eq!(s7, "");
+ Ok((vec![Statement::Condition(e4, e6)], s6, p6))
+ }
+ (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
+ assert_eq!(s7, "");
+ Ok((vec![Statement::Condition(e4, e6)], s6, p6))
+ }
+ (t7, _, p7) => Err(Error {
+ expected: vec![
+ Token::Add,
+ Token::Sub,
+ Token::Pow,
+ Token::Mult,
+ Token::Div,
+ Token::Unknown("".to_string()),
+ ],
+ got: t7,
+ pos: p7,
+ }),
+ },
+ Err(err) => Err(err),
},
- Err(err) => Err(err),
+ (t4, _, p4) => Err(Error {
+ expected: vec![Token::Eqeq],
+ got: t4,
+ pos: p4,
+ }),
},
- (t4, _, p4) => Err(Error {
- expected: vec![Token::Eqeq],
- got: t4,
- pos: p4,
- }),
+ Err(err) => Err(err),
},
Err(err) => Err(err),
},
(Token::LeftBracket, s1, p1) => match parse_array_select(ide, s1, p1) {
- Ok((e3, s3, p3)) => match next_token(&s3, &p3) {
- (Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) {
- Ok((e5, s5, p5)) => match next_token(&s5, &p5) {
- (Token::InlineComment(_), ref s6, _) => {
- assert_eq!(s6, "");
- Ok((vec![Statement::Condition(e3, e5)], s5, p5))
- }
- (Token::Unknown(ref t6), ref s6, _) if t6 == "" => {
- assert_eq!(s6, "");
- Ok((vec![Statement::Condition(e3, e5)], s5, p5))
- }
- (t6, _, p6) => Err(Error {
- expected: vec![
- Token::Add,
- Token::Sub,
- Token::Pow,
- Token::Mult,
- Token::Div,
- Token::Unknown("".to_string()),
- ],
- got: t6,
- pos: p6,
- }),
+ Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
+ Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
+ (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
+ Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
+ (Token::InlineComment(_), ref s7, _) => {
+ assert_eq!(s7, "");
+ Ok((vec![Statement::Condition(e4, e6)], s6, p6))
+ }
+ (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
+ assert_eq!(s7, "");
+ Ok((vec![Statement::Condition(e4, e6)], s6, p6))
+ }
+ (t7, _, p7) => Err(Error {
+ expected: vec![
+ Token::Add,
+ Token::Sub,
+ Token::Pow,
+ Token::Mult,
+ Token::Div,
+ Token::Unknown("".to_string()),
+ ],
+ got: t7,
+ pos: p7,
+ }),
+ },
+ Err(err) => Err(err),
},
- Err(err) => Err(err),
+ (Token::Eq, s5, p5) => parse_definition1(Assignee::from(e4), s5, p5),
+ (t4, _, p4) => Err(Error {
+ expected: vec![Token::Eqeq],
+ got: t4,
+ pos: p4,
+ }),
},
- (Token::Eq, s4, p4) => parse_definition1(Assignee::from(e3), s4, p4),
- (t4, _, p4) => Err(Error {
- expected: vec![Token::Eqeq],
- got: t4,
- pos: p4,
- }),
+ Err(err) => Err(err),
},
Err(err) => Err(err),
},
@@ -580,5 +586,48 @@ mod tests {
parse_statement1(String::from("foo"), string, pos)
);
}
+
+ #[test]
+ fn left_call_in_assertion2() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("() - g() - 1 == 1");
+ let cond = Statement::Condition(
+ Expression::Sub(
+ box Expression::Sub(
+ box Expression::FunctionCall(String::from("foo"), vec![]),
+ box Expression::FunctionCall(String::from("g"), vec![]),
+ ),
+ box Expression::Number(FieldPrime::from(1)),
+ ),
+ Expression::Number(FieldPrime::from(1)),
+ );
+ assert_eq!(
+ Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
+ parse_statement1(String::from("foo"), string, pos)
+ );
+ }
+
+ #[test]
+ fn left_select_in_assertion2() {
+ let pos = Position { line: 45, col: 121 };
+ let string = String::from("[3] - g() - 1 == 1");
+ let cond = Statement::Condition(
+ Expression::Sub(
+ box Expression::Sub(
+ box Expression::Select(
+ box Expression::Identifier(String::from("foo")),
+ box Expression::Number(FieldPrime::from(3)),
+ ),
+ box Expression::FunctionCall(String::from("g"), vec![]),
+ ),
+ box Expression::Number(FieldPrime::from(1)),
+ ),
+ Expression::Number(FieldPrime::from(1)),
+ );
+ assert_eq!(
+ Ok((vec![cond], String::from(""), pos.col(string.len() as isize))),
+ parse_statement1(String::from("foo"), string, pos)
+ );
+ }
}
}
diff --git a/zokrates_core/src/r1cs.rs b/zokrates_core/src/r1cs.rs
index 5aef0582..c4bcc298 100644
--- a/zokrates_core/src/r1cs.rs
+++ b/zokrates_core/src/r1cs.rs
@@ -193,51 +193,6 @@ fn r1cs_expression(
c_row.push((provide_variable_idx(variables, &key), value));
}
}
- Div(lhs, rhs) => {
- // a / b = c --> c * b = a
- match lhs {
- box Number(x) => c_row.push((0, x)),
- box Identifier(x) => c_row.push((provide_variable_idx(variables, &x), T::one())),
- box e @ Add(..) => {
- for (key, value) in count_variables_add(&e) {
- c_row.push((provide_variable_idx(variables, &key), value));
- }
- }
- box e @ Sub(..) => {
- return r1cs_expression(
- Mult(box linear_expr, rhs),
- e,
- variables,
- a_row,
- b_row,
- c_row,
- )
- }
- box Mult(box Number(ref x1), box Number(ref x2)) => {
- c_row.push((0, x1.clone() * x2))
- }
- box Mult(box Number(ref x), box Identifier(ref v))
- | box Mult(box Identifier(ref v), box Number(ref x)) => {
- c_row.push((provide_variable_idx(variables, v), x.clone()))
- }
- e @ _ => panic!("(lhs) not supported: {:?}", e),
- };
- match rhs {
- box Number(x) => b_row.push((0, x)),
- box Identifier(x) => b_row.push((provide_variable_idx(variables, &x), T::one())),
- box Mult(box Number(ref x1), box Number(ref x2)) => {
- b_row.push((0, x1.clone() * x2))
- }
- box Mult(box Number(ref x), box Identifier(ref v))
- | box Mult(box Identifier(ref v), box Number(ref x)) => {
- b_row.push((provide_variable_idx(variables, v), x.clone()))
- }
- e @ _ => panic!("(rhs) not supported: {:?}", e),
- };
- for (key, value) in count_variables_add(&linear_expr) {
- a_row.push((provide_variable_idx(variables, &key), value));
- }
- }
Identifier(var) => {
a_row.push((provide_variable_idx(variables, &var), T::one()));
b_row.push((0, T::one()));
@@ -659,37 +614,5 @@ mod tests {
c_row
);
}
-
- #[test]
- fn div() {
- // x = (3 * x) / (y * 6) --> x * (y * 6) = 3 * x
-
- let one = FlatVariable::one();
- let x = FlatVariable::new(0);
- let y = FlatVariable::new(1);
-
- let lhs = Identifier(x);
- let rhs = Div(
- box Mult(box Number(FieldPrime::from(3)), box Identifier(x)),
- box Mult(box Identifier(y), box Number(FieldPrime::from(6))),
- );
-
- let mut a_row = Vec::new();
- let mut b_row = Vec::new();
- let mut c_row = Vec::new();
-
- let mut variables: HashMap = HashMap::new();
- variables.insert(one, 0);
- variables.insert(x, 1);
- variables.insert(y, 2);
-
- r1cs_expression(lhs, rhs, &mut variables, &mut a_row, &mut b_row, &mut c_row);
- a_row.sort_by(sort_tup);
- b_row.sort_by(sort_tup);
- c_row.sort_by(sort_tup);
- assert_eq!(vec![(1, FieldPrime::from(1))], a_row); // x
- assert_eq!(vec![(2, FieldPrime::from(6))], b_row); // y * 6
- assert_eq!(vec![(1, FieldPrime::from(3))], c_row); // 3 * x
- }
}
}
diff --git a/zokrates_core/src/static_analysis/flat_propagation.rs b/zokrates_core/src/static_analysis/flat_propagation.rs
index a57c9aee..f936fbfc 100644
--- a/zokrates_core/src/static_analysis/flat_propagation.rs
+++ b/zokrates_core/src/static_analysis/flat_propagation.rs
@@ -49,14 +49,6 @@ impl PropagateWithContext for FlatExpression {
(e1, e2) => FlatExpression::Mult(box e1, box e2),
}
}
- FlatExpression::Div(box e1, box e2) => {
- match (e1.propagate(constants), e2.propagate(constants)) {
- (FlatExpression::Number(n1), FlatExpression::Number(n2)) => {
- FlatExpression::Number(n1 / n2)
- }
- (e1, e2) => FlatExpression::Div(box e1, box e2),
- }
- }
}
}
}
@@ -173,19 +165,6 @@ mod tests {
FlatExpression::Number(FieldPrime::from(6))
);
}
-
- #[test]
- fn div() {
- let e = FlatExpression::Div(
- box FlatExpression::Number(FieldPrime::from(6)),
- box FlatExpression::Number(FieldPrime::from(2)),
- );
-
- assert_eq!(
- e.propagate(&mut HashMap::new()),
- FlatExpression::Number(FieldPrime::from(3))
- );
- }
}
}
}
diff --git a/zokrates_fs_resolver/Cargo.toml b/zokrates_fs_resolver/Cargo.toml
index 51179550..1a654ebe 100644
--- a/zokrates_fs_resolver/Cargo.toml
+++ b/zokrates_fs_resolver/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "zokrates_fs_resolver"
-version = "0.3.1"
+version = "0.3.2"
authors = ["Thibaut Schaeffer "]
repository = "https://github.com/JacobEberhardt/ZoKrates.git"