1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

Merge branch 'master' of github.com:JacobEberhardt/ZoKrates into gm17

This commit is contained in:
schaeff 2018-12-07 17:54:08 +01:00
commit 57fc5453dd
16 changed files with 486 additions and 222 deletions

View file

@ -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

10
Cargo.lock generated
View file

@ -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"

View file

@ -1,25 +1,25 @@
<img src="http://www.redaktion.tu-berlin.de/fileadmin/fg308/icons/projekte/logos/ZoKrates_logo.svg" width="100%" height="180">
# Zokrates
# ZoKrates
[![Join the chat at https://gitter.im/ZoKrates/Lobby](https://badges.gitter.im/ZoKrates/Lobby.svg)](https://gitter.im/ZoKrates/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
![Jenkins](https://img.shields.io/jenkins/s/https/jenkins.kyroy.com/job/ZoKrates/job/master.svg?label=master)
![Jenkins](https://img.shields.io/jenkins/s/https/jenkins.kyroy.com/job/ZoKrates/job/develop.svg?label=develop)
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.

View file

@ -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, youve 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!
>ZoKrates would welcome ideas to add support for such ceremonies!

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_cli"
version = "0.3.1"
version = "0.3.2"
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"

View file

@ -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")

View file

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

View file

@ -272,7 +272,6 @@ pub enum FlatExpression<T: Field> {
Identifier(FlatVariable),
Add(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Sub(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Div(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Mult(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
}
@ -313,10 +312,6 @@ impl<T: Field> FlatExpression<T> {
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<T: Field> FlatExpression<T> {
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<T: Field> FlatExpression<T> {
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<T: Field> fmt::Display for FlatExpression<T> {
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<T: Field> fmt::Debug for FlatExpression<T> {
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<T: Field> From<FlatVariable> for FlatExpression<T> {
fn from(v: FlatVariable) -> FlatExpression<T> {
FlatExpression::Identifier(v)
}
}
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct FlatExpressionList<T: Field> {
pub expressions: Vec<FlatExpression<T>>,

View file

@ -692,17 +692,47 @@ impl Flattener {
statements_flattened,
right,
);
let new_left = {
let new_left: FlatExpression<T> = {
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<T> = {
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 = [ , , ]

View file

@ -17,16 +17,17 @@ pub struct DirectiveStatement<T: Field> {
}
impl<T: Field> DirectiveStatement<T> {
pub fn new(outputs: Vec<FlatVariable>, helper: Helper, inputs: Vec<FlatVariable>) -> Self {
pub fn new<E: Into<FlatExpression<T>>>(
outputs: Vec<FlatVariable>,
helper: Helper,
inputs: Vec<E>,
) -> 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,
}
}

View file

@ -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<T: Field> Executable<T> for RustHelper {
assert_eq!(num, T::zero());
Ok(res)
}
RustHelper::Div => Ok(vec![inputs[0].clone() / inputs[1].clone()]),
}
}
}

View file

@ -240,6 +240,19 @@ fn parse_factor1<T: Field>(
}
}
// parse an identifier or select or function call
fn parse_identified1<T: Field>(
x: String,
input: String,
position: Position,
) -> Result<(Expression<T>, String, Position), Error<T>> {
match next_token::<T>(&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<T: Field>(
input: &String,
pos: &Position,
@ -257,10 +270,9 @@ fn parse_factor<T: Field>(
},
Err(err) => Err(err),
},
(Token::Ide(x), s1, p1) => match next_token::<T>(&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<T: Field>(
match next_token::<T>(&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<T: Field>(
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<T: Field>(
match next_token::<T>(&input, &pos) {
(_, _, _) => match parse_expr(&input, &pos) {
Ok((e1, s1, p1)) => match next_token::<T>(&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<T: Field>(
},
Err(err) => Err(err),
},
(Token::Ide(x), s1, p1) => match next_token::<T>(&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 };

View file

@ -389,73 +389,79 @@ fn parse_statement1<T: Field>(
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)
);
}
}
}

View file

@ -193,51 +193,6 @@ fn r1cs_expression<T: Field>(
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<FlatVariable, usize> = 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
}
}
}

View file

@ -49,14 +49,6 @@ impl<T: Field> PropagateWithContext<T> for FlatExpression<T> {
(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))
);
}
}
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_fs_resolver"
version = "0.3.1"
version = "0.3.2"
authors = ["Thibaut Schaeffer <thibaut@schaeff.fr>"]
repository = "https://github.com/JacobEberhardt/ZoKrates.git"