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 command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" ./build.sh
- run: - run:
name: Run tests 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: - run:
name: Run integration tests name: Run integration tests
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --ignored 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]] [[package]]
name = "zokrates_cli" name = "zokrates_cli"
version = "0.3.1" version = "0.3.2"
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.1", "zokrates_core 0.3.2",
"zokrates_fs_resolver 0.3.1", "zokrates_fs_resolver 0.3.2",
] ]
[[package]] [[package]]
name = "zokrates_core" name = "zokrates_core"
version = "0.3.1" version = "0.3.2"
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)",
@ -658,7 +658,7 @@ dependencies = [
[[package]] [[package]]
name = "zokrates_fs_resolver" name = "zokrates_fs_resolver"
version = "0.3.1" version = "0.3.2"
[metadata] [metadata]
"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "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"> <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) [![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/master.svg?label=master)
![Jenkins](https://img.shields.io/jenkins/s/https/jenkins.kyroy.com/job/ZoKrates/job/develop.svg?label=develop) ![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._ _This is a proof-of-concept implementation. It has not been tested for production._
## Getting Started ## 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). A getting started tutorial can be found [here](https://zokrates.github.io/sha256example.html).
## Getting Help ## 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 ## License
@ -27,4 +27,6 @@ ZoKrates is released under the GNU Lesser General Public License v3.
## Contributing ## 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. 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 ```zokrates
import "LIBSNARK/sha256packed" 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, h1 = sha256packed(a, b, c, d)
h0 == 263561599766550617289250058199814760685 h0 == 263561599766550617289250058199814760685
h1 == 65303172752238645975888084098459749904 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. >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] [package]
name = "zokrates_cli" 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>"] 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

@ -41,7 +41,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.1") .version("0.3.2")
.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.1" version = "0.3.2"
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

@ -272,7 +272,6 @@ pub enum FlatExpression<T: Field> {
Identifier(FlatVariable), Identifier(FlatVariable),
Add(Box<FlatExpression<T>>, Box<FlatExpression<T>>), Add(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
Sub(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>>), Mult(Box<FlatExpression<T>>, Box<FlatExpression<T>>),
} }
@ -313,10 +312,6 @@ impl<T: Field> FlatExpression<T> {
box e1.apply_substitution(substitution, should_fallback), box e1.apply_substitution(substitution, should_fallback),
box e2.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::Add(ref x, ref y) => x.solve(inputs) + y.solve(inputs),
FlatExpression::Sub(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::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) => { FlatExpression::Add(ref x, ref y) | FlatExpression::Sub(ref x, ref y) => {
x.is_linear() && y.is_linear() x.is_linear() && y.is_linear()
} }
FlatExpression::Mult(ref x, ref y) | FlatExpression::Div(ref x, ref y) => { FlatExpression::Mult(ref x, ref y) => match (x.clone(), y.clone()) {
match (x.clone(), y.clone()) { (box FlatExpression::Number(_), box FlatExpression::Number(_))
(box FlatExpression::Number(_), box FlatExpression::Number(_)) | (box FlatExpression::Number(_), box FlatExpression::Identifier(_))
| (box FlatExpression::Number(_), box FlatExpression::Identifier(_)) | (box FlatExpression::Identifier(_), box FlatExpression::Number(_)) => true,
| (box FlatExpression::Identifier(_), box FlatExpression::Number(_)) => true, _ => false,
_ => false, },
}
}
} }
} }
} }
@ -360,7 +352,6 @@ impl<T: Field> fmt::Display for FlatExpression<T> {
FlatExpression::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs), FlatExpression::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
FlatExpression::Sub(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::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::Add(ref lhs, ref rhs) => write!(f, "Add({:?}, {:?})", lhs, rhs),
FlatExpression::Sub(ref lhs, ref rhs) => write!(f, "Sub({:?}, {:?})", 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::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)] #[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct FlatExpressionList<T: Field> { pub struct FlatExpressionList<T: Field> {
pub expressions: Vec<FlatExpression<T>>, pub expressions: Vec<FlatExpression<T>>,

View file

@ -692,17 +692,47 @@ impl Flattener {
statements_flattened, statements_flattened,
right, right,
); );
let new_left = { let new_left: FlatExpression<T> = {
let id = self.use_sym(); let id = self.use_sym();
statements_flattened.push(FlatStatement::Definition(id, left_flattened)); 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(); let id = self.use_sym();
statements_flattened.push(FlatStatement::Definition(id, right_flattened)); 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) => { FieldElementExpression::Pow(box base, box exponent) => {
match exponent { match exponent {
@ -1935,6 +1965,121 @@ mod tests {
flattener.flatten_field_expression(&functions_flattened, &vec![], &mut vec![], expression); 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] #[test]
fn field_array() { fn field_array() {
// foo = [ , , ] // foo = [ , , ]

View file

@ -17,16 +17,17 @@ pub struct DirectiveStatement<T: Field> {
} }
impl<T: Field> DirectiveStatement<T> { 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(); let (in_len, out_len) = helper.get_signature();
assert_eq!(in_len, inputs.len()); assert_eq!(in_len, inputs.len());
assert_eq!(out_len, outputs.len()); assert_eq!(out_len, outputs.len());
DirectiveStatement { DirectiveStatement {
helper, helper,
inputs: inputs inputs: inputs.into_iter().map(|i| i.into()).collect(),
.into_iter()
.map(|i| FlatExpression::Identifier(i))
.collect(),
outputs, outputs,
} }
} }

View file

@ -7,6 +7,7 @@ pub enum RustHelper {
Identity, Identity,
ConditionEq, ConditionEq,
Bits, Bits,
Div,
} }
impl fmt::Display for RustHelper { impl fmt::Display for RustHelper {
@ -15,6 +16,7 @@ impl fmt::Display for RustHelper {
RustHelper::Identity => write!(f, "Identity"), RustHelper::Identity => write!(f, "Identity"),
RustHelper::ConditionEq => write!(f, "ConditionEq"), RustHelper::ConditionEq => write!(f, "ConditionEq"),
RustHelper::Bits => write!(f, "Bits"), RustHelper::Bits => write!(f, "Bits"),
RustHelper::Div => write!(f, "Div"),
} }
} }
} }
@ -25,6 +27,7 @@ impl Signed for RustHelper {
RustHelper::Identity => (1, 1), RustHelper::Identity => (1, 1),
RustHelper::ConditionEq => (1, 2), RustHelper::ConditionEq => (1, 2),
RustHelper::Bits => (1, 254), RustHelper::Bits => (1, 254),
RustHelper::Div => (2, 1),
} }
} }
} }
@ -52,6 +55,7 @@ impl<T: Field> Executable<T> for RustHelper {
assert_eq!(num, T::zero()); assert_eq!(num, T::zero());
Ok(res) 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>( fn parse_factor<T: Field>(
input: &String, input: &String,
pos: &Position, pos: &Position,
@ -257,10 +270,9 @@ fn parse_factor<T: Field>(
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) { (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
(Token::Open, s2, p2) => parse_function_call(x, s2, p2), Ok((e2, s2, p2)) => parse_factor1(e2, s2, p2),
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2), e => e,
_ => parse_factor1(Expression::Identifier(x), s1, p1),
}, },
(Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1), (Token::Num(x), s1, p1) => parse_factor1(Expression::Number(x), s1, p1),
(t1, _, p1) => Err(Error { (t1, _, p1) => Err(Error {
@ -338,10 +350,7 @@ pub fn parse_function_call<T: Field>(
match next_token::<T>(&s, &p) { match next_token::<T>(&s, &p) {
// no arguments // no arguments
(Token::Close, s1, p1) => { (Token::Close, s1, p1) => {
match parse_term1(Expression::FunctionCall(ide, args), s1, p1) { return parse_term1(Expression::FunctionCall(ide, args), s1, p1);
Ok((e2, s2, p2)) => return parse_expr1(e2, s2, p2),
Err(err) => return Err(err),
}
} }
// at least one argument // at least one argument
(_, _, _) => match parse_expr(&s, &p) { (_, _, _) => match parse_expr(&s, &p) {
@ -353,10 +362,7 @@ pub fn parse_function_call<T: Field>(
p = p2; p = p2;
} }
(Token::Close, s2, p2) => { (Token::Close, s2, p2) => {
match parse_term1(Expression::FunctionCall(ide, args), s2, p2) { return parse_term1(Expression::FunctionCall(ide, args), s2, p2)
Ok((e3, s3, p3)) => return parse_expr1(e3, s3, p3),
Err(err) => return Err(err),
}
} }
(t2, _, p2) => { (t2, _, p2) => {
return Err(Error { return Err(Error {
@ -430,14 +436,11 @@ pub fn parse_array_select<T: Field>(
match next_token::<T>(&input, &pos) { match next_token::<T>(&input, &pos) {
(_, _, _) => match parse_expr(&input, &pos) { (_, _, _) => match parse_expr(&input, &pos) {
Ok((e1, s1, p1)) => match next_token::<T>(&s1, &p1) { 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), Expression::Select(box Expression::Identifier(ide), box e1),
s2, s2,
p2, p2,
) { ),
Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
Err(err) => Err(err),
},
(t2, _, p2) => Err(Error { (t2, _, p2) => Err(Error {
expected: vec![Token::RightBracket], expected: vec![Token::RightBracket],
got: t2, got: t2,
@ -469,13 +472,12 @@ pub fn parse_expr<T: Field>(
}, },
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Ide(x), s1, p1) => match next_token::<T>(&s1, &p1) { (Token::Ide(x), s1, p1) => match parse_identified1(x, s1, p1) {
(Token::Open, s2, p2) => parse_function_call(x, s2, p2), Ok((e2, s2, p2)) => match parse_term1(e2, s2, p2) {
(Token::LeftBracket, s2, p2) => parse_array_select(x, s2, p2), Ok((e3, s3, p3)) => parse_expr1(e3, s3, p3),
_ => match parse_term1(Expression::Identifier(x), s1, p1) { e => e,
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
Err(err) => Err(err),
}, },
e => e,
}, },
(Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) { (Token::Num(x), s1, p1) => match parse_term1(Expression::Number(x), s1, p1) {
Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2), Ok((e2, s2, p2)) => parse_expr1(e2, s2, p2),
@ -495,6 +497,169 @@ mod tests {
use super::*; use super::*;
use field::FieldPrime; 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] #[test]
fn parse_if_then_else_ok() { fn parse_if_then_else_ok() {
let pos = Position { line: 45, col: 121 }; let pos = Position { line: 45, col: 121 };

View file

@ -389,73 +389,79 @@ fn parse_statement1<T: Field>(
Err(err) => Err(err), Err(err) => Err(err),
}, },
(Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) { (Token::Open, s1, p1) => match parse_function_call(ide, s1, p1) {
Ok((e3, s3, p3)) => match next_token(&s3, &p3) { Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) { Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
Ok((e5, s5, p5)) => match next_token(&s5, &p5) { (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
(Token::InlineComment(_), ref s6, _) => { Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
assert_eq!(s6, ""); (Token::InlineComment(_), ref s7, _) => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => { }
assert_eq!(s6, ""); (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(t6, _, p6) => Err(Error { }
expected: vec![ (t7, _, p7) => Err(Error {
Token::Add, expected: vec![
Token::Sub, Token::Add,
Token::Pow, Token::Sub,
Token::Mult, Token::Pow,
Token::Div, Token::Mult,
Token::Unknown("".to_string()), Token::Div,
], Token::Unknown("".to_string()),
got: t6, ],
pos: p6, 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 { Err(err) => Err(err),
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) { (Token::LeftBracket, s1, p1) => match parse_array_select(ide, s1, p1) {
Ok((e3, s3, p3)) => match next_token(&s3, &p3) { Ok((e3, s3, p3)) => match parse_expr1(e3, s3, p3) {
(Token::Eqeq, s4, p4) => match parse_expr(&s4, &p4) { Ok((e4, s4, p4)) => match next_token(&s4, &p4) {
Ok((e5, s5, p5)) => match next_token(&s5, &p5) { (Token::Eqeq, s5, p5) => match parse_expr(&s5, &p5) {
(Token::InlineComment(_), ref s6, _) => { Ok((e6, s6, p6)) => match next_token(&s6, &p6) {
assert_eq!(s6, ""); (Token::InlineComment(_), ref s7, _) => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(Token::Unknown(ref t6), ref s6, _) if t6 == "" => { }
assert_eq!(s6, ""); (Token::Unknown(ref t7), ref s7, _) if t7 == "" => {
Ok((vec![Statement::Condition(e3, e5)], s5, p5)) assert_eq!(s7, "");
} Ok((vec![Statement::Condition(e4, e6)], s6, p6))
(t6, _, p6) => Err(Error { }
expected: vec![ (t7, _, p7) => Err(Error {
Token::Add, expected: vec![
Token::Sub, Token::Add,
Token::Pow, Token::Sub,
Token::Mult, Token::Pow,
Token::Div, Token::Mult,
Token::Unknown("".to_string()), Token::Div,
], Token::Unknown("".to_string()),
got: t6, ],
pos: p6, 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), Err(err) => Err(err),
(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) 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)); 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) => { Identifier(var) => {
a_row.push((provide_variable_idx(variables, &var), T::one())); a_row.push((provide_variable_idx(variables, &var), T::one()));
b_row.push((0, T::one())); b_row.push((0, T::one()));
@ -659,37 +614,5 @@ mod tests {
c_row 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), (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)) 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] [package]
name = "zokrates_fs_resolver" name = "zokrates_fs_resolver"
version = "0.3.1" version = "0.3.2"
authors = ["Thibaut Schaeffer <thibaut@schaeff.fr>"] authors = ["Thibaut Schaeffer <thibaut@schaeff.fr>"]
repository = "https://github.com/JacobEberhardt/ZoKrates.git" repository = "https://github.com/JacobEberhardt/ZoKrates.git"