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

merge staging

This commit is contained in:
dark64 2022-06-28 19:23:45 +02:00
commit e75552b0eb
796 changed files with 7949 additions and 8658 deletions

View file

@ -0,0 +1 @@
Introduce curly bracket based syntax, use a semicolon to separate statements, change the syntax of `if-else` expression

View file

@ -0,0 +1 @@
Change the default backend to `ark` in the CLI

View file

@ -0,0 +1 @@
Remove multiple returns

View file

@ -0,0 +1 @@
Use signature output for constant parameter inference

View file

@ -277,7 +277,7 @@ fn parse_value<T: Field>(
.map_err(|_| Error::Type(format!("Could not parse `{}` to u64 type", s))),
(ConcreteType::Boolean, serde_json::Value::Bool(b)) => Ok(Value::Boolean(b)),
(ConcreteType::Array(array_type), serde_json::Value::Array(a)) => {
let size = array_type.size;
let size = *array_type.size;
if a.len() != size as usize {
Err(Error::Type(format!(
"Expected array of size {}, found array of size {}",

View file

@ -14,24 +14,24 @@ Function parameters can be declared as mutable to allow for mutation within the
{{#include ../../../zokrates_cli/examples/book/side_effects.zok}}
```
Generic paramaters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
Generic parameters, if any, must be compile-time constants. They are inferred by the compiler if that is possible, but can also be provided explicitly.
```zokrates
{{#include ../../../zokrates_cli/examples/book/generic_call.zok}}
```
### If-expressions
### Conditional expressions
An if-expression allows you to branch your code depending on a boolean condition.
A conditional expression allows you to branch your code depending on a boolean condition.
```zokrates
{{#include ../../../zokrates_cli/examples/book/if_else.zok}}
{{#include ../../../zokrates_cli/examples/book/conditional.zok}}
```
The conditional expression can also be written using a ternary operator:
```zokrates
{{#include ../../../zokrates_cli/examples/book/ternary.zok}}
{{#include ../../../zokrates_cli/examples/book/conditional_ternary.zok}}
```
There are two important caveats when it comes to conditional expressions. Before we go into them, let's define two concepts:
@ -41,11 +41,11 @@ There are two important caveats when it comes to conditional expressions. Before
Now the two caveats:
- **Both branches are always executed**. No short-circuiting happens based on the value of the condition. Therefore, the complexity of a program in terms of the number of constraints it compiles down to is the *sum* of the cost of all branches.
```zokrates
{{#include ../../../zokrates_cli/examples/book/if_else_expensive.zok}}
{{#include ../../../zokrates_cli/examples/book/conditional_expensive.zok}}
```
- **An unsatisfied constraint inside any branch will make the whole execution fail, even if this branch is not logically executed**. Also, the compiler itself inserts assertions which can fail. This can lead to unexpected results:
```zokrates
{{#include ../../../zokrates_cli/examples/book/if_else_panic.zok}}
{{#include ../../../zokrates_cli/examples/book/conditional_panic.zok}}
```
The experimental flag `--branch-isolation` can be activated in the CLI in order to restrict any unsatisfied constraint to make the execution fail only if it is in a logically executed branch. This way, the execution of the program above will always succeed.

View file

@ -18,18 +18,4 @@ The generic parameters can be provided explicitly, especially when they cannot b
```zokrates
{{#include ../../../zokrates_cli/examples/book/explicit_generic_parameters.zok}}
```
Functions can return multiple values by providing them as a comma-separated list.
```zokrates
{{#include ../../../zokrates_cli/examples/book/multi_return.zok}}
```
### Variable declaration
When defining a variable as the return value of a function, types are provided when the variable needs to be declared:
```zokrates
{{#include ../../../zokrates_cli/examples/book/multi_def.zok}}
```

View file

@ -3,21 +3,21 @@
The following table lists the precedence and associativity of all operators. Operators are listed top to bottom, in ascending precedence. Operators in the same cell have the same precedence. Operators are binary, unless the syntax is provided.
| Operator | Description | `field` | `u8/u16` `u32/u64` | `bool` | Associativity |
|----------------------------|------------------------------------------------------------|------------------------------|-------------------------------|-----------------------------|---------------|
| `**`<br> | Power | &check;[^1] | &nbsp; | &nbsp; | Left |
| `+x`<br>`-x`<br>`!x`<br> | Positive<br>Negative<br>Negation<br> | &check;<br>&check;<br>&nbsp; | &check;<br>&check;<br>&check; | &nbsp;<br>&nbsp;<br>&check; | Right |
| `*`<br>`/`<br>`%`<br> | Multiplication<br> Division<br> Remainder<br> | &check;<br>&check;<br>&nbsp; | &check;<br>&check;<br>&check; | &nbsp;<br>&nbsp;<br>&nbsp; | Left |
| `+`<br>`-`<br> | Addition<br> Subtraction<br> | &check; | &check; | &nbsp; | Left |
| `<<`<br>`>>`<br> | Left shift<br> Right shift<br> | &nbsp; | &check;[^2] | &nbsp; | Left |
| `&` | Bitwise AND | &nbsp; | &check; | &nbsp; | Left |
| <code>&#124;</code> | Bitwise OR | &nbsp; | &check; | &nbsp; | Left |
| `^` | Bitwise XOR | &nbsp; | &check; | &nbsp; | Left |
| `>=`<br>`>`<br>`<=`<br>`<` | Greater or equal<br>Greater<br>Lower or equal<br>Lower<br> | &check;[^3] | &check; | &nbsp; | Left |
| `!=`<br>`==`<br> | Not Equal<br>Equal<br> | &check; | &check; | &check; | Left |
| `&&` | Boolean AND | &nbsp; | &nbsp; | &check; | Left |
| <code>&#124;&#124;</code> | Boolean OR | &nbsp; | &nbsp; | &check; | Left |
| `c ? x : y`<br><br>`if c then x else y fi` | Conditional expression | &check; | &check; | &check; | Right | |
| Operator | Description | `field` | `u8/u16` `u32/u64` | `bool` | Associativity |
|--------------------------------------------|------------------------------------------------------------|------------------------------|-------------------------------|-----------------------------|---------------|
| `**`<br> | Power | &check;[^1] | &nbsp; | &nbsp; | Left |
| `+x`<br>`-x`<br>`!x`<br> | Positive<br>Negative<br>Negation<br> | &check;<br>&check;<br>&nbsp; | &check;<br>&check;<br>&check; | &nbsp;<br>&nbsp;<br>&check; | Right |
| `*`<br>`/`<br>`%`<br> | Multiplication<br> Division<br> Remainder<br> | &check;<br>&check;<br>&nbsp; | &check;<br>&check;<br>&check; | &nbsp;<br>&nbsp;<br>&nbsp; | Left |
| `+`<br>`-`<br> | Addition<br> Subtraction<br> | &check; | &check; | &nbsp; | Left |
| `<<`<br>`>>`<br> | Left shift<br> Right shift<br> | &nbsp; | &check;[^2] | &nbsp; | Left |
| `&` | Bitwise AND | &nbsp; | &check; | &nbsp; | Left |
| <code>&#124;</code> | Bitwise OR | &nbsp; | &check; | &nbsp; | Left |
| `^` | Bitwise XOR | &nbsp; | &check; | &nbsp; | Left |
| `>=`<br>`>`<br>`<=`<br>`<` | Greater or equal<br>Greater<br>Lower or equal<br>Lower<br> | &check;[^3] | &check; | &nbsp; | Left |
| `!=`<br>`==`<br> | Not Equal<br>Equal<br> | &check; | &check; | &check; | Left |
| `&&` | Boolean AND | &nbsp; | &nbsp; | &check; | Left |
| <code>&#124;&#124;</code> | Boolean OR | &nbsp; | &nbsp; | &check; | Left |
| `c ? x : y`<br><br>`if c { x } else { y }` | Conditional expression | &check; | &check; | &check; | Right |
[^1]: The exponent must be a compile-time constant of type `u32`

View file

@ -71,8 +71,8 @@ ZoKrates offers a special shorthand syntax to initialize an array with a constan
The following code provides examples for declaration and initialization:
```zokrates
field[3] a = [1, 2, 3] // initialize a field array with field values
bool[13] b = [false; 13] // initialize a bool array with value false
field[3] a = [1, 2, 3] // initialize a field array with field values
bool[13] b = [false; 13] // initialize a bool array with value false
```
#### Multidimensional Arrays
@ -132,8 +132,8 @@ A struct definition starts with the `struct` keyword followed by a name. Afterwa
```zokrates
struct Point {
field x
field y
field x
field y
}
```

View file

@ -59,11 +59,9 @@ In this example, the ABI specification is:
"type":"field"
}
],
"outputs":[
{
"type":"field"
}
]
"output": {
"type":"field"
}
}
```

View file

@ -24,7 +24,7 @@ const { initialize } = require('zokrates-js')
## Example
```js
initialize().then((zokratesProvider) => {
const source = "def main(private field a) -> field: return a * a";
const source = "def main(private field a) -> field { return a * a; }";
// compilation
const artifacts = zokratesProvider.compile(source);
@ -88,7 +88,7 @@ Returns: `CompilationArtifacts`
Compilation:
```js
const artifacts = zokratesProvider.compile("def main() -> (): return");
const artifacts = zokratesProvider.compile("def main() { return; }");
```
Compilation with custom options:
@ -135,7 +135,7 @@ Returns: `ComputationResult`
**Example:**
```js
const code = 'def main(private field a) -> (field): return a * a';
const code = 'def main(private field a) -> field { return a * a; }';
const artifacts = zokratesProvider.compile(code);
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);

View file

@ -1,6 +1,8 @@
// only using add, no need to flatten
def main(field a) -> field:
field b = a + 5
field c = a + b + a + 4
field d = a + c + a + b
return b + c + d
def main(field a) -> field {
field b = a + 5;
field c = a + b + a + 4;
field d = a + c + a + b;
return b + c + d;
}

View file

@ -1,13 +1,15 @@
type byte = u8
type uint32 = u32
type UInt32Array<N> = uint32[N]
type byte = u8;
type uint32 = u32;
type UInt32Array<N> = uint32[N];
type matrix<R, C> = field[R][C]
type matrix<R, C> = field[R][C];
def fill<R, C>(field v) -> matrix<R, C>:
return [[v; C]; R]
def fill<R, C>(field v) -> matrix<R, C> {
return [[v; C]; R];
}
def main(uint32 a, uint32 b) -> (UInt32Array<2>, matrix<2, 4>):
UInt32Array<2> res = [a, b]
matrix<2, 4> m = fill(1)
return res, m
def main(uint32 a, uint32 b) -> (UInt32Array<2>, matrix<2, 4>) {
UInt32Array<2> res = [a, b];
matrix<2, 4> m = fill(1);
return (res, m);
}

View file

@ -1,14 +1,16 @@
from "./basic_aliasing.zok" import matrix
from "./struct_aliasing.zok" import Buzz
from "./basic_aliasing.zok" import matrix;
from "./struct_aliasing.zok" import Buzz;
const u32 R = 2
const u32 C = 4
const u32 R = 2;
const u32 C = 4;
type matrix_2x4 = matrix<R, C>
type matrix_2x4 = matrix<R, C>;
def buzz<N>() -> Buzz<N>:
return Buzz { a: [0; N], b: [0; N] }
def buzz<N>() -> Buzz<N> {
return Buzz { a: [0; N], b: [0; N] };
}
def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4):
Buzz<2> b = buzz::<2>()
return b, m
def main(matrix_2x4 m) -> (Buzz<2>, matrix_2x4) {
Buzz<2> b = buzz::<2>();
return (b, m);
}

View file

@ -1,15 +1,16 @@
type FieldArray<N> = field[N]
type FieldArray<N> = field[N];
struct Foo<A, B> {
FieldArray<A> a
FieldArray<B> b
FieldArray<A> a;
FieldArray<B> b;
}
type Bar = Foo<2, 2>
type Buzz<A> = Foo<A, A>
type Bar = Foo<2, 2>;
type Buzz<A> = Foo<A, A>;
def main(Bar a) -> Buzz<2>:
Bar bar = Bar { a: [1, 2], b: [1, 2] }
Buzz<2> buzz = Buzz { a: [1, 2], b: [1, 2] }
assert(bar == buzz)
return buzz
def main(Bar a) -> Buzz<2> {
Bar bar = Bar { a: [1, 2], b: [1, 2] };
Buzz<2> buzz = Buzz { a: [1, 2], b: [1, 2] };
assert(bar == buzz);
return buzz;
}

View file

@ -1,6 +1,8 @@
def sub(field mut a) -> field:
a = a + 3
return a
def sub(field mut a) -> field {
a = a + 3;
return a;
}
def main() -> field:
return sub(4)
def main() -> field {
return sub(4);
}

View file

@ -1,11 +1,12 @@
def myFct<N, N2>(u64[N] ignored) -> u64[N2]:
assert(2*N == N2)
return [0; N2]
def myFct<N, N2>(u64[N] ignored) -> u64[N2] {
assert(2*N == N2);
return [0; N2];
}
const u32 N = 3
const u32 N = 3;
const u32 N2 = 2 * N;
const u32 N2 = 2*N
def main(u64[N] arg) -> bool:
u64[N2] someVariable = myFct(arg)
return true
def main(u64[N] arg) -> bool {
u64[N2] someVariable = myFct(arg);
return true;
}

View file

@ -1,8 +1,11 @@
def foo(field[2] a) -> bool:
return true
def foo(field[2] a) -> bool {
return true;
}
def foo(field[1] a) -> bool:
return true
def foo(field[1] a) -> bool {
return true;
}
def main() -> bool:
return foo([1])
def main() -> bool {
return foo([1]);
}

View file

@ -1,2 +1,3 @@
def main(field[3] a) -> field:
return a[0] + a[1] + a[2]
def main(field[3] a) -> field {
return a[0] + a[1] + a[2];
}

View file

@ -1,7 +1,8 @@
def main() -> u32:
u32[3] a = [1, 2, 3]
u32 mut c = 0
for u32 i in 0..3 do
c = c + a[i]
endfor
return c
def main() -> u32 {
u32[3] a = [1, 2, 3];
u32 mut c = 0;
for u32 i in 0..3 {
c = c + a[i];
}
return c;
}

View file

@ -1,7 +1,8 @@
def main() -> (u32[3]):
u32[3] a = [1, 2, 3]
u32[3] mut c = [4, 5, 6]
for u32 i in 0..3 do
c[i] = c[i] + a[i]
endfor
return c
def main() -> u32[3] {
u32[3] a = [1, 2, 3];
u32[3] mut c = [4, 5, 6];
for u32 i in 0..3 {
c[i] = c[i] + a[i];
}
return c;
}

View file

@ -1,9 +1,10 @@
def main(bool[3] mut a) -> (field[3]):
bool[3] c = [true, true || false, true]
a[1] = true || a[2]
a[2] = a[0]
field[3] mut result = [0; 3]
for u32 i in 0..3 do
result[i] = if a[i] then 33 else 0 fi
endfor
return result
def main(bool[3] mut a) -> field[3] {
bool[3] c = [true, true || false, true];
a[1] = true || a[2];
a[2] = a[0];
field[3] mut result = [0; 3];
for u32 i in 0..3 {
result[i] = a[i] ? 33 : 0;
}
return result;
}

View file

@ -1,3 +1,4 @@
def main() -> field:
field[4] a = [1, 2, 42, 55]
return a[2]
def main() -> field {
field[4] a = [1, 2, 42, 55];
return a[2];
}

View file

@ -1,12 +1,13 @@
def main(field[2][2][2] cube) -> field:
field mut res = 0
def main(field[2][2][2] cube) -> field {
field mut res = 0;
for u32 i in 0..2 do
for u32 j in 0..2 do
for u32 k in 0..2 do
res = res + cube[i][j][k]
endfor
endfor
endfor
for u32 i in 0..2 {
for u32 j in 0..2 {
for u32 k in 0..2 {
res = res + cube[i][j][k];
}
}
}
return res
return res;
}

View file

@ -1,2 +1,3 @@
def main(field[2] a, field[2] b, field condition) -> field[2]:
return if condition == 1 then a else b fi
def main(field[2] a, field[2] b, field condition) -> field[2] {
return condition == 1 ? a : b;
}

View file

@ -1,2 +1,3 @@
def main(field value) -> (field[3]):
return [value, value, value]
def main(field value) -> field[3] {
return [value, value, value];
}

View file

@ -1,4 +1,6 @@
const u32 SIZE = 100
def main(private field[SIZE][SIZE] a):
assert(a == [[0; SIZE]; SIZE])
return
const u32 SIZE = 100;
def main(private field[SIZE][SIZE] a) {
assert(a == [[0; SIZE]; SIZE]);
return;
}

View file

@ -1,2 +1,3 @@
def main(u32 index, field[5] array) -> field:
return array[index]
def main(u32 index, field[5] array) -> field {
return array[index];
}

View file

@ -1,5 +1,7 @@
def identity<N>(field[N][N] t) -> field[N][N]:
return t
def identity<N>(field[N][N] t) -> field[N][N] {
return t;
}
def main() -> field[1][1]:
return identity([[0]; 1])
def main() -> field[1][1] {
return identity([[0]; 1]);
}

View file

@ -1,4 +1,5 @@
def main(field[10][10][10] mut a, u32 i, u32 j, u32 k) -> (field[3]):
a[i][j][k] = 42
field[3][3] b = [[1, 2, 3], [1, 2, 3], [1, 2, 3]]
return b[0]
def main(field[10][10][10] mut a, u32 i, u32 j, u32 k) -> field[3] {
a[i][j][k] = 42;
field[3][3] b = [[1, 2, 3], [1, 2, 3], [1, 2, 3]];
return b[0];
}

View file

@ -1,4 +1,5 @@
def main(field a) -> field[4]:
u32 SIZE = 4
field[SIZE] res = [a; SIZE]
return res
def main(field a) -> field[4] {
u32 SIZE = 4;
field[SIZE] res = [a; SIZE];
return res;
}

View file

@ -1,5 +1,7 @@
def foo() -> field[2]:
return [1, 2]
def foo() -> field[2] {
return [1, 2];
}
def main() -> field[2]:
return foo()
def main() -> field[2] {
return foo();
}

View file

@ -1,2 +1,3 @@
def main(field[2] a, field[2] b) -> field[2]:
return [a[0] + b[0], a[1] + b[1]]
def main(field[2] a, field[2] b) -> field[2] {
return [a[0] + b[0], a[1] + b[1]];
}

File diff suppressed because one or more lines are too long

View file

@ -1,9 +1,11 @@
def foo(field[3] mut a) -> field:
a[1] = 2
return a[1]
def foo(field[3] mut a) -> field {
a[1] = 2;
return a[1];
}
def main() -> (field, field):
field[3] a = [0, 0, 0]
field res = foo(a)
assert(a[1] == 0)
return res, a[1]
def main() -> (field, field) {
field[3] a = [0, 0, 0];
field res = foo(a);
assert(a[1] == 0);
return (res, a[1]);
}

View file

@ -1,9 +1,11 @@
def foo(field a) -> field:
return 2
def foo(field a) -> field {
return 2;
}
def main(field a) -> (field, field):
field[2] mut result = [0, 0]
field r = foo(a)
result[1] = r
assert(result[1] == r)
return result[1], r
def main(field a) -> (field, field) {
field[2] mut result = [0, 0];
field r = foo(a);
result[1] = r;
assert(result[1] == r);
return (result[1], r);
}

View file

@ -1,10 +1,11 @@
def main():
field[3] a = [1, 2, 3]
bool[3] b = [true, true, false]
field[3][2] c = [[1, 2], [3, 4], [5, 6]]
def main() {
field[3] a = [1, 2, 3];
bool[3] b = [true, true, false];
field[3][2] c = [[1, 2], [3, 4], [5, 6]];
field[3] aa = [...a]
bool[3] bb = [...b]
field[3][2] cc = [...c]
field[3] aa = [...a];
bool[3] bb = [...b];
field[3][2] cc = [...c];
return
return;
}

View file

@ -1,7 +1,9 @@
def get(field[32] array, u32 index) -> field:
return array[index]
def get(field[32] array, u32 index) -> field {
return array[index];
}
def main() -> field:
field[32] array = [0, 0, 0, 0, 0, 0, 7, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
field r = get(array, 7)
return r
def main() -> field {
field[32] array = [0, 0, 0, 0, 0, 0, 7, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
field r = get(array, 7);
return r;
}

View file

@ -1,11 +1,9 @@
def foo() -> u32:
return 0
def foo() -> u32 {
return 0;
}
def bar() -> (u32, u32):
return 0, 0
def main(u32[1] mut a, u32 mut b):
a[0] = foo()
a[0], b = bar()
return
def main(u32[1] mut a, (u32,) mut b) {
a[0] = foo();
b.0 = foo();
return;
}

View file

@ -1,11 +1,12 @@
struct Bar {
field a
field a;
}
struct Foo {
u8 a
Bar b
u8 a;
Bar b;
}
def main(Foo foo, bool[2] bar, field num) -> field:
return 42
def main(Foo foo, bool[2] bar, field num) -> field {
return 42;
}

View file

@ -1,10 +1,11 @@
def main() -> field:
field[3] mut a = [1, 2, 3] // initialize a field array with field values
a[2] = 4 // set a member to a value
field[4] b = [42; 4] // initialize an array of 4 values all equal to 42
field[4] c = [...a, 4] // initialize an array copying values from `a`, followed by 4
field[2] d = a[1..3] // initialize an array copying a slice from `a`
bool[3] e = [true, true || false, true] // initialize a boolean array
u32 SIZE = 3
field[SIZE] f = [1, 2, 3] // initialize a field array with a size that's a compile-time constant
return a[0] + b[1] + c[2]
def main() -> field {
field[3] mut a = [1, 2, 3]; // initialize a field array with field values
a[2] = 4; // set a member to a value
field[4] b = [42; 4]; // initialize an array of 4 values all equal to 42
field[4] c = [...a, 4]; // initialize an array copying values from `a`, followed by 4
field[2] d = a[1..3]; // initialize an array copying a slice from `a`
bool[3] e = [true, true || false, true]; // initialize a boolean array
u32 SIZE = 3;
field[SIZE] f = [1, 2, 3]; // initialize a field array with a size that's a compile-time constant
return a[0] + b[1] + c[2];
}

View file

@ -1,3 +1,4 @@
def main() -> ():
assert(1f + 1f == 2f)
return
def main() {
assert(1f + 1f == 2f);
return;
}

View file

@ -1,16 +1,21 @@
def swap(u32 a, u32 mut b, bool c) -> (u32, u32):
u32 a_prime = if c then b else a fi
b = if c then a else b fi
return a_prime, b
def swap(u32 a, u32 mut b, bool c) -> (u32, u32) {
u32 a_prime = c ? b : a;
b = c ? a : b;
return (a_prime, b);
}
def bubblesort<N>(u32[N] mut a) -> u32[N]:
for u32 i in 0..(N-1) do
for u32 j in 0..(N-1-i) do
bool need_swap = a[j + 1] < a[j]
a[j], a[j + 1] = swap(a[j], a[j + 1], need_swap)
endfor
endfor
return a
def bubblesort<N>(u32[N] mut a) -> u32[N] {
for u32 i in 0..(N-1) {
for u32 j in 0..(N-1-i) {
bool need_swap = a[j + 1] < a[j];
(u32, u32) swapped = swap(a[j], a[j + 1], need_swap);
a[j] = swapped.0;
a[j + 1] = swapped.1;
}
}
return a;
}
def main(u32[10] a) -> u32[10]:
return bubblesort(a)
def main(u32[10] a) -> u32[10] {
return bubblesort(a);
}

View file

@ -1,4 +1,5 @@
def main() -> field:
field a = 42 // this is an end of line comment
def main() -> field {
field a = 42; // this is an end of line comment
// this is a full line comment
return a
return a;
}

View file

@ -0,0 +1,4 @@
def main(field x) -> field {
field y = if x + 2 == 3 { 1 } else { 5 };
return y;
}

View file

@ -0,0 +1,15 @@
def cheap(field x) -> field {
return x + 1;
}
def expensive(field x) -> field {
return x**1000;
}
def main(field x) -> field {
return if x == 1 {
cheap(x)
} else {
expensive(x) // both branches executed
};
}

View file

@ -0,0 +1,7 @@
def main(field x) -> field {
return if x == 0 {
0
} else {
1 / x // executed even for x := 0, which leads to the execution failing
};
}

View file

@ -0,0 +1,4 @@
def main(field x) -> field {
field y = x + 2 == 3 ? 1 : 5;
return y;
}

View file

@ -1,4 +1,5 @@
const field PRIME = 31
const field PRIME = 31;
def main() -> field:
return PRIME
def main() -> field {
return PRIME;
}

View file

@ -1,5 +1,6 @@
const field ONE = 1
const field TWO = ONE + ONE
const field ONE = 1;
const field TWO = ONE + ONE;
def main() -> field:
return TWO
def main() -> field {
return TWO;
}

View file

@ -1,6 +1,7 @@
def main():
// declare and define `my_variable`
field mut my_variable = 2
// redefine `my_variable`
my_variable = 3
return
def main() {
// declare and define `my_variable`
field mut my_variable = 2;
// redefine `my_variable`
my_variable = 3;
return;
}

View file

@ -1,11 +1,13 @@
// a function to sum the N first powers of a field element
def sum_powers<N>(field a) -> field:
field mut res = 0
for u32 i in 0..N do
res = res + a ** i
endfor
return res
def sum_powers<N>(field a) -> field {
field mut res = 0;
for u32 i in 0..N {
res = res + a ** i;
}
return res;
}
def main(field a) -> field:
def main(field a) -> field {
// call `sum_powers` providing the explicit generic parameter `N := 5`
return sum_powers::<5>(a)
return sum_powers::<5>(a);
}

View file

@ -1,3 +1,4 @@
def main(private field a, field b):
assert(a * a == b)
return
def main(private field a, field b) {
assert(a * a == b);
return;
}

View file

@ -1,4 +1,5 @@
def main():
field pMinusOne = 21888242871839275222246405745257275088548364400416034343698204186575808495616
assert(0 - 1 == pMinusOne)
return
def main() {
field pMinusOne = 21888242871839275222246405745257275088548364400416034343698204186575808495616;
assert(0 - 1 == pMinusOne);
return;
}

View file

@ -1,8 +1,9 @@
def main() -> u32:
u32 mut res = 0
for u32 i in 0..4 do
for u32 j in i..5 do
res = res + i
endfor
endfor
return res
def main() -> u32 {
u32 mut res = 0;
for u32 i in 0..4 {
for u32 j in i..5 {
res = res + i;
}
}
return res;
}

View file

@ -1,7 +1,8 @@
def main() -> u32:
u32 mut a = 0
for u32 i in 0..5 do
a = a + i
endfor
// return i <- not allowed
return a
def main() -> u32 {
u32 mut a = 0;
for u32 i in 0..5 {
a = a + i;
}
// return i <- not allowed
return a;
}

View file

@ -1,5 +1,7 @@
def foo(field a, field b) -> field:
return a + b
def foo(field a, field b) -> field {
return a + b;
}
def main() -> field:
return foo(1, 2)
def main() -> field {
return foo(1, 2);
}

View file

@ -1,7 +1,9 @@
def foo() -> field:
// return myGlobal <- not allowed
return 42
def foo() -> field {
// return myGlobal <- not allowed
return 42;
}
def main() -> field:
field myGlobal = 42
return foo()
def main() -> field {
field myGlobal = 42;
return foo();
}

View file

@ -1,7 +1,9 @@
def foo<N, P>() -> field[P]:
return [42; P]
def foo<N, P>() -> field[P] {
return [42; P];
}
def main() -> field[2]:
def main() -> field[2] {
// `P` is inferred from the declaration of `res`, while `N` is provided explicitly
field[2] res = foo::<3, _>()
return res
field[2] res = foo::<3, _>();
return res;
}

View file

@ -1,6 +1,8 @@
def foo<N>() -> field[N]:
return [42; N]
def foo<N>() -> field[N] {
return [42; N];
}
def main() -> field[2]:
field[2] res = foo()
return res
def main() -> field[2] {
field[2] res = foo();
return res;
}

View file

@ -1,9 +1,11 @@
def sum<N>(field[N] a) -> field:
field mut res = 0
for u32 i in 0..N do
res = res + a[i]
endfor
return res
def sum<N>(field[N] a) -> field {
field mut res = 0;
for u32 i in 0..N {
res = res + a[i];
}
return res;
}
def main(field[3] a) -> field:
return sum(a)
def main(field[3] a) -> field {
return sum(a);
}

View file

@ -1,3 +0,0 @@
def main(field x) -> field:
field y = if x + 2 == 3 then 1 else 5 fi
return y

View file

@ -1,12 +0,0 @@
def cheap(field x) -> field:
return x + 1
def expensive(field x) -> field:
return x**1000
def main(field x) -> field:
return if x == 1 then\
cheap(x)\// executed
else\
expensive(x)\// also executed
fi

View file

@ -1,6 +0,0 @@
def main(field x) -> field:
return if x == 0 then\
0\
else\
1/x\// executed even for x := 0, which leads to the execution failing
fi

View file

@ -1,2 +1,3 @@
def main(private field a, private field b) -> field:
return a * b
def main(private field a, private field b) -> field {
return a * b;
}

View file

@ -34,5 +34,5 @@ zokrates mpc export -i final.params
# use the keys to generate proofs and verify
zokrates compute-witness -i circuit -a 123456789 987654321 --verbose
zokrates generate-proof -i circuit
zokrates verify
zokrates generate-proof -i circuit -b bellman
zokrates verify -b bellman

View file

@ -1,9 +0,0 @@
def foo() -> (field, field):
return 21, 42
def main():
// a is declared here
field mut a = 1
// b is declared here
a, field b = foo()
return

View file

@ -1,2 +0,0 @@
def main() -> (field, field[3]):
return 1, [2, 3, 4]

View file

@ -1,9 +1,10 @@
def main() -> field:
def main() -> field {
// Array of two elements of array of 3 elements
field[2][3] a = [[1, 2, 3],[4, 5, 6]]
field[2][3] a = [[1, 2, 3],[4, 5, 6]];
field[3] b = a[0] // should be [1, 2, 3]
field[3] b = a[0]; // should be [1, 2, 3]
// allowed access [0..2][0..3]
return a[1][2]
return a[1][2];
}

View file

@ -2,5 +2,6 @@
This is a multi-line comment
written in more than just one line.
*/
def main() -> field:
return 42
def main() -> field {
return 42;
}

View file

@ -1,6 +1,7 @@
def main():
field a = 42
// a = 43 <- not allowed, as `a` is immutable
field mut b = 42
b = 43 // ok
return
def main() {
field a = 42;
// a = 43; <- not allowed, as `a` is immutable
field mut b = 42;
b = 43; // ok
return;
}

View file

@ -1,7 +1,8 @@
def main() -> field:
field a = 2
// field a = 3 <- not allowed
for u32 i in 0..5 do
// field a = 7 <- not allowed
endfor
return a
def main() -> field {
field a = 2;
// field a = 3 <- not allowed
for u32 i in 0..5 {
// field a = 7 <- not allowed
}
return a;
}

View file

@ -1,2 +1,3 @@
def main(field a, field b) -> (bool):
return !(a == b)
def main(field a, field b) -> bool {
return !(a == b);
}

View file

@ -1,9 +1,10 @@
def main():
// `255` is infered to `255f`, and the addition happens between field elements
assert(255 + 1f == 256)
def main() {
// `255` is infered to `255f`, and the addition happens between field elements
assert(255 + 1f == 256);
// `255` is infered to `255u8`, and the addition happens between u8
// This causes an overflow
assert(255 + 1u8 == 0)
return
// `255` is infered to `255u8`, and the addition happens between u8
// This causes an overflow
assert(255 + 1u8 == 0);
return;
}

View file

@ -1,5 +1,6 @@
import "hashes/sha256/512bit" as sha256
import "hashes/sha256/512bit" as sha256;
def main(u32[16] hashMe) -> u32[8]:
u32[8] h = sha256(hashMe[0..8], hashMe[8..16])
return h
def main(u32[16] hashMe) -> u32[8] {
u32[8] h = sha256(hashMe[0..8], hashMe[8..16]);
return h;
}

View file

@ -1,20 +1,19 @@
import "hashes/sha256/512bit" as sha256
import "utils/casts/u32_to_bits" as u32_to_bits
import "hashes/sha256/512bit" as sha256;
import "utils/casts/u32_to_bits" as u32_to_bits;
// Reveal a bit from a 512 bit value, and return it with the corresponding hash
// for that value.
//
// WARNING, once enough bits have been revealed it is possible to brute force
// the remaining preimage bits.
def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool):
// Convert the preimage to bits
bool[512] mut preimageBits = [false; 512]
for u32 i in 0..16 do
bool[32] val = u32_to_bits(preimage[i])
for u32 bit in 0..32 do
preimageBits[i*32+bit] = val[bit]
endfor
endfor
return sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]
def main(private u32[16] preimage, u32 bitNum) -> (u32[8], bool) {
// Convert the preimage to bits
bool[512] mut preimageBits = [false; 512];
for u32 i in 0..16 {
bool[32] val = u32_to_bits(preimage[i]);
for u32 bit in 0..32 {
preimageBits[i*32 + bit] = val[bit];
}
}
return (sha256(preimage[0..8], preimage[8..16]), preimageBits[bitNum]);
}

View file

@ -1,5 +1,6 @@
import "hashes/sha256/512bitPacked" as sha256packed
import "hashes/sha256/512bitPacked" as sha256packed;
def main(private field a, private field b, private field c, private field d) -> field[2]:
field[2] h = sha256packed([a, b, c, d])
return h
def main(private field a, private field b, private field c, private field d) -> field[2] {
field[2] h = sha256packed([a, b, c, d]);
return h;
}

View file

@ -1,7 +1,8 @@
import "hashes/sha256/512bitPacked" as sha256packed
import "hashes/sha256/512bitPacked" as sha256packed;
def main(private field a, private field b, private field c, private field d):
field[2] h = sha256packed([a, b, c, d])
assert(h[0] == 263561599766550617289250058199814760685)
assert(h[1] == 65303172752238645975888084098459749904)
return
def main(private field a, private field b, private field c, private field d) {
field[2] h = sha256packed([a, b, c, d]);
assert(h[0] == 263561599766550617289250058199814760685);
assert(h[1] == 65303172752238645975888084098459749904);
return;
}

View file

@ -1,10 +1,11 @@
def incr(field mut a) -> field:
// `a` was declared as mutable in the function parameters, so we can mutate it
a = a + 1
return a
def incr(field mut a) -> field {
a = a + 1;
return a;
}
def main():
field x = 1
field res = incr(x)
assert(x == 1) // x has not changed
return
def main() {
field x = 1;
field res = incr(x);
assert(x == 1); // x has not changed
return;
}

View file

@ -1,10 +1,11 @@
struct Point {
field x
field y
field x;
field y;
}
def main(field a) -> (Point):
Point mut p = Point {x: 1, y: 0}
p.x = a
p.y = p.x
return p
def main(field a) -> Point {
Point mut p = Point { x: 1, y: 0 };
p.x = a;
p.y = p.x;
return p;
}

View file

@ -1,8 +1,10 @@
struct Point {
field x
field y
field x;
field y;
}
def main() -> Point {
Point p = Point { x: 1, y: 0 };
return p;
}
def main() -> (Point):
Point p = Point {x: 1, y: 0}
return p

View file

@ -1,14 +1,16 @@
struct Bar<N> {
field[N] c
bool d
field[N] c;
bool d;
}
struct Foo<P> {
Bar<P> a
bool b
Bar<P> a;
bool b;
}
def main() -> Foo<2> {
Foo<2>[2] mut f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true }];
f[0].a.c = [42, 43];
return f[0];
}
def main() -> (Foo<2>):
Foo<2>[2] mut f = [Foo { a: Bar { c: [0, 0], d: false }, b: true}, Foo { a: Bar {c: [0, 0], d: false}, b: true}]
f[0].a.c = [42, 43]
return f[0]

View file

@ -1,3 +0,0 @@
def main(field x) -> field:
field y = x + 2 == 3 ? 1 : 5
return y

View file

@ -1,4 +1,5 @@
def main() -> bool:
(field[2], bool) mut v = ([1, 2], true)
v.0 = [42, 43]
return v.1
def main() -> bool {
(field[2], bool) mut v = ([1, 2], true);
v.0 = [42, 43];
return v.1;
}

View file

@ -1,11 +1,12 @@
type MyField = field
type MyField = field;
type Rectangle<L, W> = bool[L][W]
type Rectangle<L, W> = bool[L][W];
type Square<S> = Rectangle<S, S>
type Square<S> = Rectangle<S, S>;
def main():
MyField f = 42
Rectangle<2, 2> r = [[true; 2]; 2]
Square<2> s = r
return
def main() {
MyField f = 42;
Rectangle<2, 2> r = [[true; 2]; 2];
Square<2> s = r;
return;
}

View file

@ -1,9 +1,12 @@
def foo() -> (field, field[3]):
return 1, [2, 3, 4]
def foo() -> (field, field[3]) {
return (1, [2, 3, 4]);
}
def foo() -> (field, field):
return 1, 2
def foo() -> (field, field) {
return (1, 2);
}
def main():
field a, field[3] b = foo()
return
def main() {
(field, field[3]) a = foo();
return;
}

View file

@ -1,7 +1,8 @@
// example using if-then-else-fi with &&
// example using ternary with &&
def main(field a, field b) -> field:
field y = if a + 2 == 3 && a * 2 == 2 then 1 else 0 fi
field z = if y == 1 && 1-y == 0 then y else 1 fi
assert(b == 1)
return a
def main(field a, field b) -> field {
field y = a + 2 == 3 && a * 2 == 2 ? 1 : 0;
field z = y == 1 && 1 - y == 0 ? y : 1;
assert(b == 1);
return a;
}

View file

@ -1,3 +1,4 @@
def main(field a) -> field:
field x = if !(!(a < 5) && !(a > 1) || a < 4) then 3 else 4 fi
return x
def main(field a) -> field {
field x = !(!(a < 5) && !(a > 1) || a < 4) ? 3 : 4;
return x;
}

View file

@ -1,7 +1,7 @@
// example using if-then-else-fi with ||
def main(field a, field b) -> field:
field y = if a + 2 == 4 || b * 2 == 2 then 1 else 0 fi
field z = if y == 1 || y == 0 then y else 1 fi
assert(z == 1)
return z
def main(field a, field b) -> field {
field y = a + 2 == 4 || b * 2 == 2 ? 1 : 0;
field z = y == 1 || y == 0 ? y : 1;
assert(z == 1);
return z;
}

View file

@ -1,2 +1,3 @@
def main(bool a) -> bool:
return (false || true) && false
def main(bool a) -> bool {
return (false || true) && false;
}

View file

@ -1,4 +1,5 @@
def main(field a) -> field:
field b = (a + 5) * 6
field c = 7 * (b + a)
return b + c
def main(field a) -> field {
field b = (a + 5) * 6;
field c = 7 * (b + a);
return b + c;
}

View file

@ -1,10 +1,12 @@
from "./call_in_const_aux.zok" import A, foo, F
from "./call_in_const_aux.zok" import A, foo, F;
def bar(field[A] x) -> field[A]:
return x
const field[A] Y = [...bar(foo::<A>(F))[..A - 1], 1]
def bar(field[A] x) -> field[A] {
return x;
}
def main(field[A] X):
assert(X == Y)
return
const field[A] Y = [...bar(foo::<A>(F))[..A - 1], 1];
def main(field[A] X) {
assert(X == Y);
return;
}

View file

@ -1,9 +1,11 @@
const field F = 10
const u32 A = 10
const u32 B = A
const field F = 10;
const u32 A = 10;
const u32 B = A;
def foo<N>(field X) -> field[N]:
return [X; N]
def foo<N>(field X) -> field[N] {
return [X; N];
}
def main():
return
def main() {
return;
}

View file

@ -1,7 +1,9 @@
def yes() -> bool:
return true
def yes() -> bool {
return true;
}
const bool TRUE = yes()
const bool TRUE = yes();
def main():
return
def main() {
return;
}

View file

@ -1,7 +1,8 @@
// only using add, no need to flatten
def main(field a) -> field: // a needs to be 1
field b = a + 5 // inline comment
field c = a + b + a + 4
assert(a == 1) // another inline comment
field d = a + c + a + b
return b + c + d
def main(field a) -> field { // a needs to be 1
field b = a + 5; // inline comment
field c = a + b + a + 4;
assert(a == 1); // another inline comment
field d = a + c + a + b;
return b + c + d;
}

View file

@ -1,8 +1,9 @@
// comparison operator example
def main(field mut x) -> field:
field mut y = if x >= 3 then 1 else 5 fi
field mut z = if y <= x then x**3 else y**3 fi
y = if x < 3 then 2 else 6 fi
z = if y > z then 1 else 2 fi
x = if x == x then x else y fi
return x + y + z
def main(field mut x) -> field {
field mut y = x >= 3 ? 1 : 5;
field mut z = y <= x ? x**3 : y**3;
y = x < 3 ? 2 : 6;
z = y > z ? 1 : 2;
x = x == x ? x : y;
return x + y + z;
}

View file

@ -1,14 +1,17 @@
// this should not compile, as A == B
const u32 A = 1
const u32 B = 1
const u32 A = 1;
const u32 B = 1;
def foo(field[A] a) -> bool:
return true
def foo(field[A] a) -> bool {
return true;
}
def foo(field[B] a) -> bool:
return true
def foo(field[B] a) -> bool {
return true;
}
def main():
assert(foo([1]))
return
def main() {
assert(foo([1]));
return;
}

View file

@ -1,14 +1,17 @@
// this should actually compile, as A != B
const u32 A = 2
const u32 B = 1
const u32 A = 2;
const u32 B = 1;
def foo(field[A] a) -> bool:
return true
def foo(field[A] a) -> bool {
return true;
}
def foo(field[B] a) -> bool:
return true
def foo(field[B] a) -> bool {
return true;
}
def main():
assert(foo([1]))
return
def main() {
assert(foo([1]));
return;
}

View file

@ -1,3 +1,4 @@
def main():
assert(1f == 2f)
return
def main() {
assert(1f == 2f);
return;
}

View file

@ -1,3 +1,4 @@
def main():
assert([1f] == [2f])
return
def main() {
assert([1f] == [2f]);
return;
}

Some files were not shown because too many files have changed in this diff Show more