fix conflicts
This commit is contained in:
commit
a983f1e145
136 changed files with 1176 additions and 1988 deletions
|
@ -130,7 +130,7 @@ jobs:
|
|||
command: cd zokrates_js && npm run build
|
||||
zokrates_js_test:
|
||||
docker:
|
||||
- image: circleci/node
|
||||
- image: dark64/rust-wasm-env:latest
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
|
|
|
@ -5,5 +5,5 @@ def foo(field[3] a) -> (field):
|
|||
def main() -> (field, field):
|
||||
field[3] a = [0, 0, 0]
|
||||
field res = foo(a)
|
||||
a[1] == 0
|
||||
assert(a[1] == 0)
|
||||
return res, a[1]
|
||||
|
|
|
@ -5,5 +5,5 @@ def main(field a) -> (field, field):
|
|||
field[2] result = [0, 0]
|
||||
field r = foo(a)
|
||||
result[1] = r
|
||||
result[1] == r
|
||||
assert(result[1] == r)
|
||||
return result[1], r
|
|
@ -1,3 +1,2 @@
|
|||
def main(private field a, field b) -> (field):
|
||||
field result = if a * a == b then 1 else 0 fi
|
||||
return result
|
||||
def main(private field a, field b) -> (bool):
|
||||
return a * a == b
|
|
@ -1,4 +1,4 @@
|
|||
def main() -> (field):
|
||||
def main() -> ():
|
||||
field pMinusOne = 21888242871839275222246405745257275088548364400416034343698204186575808495616
|
||||
0 - 1 == pMinusOne
|
||||
return 1
|
||||
assert(0 - 1 == pMinusOne)
|
||||
return
|
|
@ -1,7 +1,7 @@
|
|||
import "hashes/sha256/512bitPacked" as sha256packed
|
||||
|
||||
def main(private field a, private field b, private field c, private field d) -> (field):
|
||||
def main(private field a, private field b, private field c, private field d) -> ():
|
||||
field[2] h = sha256packed([a, b, c, d])
|
||||
h[0] == 263561599766550617289250058199814760685
|
||||
h[1] == 65303172752238645975888084098459749904
|
||||
return 1
|
||||
assert(h[0] == 263561599766550617289250058199814760685)
|
||||
assert(h[1] == 65303172752238645975888084098459749904)
|
||||
return
|
|
@ -2,8 +2,8 @@ def incr(field a) -> (field):
|
|||
a = a + 1
|
||||
return a
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
field x = 1
|
||||
field res = incr(x)
|
||||
x == 1 // x has not changed
|
||||
return 1
|
||||
assert(x == 1) // x has not changed
|
||||
return
|
|
@ -4,6 +4,6 @@ def foo() -> (field, field[3]):
|
|||
def foo() -> (field, field):
|
||||
return 1, 2
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
field a, field[3] b = foo()
|
||||
return 1
|
||||
return
|
|
@ -3,5 +3,5 @@
|
|||
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
|
||||
b == 1
|
||||
assert(b == 1)
|
||||
return a
|
|
@ -2,6 +2,6 @@
|
|||
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
|
||||
z == 1
|
||||
assert(z == 1)
|
||||
return z
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
def main(field a) -> (field): // a needs to be 1
|
||||
field b = a + 5 // inline comment
|
||||
field c = a + b + a + 4
|
||||
a == 1 // another inline comment
|
||||
assert(a == 1) // another inline comment
|
||||
field d = a + c + a + b
|
||||
return b + c + d
|
||||
|
|
|
@ -1,6 +1,19 @@
|
|||
struct Foo {
|
||||
field a
|
||||
}
|
||||
|
||||
struct Bar {
|
||||
Foo[1] foo
|
||||
}
|
||||
|
||||
def isEqual(field a, field b) -> (bool):
|
||||
return a == b
|
||||
|
||||
def main(field a) -> (field):
|
||||
field b = (a + 5) * 6
|
||||
2 * b == a * 12 + 60
|
||||
assert(2 * b == a * 12 + 60)
|
||||
field c = 7 * (b + a)
|
||||
c == 7 * b + 7 * a
|
||||
assert(isEqual(c, 7 * b + 7 * a))
|
||||
field k = if [1, 2] == [3, 4] then 1 else 3 fi
|
||||
assert([Bar { foo : [Foo { a: 42 }]}] == [Bar { foo : [Foo { a: 42 }]}])
|
||||
return b + c
|
5
zokrates_cli/examples/error/assert.zok
Normal file
5
zokrates_cli/examples/error/assert.zok
Normal file
|
@ -0,0 +1,5 @@
|
|||
def assert() -> ():
|
||||
return
|
||||
|
||||
def main() -> ():
|
||||
return
|
|
@ -1,5 +1,5 @@
|
|||
// a and b are factorization of c
|
||||
def main(field c, private field a, private field b) -> (field):
|
||||
def main(field c, private field a, private field b) -> ():
|
||||
field d = a * b
|
||||
c == d
|
||||
return 1
|
||||
assert(c == d)
|
||||
return
|
||||
|
|
|
@ -1,23 +1,17 @@
|
|||
def lt(field a,field b) -> (field):
|
||||
return if a < b then 1 else 0 fi
|
||||
def lt(field a,field b) -> (bool):
|
||||
return a < b
|
||||
|
||||
def cutoff() -> (field):
|
||||
return 31337
|
||||
|
||||
def getThing(field index) -> (field):
|
||||
field result = 3
|
||||
result = if index == 0 then 13 else result fi
|
||||
result = if index == 1 then 23 else result fi
|
||||
result = if index == 2 then 43 else result fi
|
||||
result = if index == 3 then 53 else result fi
|
||||
result = if index == 4 then 73 else result fi
|
||||
result = if index == 5 then 83 else result fi
|
||||
return result
|
||||
field[6] a = [13, 23, 43, 53, 73, 83]
|
||||
return a[index]
|
||||
|
||||
def cubeThing(field thing) -> (field):
|
||||
return thing**3
|
||||
|
||||
def main(field index) -> (field):
|
||||
def main(field index) -> (bool):
|
||||
field thing = getThing(index)
|
||||
thing = cubeThing(thing)
|
||||
return lt(cutoff(), thing)
|
||||
|
|
|
@ -7,5 +7,5 @@ import "./bar"
|
|||
def main() -> (field):
|
||||
MyBar my_bar = MyBar {}
|
||||
Bar bar = Bar {}
|
||||
my_bar == bar
|
||||
assert(my_bar == bar)
|
||||
return foo() + bar()
|
|
@ -1,6 +1,6 @@
|
|||
def foo() -> (field):
|
||||
return 1
|
||||
|
||||
def main() -> (field):
|
||||
foo() + (1 + 44*3) == 1
|
||||
return 1
|
||||
def main() -> ():
|
||||
assert(foo() + (1 + 44*3) == 1)
|
||||
return
|
||||
|
|
|
@ -6,7 +6,11 @@ import "hashes/utils/256bitsDirectionHelper" as multiplex
|
|||
|
||||
// Merke-Tree inclusion proof for tree depth 3 using SNARK efficient pedersen hashes
|
||||
// directionSelector=> 1/true if current digest is on the rhs of the hash
|
||||
<<<<<<< HEAD
|
||||
def main(u32[8] rootDigest, private u32[8] leafDigest, private bool[3] directionSelector, u32[8] PathDigest0, private u32[8] PathDigest1, private u32[8] PathDigest2) -> (field):
|
||||
=======
|
||||
def main(bool[256] rootDigest, private bool[256] leafDigest, private bool[3] directionSelector, bool[256] PathDigest0, private bool[256] PathDigest1, private bool[256] PathDigest2) -> ():
|
||||
>>>>>>> 26f4d72ee6e0c802823cf145fbd11a372586eb28
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
//Setup
|
||||
|
@ -22,7 +26,7 @@ def main(u32[8] rootDigest, private u32[8] leafDigest, private bool[3] direction
|
|||
preimage = multiplex(directionSelector[2], currentDigest, PathDigest2)
|
||||
currentDigest = hash(preimage)
|
||||
|
||||
rootDigest == currentDigest
|
||||
assert(rootDigest == currentDigest)
|
||||
|
||||
return 1 //return true in success
|
||||
return
|
||||
|
||||
|
|
|
@ -3,7 +3,11 @@ import "utils/multiplexer/256bit" as multiplex
|
|||
|
||||
// Merkle-Tree inclusion proof for tree depth 3
|
||||
|
||||
<<<<<<< HEAD
|
||||
def main(field treeDepth, u32[8] rootDigest, private u32[8] leafDigest, private bool[2] directionSelector, u32[8] PathDigest0, private u32[8] PathDigest1) -> (field):
|
||||
=======
|
||||
def main(field treeDepth, bool[256] rootDigest, private bool[256] leafDigest, private bool[2] directionSelector, bool[256] PathDigest0, private bool[256] PathDigest1) -> ():
|
||||
>>>>>>> 26f4d72ee6e0c802823cf145fbd11a372586eb28
|
||||
|
||||
//Setup
|
||||
u32[8] currentDigest = leafDigest
|
||||
|
@ -23,8 +27,7 @@ def main(field treeDepth, u32[8] rootDigest, private u32[8] leafDigest, private
|
|||
currentDigest = sha256(lhs, rhs)
|
||||
counter = counter + 1
|
||||
|
||||
//Asserts
|
||||
counter == treeDepth
|
||||
rootDigest == currentDigest
|
||||
assert(counter == treeDepth)
|
||||
assert(rootDigest == currentDigest)
|
||||
|
||||
return 1 //return true in success
|
||||
return
|
|
@ -2,6 +2,6 @@ def foo(field a) -> (field, field, field, field):
|
|||
field b = 12*a
|
||||
return a, 2*a, 5*b, a*b
|
||||
|
||||
def main(field i) -> (field):
|
||||
def main(field i) -> ():
|
||||
field x, field y, field z, field t = foo(i)
|
||||
return 1
|
||||
return
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// this code does not need to be flattened
|
||||
def main(field x, field a, field b) -> (field):
|
||||
a == b * 7
|
||||
assert(a == b * 7)
|
||||
return x + a + b
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// this code does not need to be flattened
|
||||
def main(field x, field y, field z) -> (field):
|
||||
field a = x + 3*y - z *2 - x * 12
|
||||
3*y - z *2 - x * 12 == a - x
|
||||
(x + y) - ((z + 3*x) - y) == (x - y) + ((2*x - 4*y) + (4*y - 2*z))
|
||||
assert(3*y - z *2 - x * 12 == a - x)
|
||||
assert((x + y) - ((z + 3*x) - y) == (x - y) + ((2*x - 4*y) + (4*y - 2*z)))
|
||||
return x
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
def main() -> (field):
|
||||
def main() -> ():
|
||||
field x = 2**4
|
||||
x == 16
|
||||
assert(x == 16)
|
||||
x = x**2
|
||||
x == 256
|
||||
assert(x == 256)
|
||||
field y = 3**3
|
||||
y == 27
|
||||
assert(y == 27)
|
||||
field z = y**2
|
||||
z == 729
|
||||
assert(z == 729)
|
||||
field a = 5**2
|
||||
a == 25
|
||||
assert(a == 25)
|
||||
a = a**2
|
||||
a == 625
|
||||
assert(a == 625)
|
||||
a = 5**5
|
||||
a == 3125
|
||||
return 1
|
||||
assert(a == 3125)
|
||||
return
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
def foo(field a, field b) -> (field, field):
|
||||
a == b + 2
|
||||
assert(a == b + 2)
|
||||
return a, b
|
||||
|
||||
def main() -> (field):
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
// It should not work for the maxvalue = 2^(pbits - 2) - 1 augmented by one
|
||||
// /!\ should be called with a = 0
|
||||
|
||||
def main(field a) -> (field):
|
||||
def main(field a) -> (bool):
|
||||
field pbits = 254
|
||||
// maxvalue = 2**252 - 1
|
||||
field maxvalue = a + 7237005577332262213973186563042994240829374041602535252466099000494570602496 - 1
|
||||
// we added a = 0 to prevent the condition to be evaluated at compile time
|
||||
return if 0 < (maxvalue + 1) then 1 else 0 fi
|
||||
return 0 < (maxvalue + 1)
|
|
@ -1,7 +1,7 @@
|
|||
// as p - 1 is greater than p/2, comparing to it should fail
|
||||
// /!\ should be called with a = 0
|
||||
|
||||
def main(field a) -> (field):
|
||||
def main(field a) -> (bool):
|
||||
field p = 21888242871839275222246405745257275088548364400416034343698204186575808495617 + a
|
||||
// we added a = 0 to prevent the condition to be evaluated at compile time
|
||||
return if 0 < p - 1 then 1 else 0 fi
|
||||
return 0 < p - 1
|
58
zokrates_cli/examples/sudoku/prime_sudoku_checker.zok
Normal file
58
zokrates_cli/examples/sudoku/prime_sudoku_checker.zok
Normal file
|
@ -0,0 +1,58 @@
|
|||
// Sudoku of format
|
||||
|
||||
// | a11 | a12 || b11 | b12 |
|
||||
// --------------------------
|
||||
// | a21 | a22 || b21 | b22 |
|
||||
// ==========================
|
||||
// | c11 | c12 || d11 | d12 |
|
||||
// --------------------------
|
||||
// | c21 | c22 || d21 | d22 |
|
||||
|
||||
// We encode values in the following way:
|
||||
// 1 -> 2
|
||||
// 2 -> 3
|
||||
// 3 -> 5
|
||||
// 4 -> 7
|
||||
|
||||
// returns true if there are no duplicates
|
||||
// assumption: `a, b, c, d` are all in `{ 2, 3, 5, 7 }`
|
||||
def checkNoDuplicates(field a, field b, field c, field d) -> (bool):
|
||||
// as `{ 2, 3, 5, 7 }` are primes, the set `{ a, b, c, d }` is equal to the set `{ 2, 3, 5, 7}` if and only if the products match
|
||||
return a * b * c * d == 2 * 3 * 5 * 7
|
||||
|
||||
// returns `0` if and only if `x` in `{ 2, 3, 5, 7 }`
|
||||
def validateInput(field x) -> (bool):
|
||||
return (x-2) * (x-3) * (x-5) * (x-7) == 0
|
||||
|
||||
// variables naming: box'row''column'
|
||||
def main(field a21, field b11, field b22, field c11, field c22, field d21, private field a11, private field a12, private field a22, private field b12, private field b21, private field c12, private field c21, private field d11, private field d12, private field d22) -> (bool):
|
||||
|
||||
field[4][4] a = [[a11, a12, b11, b12], [a21, a22, b21, b22], [c11, c12, d11, d12], [c21, c22, d21, d22]]
|
||||
|
||||
bool res = true
|
||||
|
||||
// go through the whole grid and check that all elements are valid
|
||||
for field i in 0..4 do
|
||||
for field j in 0..4 do
|
||||
res = res && validateInput(a[i][j])
|
||||
endfor
|
||||
endfor
|
||||
|
||||
// go through the 4 2x2 boxes and check that they do not contain duplicates
|
||||
for field i in 0..1 do
|
||||
for field j in 0..1 do
|
||||
res = res && checkNoDuplicates(a[2*i][2*i], a[2*i][2*i + 1], a[2*i + 1][2*i], a[2*i + 1][2*i + 1])
|
||||
endfor
|
||||
endfor
|
||||
|
||||
// go through the 4 rows and check that they do not contain duplicates
|
||||
for field i in 0..4 do
|
||||
res = res && checkNoDuplicates(a[i][0], a[i][1], a[i][2], a[i][3])
|
||||
endfor
|
||||
|
||||
// go through the 4 columns and check that they do not contain duplicates
|
||||
for field j in 0..4 do
|
||||
res = res && checkNoDuplicates(a[0][j], a[1][j], a[2][j], a[3][j])
|
||||
endfor
|
||||
|
||||
return res
|
75
zokrates_cli/examples/sudoku/sudoku_checker.zok
Normal file
75
zokrates_cli/examples/sudoku/sudoku_checker.zok
Normal file
|
@ -0,0 +1,75 @@
|
|||
// Sudoku of format
|
||||
|
||||
// | a11 | a12 || b11 | b12 |
|
||||
// --------------------------
|
||||
// | a21 | a22 || b21 | b22 |
|
||||
// ==========================
|
||||
// | c11 | c12 || d11 | d12 |
|
||||
// --------------------------
|
||||
// | c21 | c22 || d21 | d22 |
|
||||
|
||||
// We use a naive encoding of the values as `[1, 2, 3, 4]` and rely on if-else statements to detect duplicates
|
||||
|
||||
def countDuplicates(field e11,field e12,field e21,field e22) -> (field):
|
||||
field duplicates = if e11 == e12 then 1 else 0 fi
|
||||
duplicates = duplicates + if e11 == e21 then 1 else 0 fi
|
||||
duplicates = duplicates + if e11 == e22 then 1 else 0 fi
|
||||
duplicates = duplicates + if e12 == e21 then 1 else 0 fi
|
||||
duplicates = duplicates + if e12 == e21 then 1 else 0 fi
|
||||
duplicates = duplicates + if e21 == e22 then 1 else 0 fi
|
||||
return duplicates
|
||||
|
||||
// returns 0 for x in (1..4)
|
||||
def validateInput(field x) -> (bool):
|
||||
return (x-1)*(x-2)*(x-3)*(x-4) == 0
|
||||
|
||||
// variables naming: box'row''column'
|
||||
def main(field a21, field b11, field b22, field c11, field c22, field d21, private field a11, private field a12, private field a22, private field b12, private field b21, private field c12, private field c21, private field d11, private field d12, private field d22) -> (bool):
|
||||
|
||||
// validate inputs
|
||||
assert(validateInput(a11))
|
||||
assert(validateInput(a12))
|
||||
assert(validateInput(a21))
|
||||
assert(validateInput(a22))
|
||||
|
||||
assert(validateInput(b11))
|
||||
assert(validateInput(b12))
|
||||
assert(validateInput(b21))
|
||||
assert(validateInput(b22))
|
||||
|
||||
assert(validateInput(c11))
|
||||
assert(validateInput(c12))
|
||||
assert(validateInput(c21))
|
||||
assert(validateInput(c22))
|
||||
|
||||
assert(validateInput(d11))
|
||||
assert(validateInput(d12))
|
||||
assert(validateInput(d21))
|
||||
assert(validateInput(d22))
|
||||
|
||||
field duplicates = 0 // globally counts duplicate entries in boxes, rows and columns
|
||||
|
||||
// check box correctness
|
||||
|
||||
// no duplicates
|
||||
duplicates = duplicates + countDuplicates(a11,a12,a21,a22)
|
||||
duplicates = duplicates + countDuplicates(b11,b12,b21,b22)
|
||||
duplicates = duplicates + countDuplicates(c11,c12,c21,c22)
|
||||
duplicates = duplicates + countDuplicates(d11,d12,d21,d22)
|
||||
|
||||
// check row correctness
|
||||
|
||||
duplicates = duplicates + countDuplicates(a11,a12,b11,b12)
|
||||
duplicates = duplicates + countDuplicates(a21,a22,b21,b22)
|
||||
duplicates = duplicates + countDuplicates(c11,c12,d11,d12)
|
||||
duplicates = duplicates + countDuplicates(c21,c22,d21,d22)
|
||||
|
||||
// check column correctness
|
||||
|
||||
duplicates = duplicates + countDuplicates(a11,a21,c11,c21)
|
||||
duplicates = duplicates + countDuplicates(a12,a22,c12,c22)
|
||||
duplicates = duplicates + countDuplicates(b11,b21,d11,d21)
|
||||
duplicates = duplicates + countDuplicates(b12,b22,d12,d22)
|
||||
|
||||
// the solution is correct if and only if there are no duplicates
|
||||
return duplicates == 0
|
|
@ -1,75 +0,0 @@
|
|||
// Sudoku of format
|
||||
|
||||
// | a11 | a12 || b11 | b12 |
|
||||
// --------------------------
|
||||
// | a21 | a22 || b21 | b22 |
|
||||
// ==========================
|
||||
// | c11 | c12 || d11 | d12 |
|
||||
// --------------------------
|
||||
// | c21 | c22 || d21 | d22 |
|
||||
|
||||
def checkEquality(field e11,field e12,field e21,field e22) -> (field):
|
||||
field counter = if e11 == e12 then 1 else 0 fi
|
||||
counter = counter + if e11 == e21 then 1 else 0 fi
|
||||
counter = counter + if e11 == e22 then 1 else 0 fi
|
||||
counter = counter + if e12 == e21 then 1 else 0 fi
|
||||
counter = counter + if e12 == e21 then 1 else 0 fi
|
||||
counter = counter + if e21 == e22 then 1 else 0 fi
|
||||
return counter
|
||||
|
||||
// returns 0 for x in (1..4)
|
||||
def validateInput(field x) -> (field):
|
||||
return (x-1)*(x-2)*(x-3)*(x-4)
|
||||
|
||||
// variables naming: box'row''column'
|
||||
def main(field a21, field b11, field b22, field c11, field c22, field d21, private field a11, private field a12, private field a22, private field b12, private field b21, private field c12, private field c21, private field d11, private field d12, private field d22) -> (field):
|
||||
|
||||
// validate inputs
|
||||
0 == validateInput(a11)
|
||||
0 == validateInput(a12)
|
||||
0 == validateInput(a21)
|
||||
0 == validateInput(a22)
|
||||
|
||||
0 == validateInput(b11)
|
||||
0 == validateInput(b12)
|
||||
0 == validateInput(b21)
|
||||
0 == validateInput(b22)
|
||||
|
||||
0 == validateInput(c11)
|
||||
0 == validateInput(c12)
|
||||
0 == validateInput(c21)
|
||||
0 == validateInput(c22)
|
||||
|
||||
0 == validateInput(d11)
|
||||
0 == validateInput(d12)
|
||||
0 == validateInput(d21)
|
||||
0 == validateInput(d22)
|
||||
|
||||
field counter = 0 // globally counts duplicate entries in boxes, rows and columns
|
||||
|
||||
// check box correctness
|
||||
|
||||
// no duplicates
|
||||
counter = counter + checkEquality(a11,a12,a21,a22)
|
||||
counter = counter + checkEquality(b11,b12,b21,b22)
|
||||
counter = counter + checkEquality(c11,c12,c21,c22)
|
||||
counter = counter + checkEquality(d11,d12,d21,d22)
|
||||
|
||||
// check row correctness
|
||||
|
||||
counter = counter + checkEquality(a11,a12,b11,b12)
|
||||
counter = counter + checkEquality(a21,a22,b21,b22)
|
||||
counter = counter + checkEquality(c11,c12,d11,d12)
|
||||
counter = counter + checkEquality(c21,c22,d21,d22)
|
||||
|
||||
// check column correctness
|
||||
|
||||
counter = counter + checkEquality(a11,a21,c11,c21)
|
||||
counter = counter + checkEquality(a12,a22,c12,c22)
|
||||
counter = counter + checkEquality(b11,b21,d11,d21)
|
||||
counter = counter + checkEquality(b12,b22,d12,d22)
|
||||
|
||||
// assert counter is 0
|
||||
counter == 0
|
||||
|
||||
return 1
|
|
@ -3,11 +3,11 @@ def main(field x) -> (field):
|
|||
field a = 5
|
||||
field b = 7
|
||||
field c = if a == b then 4 else 3 fi
|
||||
c == 3
|
||||
assert(c == 3)
|
||||
field d = if a == 5 then 1 else 2 fi
|
||||
d == 1
|
||||
assert(d == 1)
|
||||
field e = if a < b then 5 else 6 fi
|
||||
e == 5
|
||||
assert(e == 5)
|
||||
field f = if b < a then 7 else 8 fi
|
||||
f == 8
|
||||
assert(f == 8)
|
||||
return x
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
// we can compare numbers up to 2^(pbits - 2) - 1, ie any number which fits in (pbits - 2) bits
|
||||
// lt should work for the maxvalue = 2^(pbits - 2) - 1
|
||||
|
||||
def main(field a) -> (field):
|
||||
def main(field a) -> (bool):
|
||||
field pbits = 254
|
||||
// maxvalue = 2**252 - 1
|
||||
field maxvalue = 7237005577332262213973186563042994240829374041602535252466099000494570602496 - 1
|
||||
return if 0 < maxvalue then 1 else 0 fi
|
||||
return 0 < maxvalue
|
|
@ -2,24 +2,14 @@
|
|||
// In this example, the crowd is a series of numbers, ideally* all prime but one, and Waldo is a non-prime number
|
||||
// * we don't enforce only one number being non-prime, so there could be multiple Waldos
|
||||
|
||||
def isWaldo(field a, field p, field q) -> (field):
|
||||
// make sure that p and q are both non zero
|
||||
// we can't check inequalities, so let's create binary
|
||||
// variables
|
||||
field p1 = if p == 1 then 0 else 1 fi // "p != 1"
|
||||
field q1 = if q == 1 then 0 else 1 fi // "q != 1"
|
||||
q1 * p1 == 1 // "p1 and q1"
|
||||
def isWaldo(field a, field p, field q) -> (bool):
|
||||
// make sure that p and q are both not one
|
||||
assert(p != 1 && q != 1)
|
||||
|
||||
// we know how to factor a
|
||||
a == p * q
|
||||
|
||||
return 1
|
||||
return a == p * q
|
||||
|
||||
// define all
|
||||
def main(field a0, field a1, field a2, field a3, private field index, private field p, private field q) -> (field):
|
||||
def main(field[3] a, private field index, private field p, private field q) -> (bool):
|
||||
// prover provides the index of Waldo
|
||||
field waldo = if index == 0 then a0 else 0 fi
|
||||
waldo = waldo + if index == 1 then a1 else 0 fi
|
||||
waldo = waldo + if index == 2 then a2 else 0 fi
|
||||
waldo = waldo + if index == 3 then a3 else 0 fi
|
||||
return isWaldo(waldo, p, q)
|
||||
return isWaldo(a[index], p, q)
|
|
@ -1,3 +1,3 @@
|
|||
def main(field a, field b) -> ():
|
||||
a==b
|
||||
assert(a == b)
|
||||
return
|
|
@ -7,7 +7,7 @@ readme = "README.md"
|
|||
build = "build.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
default = ["bellman_ce/nolog"]
|
||||
libsnark = ["cc", "cmake", "git2"]
|
||||
wasm = ["bellman_ce/wasm"]
|
||||
multicore = ["bellman_ce/multicore"]
|
||||
|
|
|
@ -44,6 +44,7 @@ fn main() {
|
|||
.define("USE_PT_COMPRESSION", "OFF")
|
||||
.define("MONTGOMERY_OUTPUT", "ON")
|
||||
.define("BINARY_OUTPUT", "ON")
|
||||
.define("DMULTICORE", "ON")
|
||||
.build();
|
||||
|
||||
// build backends
|
||||
|
|
|
@ -262,23 +262,8 @@ impl<'ast, T: Field> From<pest::AssertionStatement<'ast>> for absy::StatementNod
|
|||
fn from(statement: pest::AssertionStatement<'ast>) -> absy::StatementNode<T> {
|
||||
use absy::NodeValue;
|
||||
|
||||
match statement.expression {
|
||||
pest::Expression::Binary(e) => match e.op {
|
||||
pest::BinaryOperator::Eq => absy::Statement::Condition(
|
||||
absy::ExpressionNode::from(*e.left),
|
||||
absy::ExpressionNode::from(*e.right),
|
||||
),
|
||||
_ => unimplemented!(
|
||||
"Assertion statements should be an equality check, found {}",
|
||||
statement.span.as_str()
|
||||
),
|
||||
},
|
||||
_ => unimplemented!(
|
||||
"Assertion statements should be an equality check, found {}",
|
||||
statement.span.as_str()
|
||||
),
|
||||
}
|
||||
.span(statement.span)
|
||||
absy::Statement::Assertion(absy::ExpressionNode::from(statement.expression))
|
||||
.span(statement.span)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -389,7 +374,14 @@ impl<'ast, T: Field> From<pest::BinaryExpression<'ast>> for absy::ExpressionNode
|
|||
box absy::ExpressionNode::from(*expression.left),
|
||||
box absy::ExpressionNode::from(*expression.right),
|
||||
),
|
||||
o => unimplemented!("Operator {:?} not implemented", o),
|
||||
// rewrite (a != b)` as `!(a == b)`
|
||||
pest::BinaryOperator::NotEq => absy::Expression::Not(
|
||||
box absy::Expression::Eq(
|
||||
box absy::ExpressionNode::from(*expression.left),
|
||||
box absy::ExpressionNode::from(*expression.right),
|
||||
)
|
||||
.span(expression.span.clone()),
|
||||
),
|
||||
}
|
||||
.span(expression.span)
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ pub enum Statement<'ast, T> {
|
|||
Return(ExpressionListNode<'ast, T>),
|
||||
Declaration(VariableNode<'ast>),
|
||||
Definition(AssigneeNode<'ast, T>, ExpressionNode<'ast, T>),
|
||||
Condition(ExpressionNode<'ast, T>, ExpressionNode<'ast, T>),
|
||||
Assertion(ExpressionNode<'ast, T>),
|
||||
For(
|
||||
VariableNode<'ast>,
|
||||
ExpressionNode<'ast, T>,
|
||||
|
@ -317,7 +317,7 @@ impl<'ast, T: fmt::Display> fmt::Display for Statement<'ast, T> {
|
|||
Statement::Return(ref expr) => write!(f, "return {}", expr),
|
||||
Statement::Declaration(ref var) => write!(f, "{}", var),
|
||||
Statement::Definition(ref lhs, ref rhs) => write!(f, "{} = {}", lhs, rhs),
|
||||
Statement::Condition(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
Statement::Assertion(ref e) => write!(f, "assert({})", e),
|
||||
Statement::For(ref var, ref start, ref stop, ref list) => {
|
||||
write!(f, "for {} in {}..{} do\n", var, start, stop)?;
|
||||
for l in list {
|
||||
|
@ -346,7 +346,7 @@ impl<'ast, T: fmt::Debug> fmt::Debug for Statement<'ast, T> {
|
|||
Statement::Definition(ref lhs, ref rhs) => {
|
||||
write!(f, "Definition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
Statement::Condition(ref lhs, ref rhs) => write!(f, "Condition({:?}, {:?})", lhs, rhs),
|
||||
Statement::Assertion(ref e) => write!(f, "Assertion({:?})", e),
|
||||
Statement::For(ref var, ref start, ref stop, ref list) => {
|
||||
write!(f, "for {:?} in {:?}..{:?} do\n", var, start, stop)?;
|
||||
for l in list {
|
||||
|
|
|
@ -140,7 +140,7 @@ impl fmt::Display for CompileErrorInner {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct CompileConfig {
|
||||
is_release: bool,
|
||||
}
|
||||
|
|
|
@ -575,9 +575,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
)
|
||||
}
|
||||
BooleanExpression::FieldEq(box lhs, box rhs) => {
|
||||
// We know from semantic checking that lhs and rhs have the same type
|
||||
// What the expression will flatten to depends on that type
|
||||
|
||||
// Wanted: (Y = (X != 0) ? 1 : 0)
|
||||
// X = a - b
|
||||
// # Y = if X == 0 then 0 else 1 fi
|
||||
|
@ -616,6 +613,53 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
|
||||
res
|
||||
}
|
||||
BooleanExpression::UintEq(box lhs, box rhs) => {
|
||||
// We reduce each side into range and apply the same approach as for field elements
|
||||
|
||||
// Wanted: (Y = (X != 0) ? 1 : 0)
|
||||
// X = a - b
|
||||
// # Y = if X == 0 then 0 else 1 fi
|
||||
// # M = if X == 0 then 1 else 1/X fi
|
||||
// Y == X * M
|
||||
// 0 == (1-Y) * X
|
||||
|
||||
let name_y = self.use_sym();
|
||||
let name_m = self.use_sym();
|
||||
|
||||
assert!(lhs.metadata.clone().unwrap().should_reduce.to_bool());
|
||||
assert!(rhs.metadata.clone().unwrap().should_reduce.to_bool());
|
||||
|
||||
let lhs = self
|
||||
.flatten_uint_expression(symbols, statements_flattened, lhs)
|
||||
.get_field_unchecked();
|
||||
let rhs = self
|
||||
.flatten_uint_expression(symbols, statements_flattened, rhs)
|
||||
.get_field_unchecked();
|
||||
|
||||
let x = FlatExpression::Sub(box lhs, box rhs);
|
||||
|
||||
statements_flattened.push(FlatStatement::Directive(FlatDirective::new(
|
||||
vec![name_y, name_m],
|
||||
Solver::ConditionEq,
|
||||
vec![x.clone()],
|
||||
)));
|
||||
statements_flattened.push(FlatStatement::Condition(
|
||||
FlatExpression::Identifier(name_y),
|
||||
FlatExpression::Mult(box x.clone(), box FlatExpression::Identifier(name_m)),
|
||||
));
|
||||
|
||||
let res = FlatExpression::Sub(
|
||||
box FlatExpression::Number(T::one()),
|
||||
box FlatExpression::Identifier(name_y),
|
||||
);
|
||||
|
||||
statements_flattened.push(FlatStatement::Condition(
|
||||
FlatExpression::Number(T::zero()),
|
||||
FlatExpression::Mult(box res.clone(), box x),
|
||||
));
|
||||
|
||||
res
|
||||
}
|
||||
BooleanExpression::Le(box lhs, box rhs) => {
|
||||
let lt = self.flatten_boolean_expression(
|
||||
symbols,
|
||||
|
@ -1851,24 +1895,22 @@ impl<'ast, T: Field> Flattener<'ast, T> {
|
|||
None => {}
|
||||
}
|
||||
}
|
||||
ZirStatement::Condition(lhs, rhs) => {
|
||||
// flatten expr1 and expr2 to n flattened expressions with n the number of primitive types for expr1
|
||||
// add n conditions to check equality of the n expressions
|
||||
ZirStatement::Assertion(e) => {
|
||||
// naive approach: flatten the boolean to a single field element and constrain it to 1
|
||||
|
||||
let lhs = self
|
||||
.flatten_expression(symbols, statements_flattened, lhs)
|
||||
.get_field_unchecked();
|
||||
let rhs = self
|
||||
.flatten_expression(symbols, statements_flattened, rhs)
|
||||
.get_field_unchecked();
|
||||
let e = self.flatten_boolean_expression(symbols, statements_flattened, e);
|
||||
|
||||
if lhs.is_linear() {
|
||||
statements_flattened.push(FlatStatement::Condition(lhs, rhs));
|
||||
} else if rhs.is_linear() {
|
||||
// swap so that left side is linear
|
||||
statements_flattened.push(FlatStatement::Condition(rhs, lhs));
|
||||
if e.is_linear() {
|
||||
statements_flattened.push(FlatStatement::Condition(
|
||||
e,
|
||||
FlatExpression::Number(T::from(1)),
|
||||
));
|
||||
} else {
|
||||
unreachable!()
|
||||
// swap so that left side is linear
|
||||
statements_flattened.push(FlatStatement::Condition(
|
||||
FlatExpression::Number(T::from(1)),
|
||||
e,
|
||||
));
|
||||
}
|
||||
}
|
||||
ZirStatement::MultipleDefinition(vars, rhs) => {
|
||||
|
|
|
@ -875,27 +875,21 @@ impl<'ast> Checker<'ast> {
|
|||
}
|
||||
.map_err(|e| vec![e])
|
||||
}
|
||||
Statement::Condition(lhs, rhs) => {
|
||||
let checked_lhs = self
|
||||
.check_expression(lhs, module_id, &types)
|
||||
.map_err(|e| vec![e])?;
|
||||
let checked_rhs = self
|
||||
.check_expression(rhs, module_id, &types)
|
||||
Statement::Assertion(e) => {
|
||||
let e = self
|
||||
.check_expression(e, module_id, &types)
|
||||
.map_err(|e| vec![e])?;
|
||||
|
||||
if checked_lhs.get_type() == checked_rhs.get_type() {
|
||||
Ok(TypedStatement::Condition(checked_lhs, checked_rhs))
|
||||
} else {
|
||||
Err(ErrorInner {
|
||||
match e {
|
||||
TypedExpression::Boolean(e) => Ok(TypedStatement::Assertion(e)),
|
||||
e => Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Cannot compare {} of type {:?} to {} of type {:?}",
|
||||
checked_lhs,
|
||||
checked_lhs.get_type(),
|
||||
checked_rhs,
|
||||
checked_rhs.get_type(),
|
||||
"Expected {} to be of type bool, found {}",
|
||||
e,
|
||||
e.get_type(),
|
||||
),
|
||||
})
|
||||
}),
|
||||
}
|
||||
.map_err(|e| vec![e])
|
||||
}
|
||||
|
@ -1543,6 +1537,54 @@ impl<'ast> Checker<'ast> {
|
|||
(TypedExpression::Boolean(e1), TypedExpression::Boolean(e2)) => {
|
||||
Ok(BooleanExpression::BoolEq(box e1, box e2).into())
|
||||
}
|
||||
(TypedExpression::Array(e1), TypedExpression::Array(e2)) => {
|
||||
if e1.get_type() == e2.get_type() {
|
||||
Ok(BooleanExpression::ArrayEq(box e1, box e2).into())
|
||||
} else {
|
||||
Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1,
|
||||
e1.get_type(),
|
||||
e2,
|
||||
e2.get_type()
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
(TypedExpression::Struct(e1), TypedExpression::Struct(e2)) => {
|
||||
if e1.get_type() == e2.get_type() {
|
||||
Ok(BooleanExpression::StructEq(box e1, box e2).into())
|
||||
} else {
|
||||
Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1,
|
||||
e1.get_type(),
|
||||
e2,
|
||||
e2.get_type()
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
(TypedExpression::Uint(e1), TypedExpression::Uint(e2)) => {
|
||||
if e1.get_type() == e2.get_type() {
|
||||
Ok(BooleanExpression::UintEq(box e1, box e2).into())
|
||||
} else {
|
||||
Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
"Cannot compare {} of type {} to {} of type {}",
|
||||
e1,
|
||||
e1.get_type(),
|
||||
e2,
|
||||
e2.get_type()
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
(e1, e2) => Err(ErrorInner {
|
||||
pos: Some(pos),
|
||||
message: format!(
|
||||
|
@ -3136,9 +3178,12 @@ mod tests {
|
|||
// def bar():
|
||||
// 2 == foo()
|
||||
// should fail
|
||||
let bar_statements: Vec<StatementNode<Bn128Field>> = vec![Statement::Condition(
|
||||
Expression::FieldConstant(Bn128Field::from(2)).mock(),
|
||||
Expression::FunctionCall("foo", vec![]).mock(),
|
||||
let bar_statements: Vec<StatementNode<Bn128Field>> = vec![Statement::Assertion(
|
||||
Expression::Eq(
|
||||
box Expression::FieldConstant(Bn128Field::from(2)).mock(),
|
||||
box Expression::FunctionCall("foo", vec![]).mock(),
|
||||
)
|
||||
.mock(),
|
||||
)
|
||||
.mock()];
|
||||
|
||||
|
@ -3535,9 +3580,12 @@ mod tests {
|
|||
// def bar():
|
||||
// 1 == foo()
|
||||
// should fail
|
||||
let bar_statements: Vec<StatementNode<Bn128Field>> = vec![Statement::Condition(
|
||||
Expression::FieldConstant(Bn128Field::from(1)).mock(),
|
||||
Expression::FunctionCall("foo", vec![]).mock(),
|
||||
let bar_statements: Vec<StatementNode<Bn128Field>> = vec![Statement::Assertion(
|
||||
Expression::Eq(
|
||||
box Expression::FieldConstant(Bn128Field::from(1)).mock(),
|
||||
box Expression::FunctionCall("foo", vec![]).mock(),
|
||||
)
|
||||
.mock(),
|
||||
)
|
||||
.mock()];
|
||||
|
||||
|
|
|
@ -248,14 +248,9 @@ pub fn fold_statement<'ast, T: Field>(
|
|||
.map(|v| zir::ZirStatement::Declaration(v))
|
||||
.collect()
|
||||
}
|
||||
typed_absy::TypedStatement::Condition(left, right) => {
|
||||
let left = f.fold_expression(left);
|
||||
let right = f.fold_expression(right);
|
||||
assert_eq!(left.len(), right.len());
|
||||
left.into_iter()
|
||||
.zip(right.into_iter())
|
||||
.map(|(left, right)| zir::ZirStatement::Condition(left, right))
|
||||
.collect()
|
||||
typed_absy::TypedStatement::Assertion(e) => {
|
||||
let e = f.fold_boolean_expression(e);
|
||||
vec![zir::ZirStatement::Assertion(e)]
|
||||
}
|
||||
typed_absy::TypedStatement::For(..) => unreachable!(),
|
||||
typed_absy::TypedStatement::MultipleDefinition(variables, elist) => {
|
||||
|
@ -555,6 +550,68 @@ pub fn fold_boolean_expression<'ast, T: Field>(
|
|||
let e2 = f.fold_boolean_expression(e2);
|
||||
zir::BooleanExpression::BoolEq(box e1, box e2)
|
||||
}
|
||||
typed_absy::BooleanExpression::ArrayEq(box e1, box e2) => {
|
||||
let e1 = f.fold_array_expression(e1);
|
||||
let e2 = f.fold_array_expression(e2);
|
||||
|
||||
assert_eq!(e1.len(), e2.len());
|
||||
|
||||
e1.into_iter().zip(e2.into_iter()).fold(
|
||||
zir::BooleanExpression::Value(true),
|
||||
|acc, (e1, e2)| {
|
||||
zir::BooleanExpression::And(
|
||||
box acc,
|
||||
box match (e1, e2) {
|
||||
(
|
||||
zir::ZirExpression::FieldElement(e1),
|
||||
zir::ZirExpression::FieldElement(e2),
|
||||
) => zir::BooleanExpression::FieldEq(box e1, box e2),
|
||||
(zir::ZirExpression::Boolean(e1), zir::ZirExpression::Boolean(e2)) => {
|
||||
zir::BooleanExpression::BoolEq(box e1, box e2)
|
||||
}
|
||||
(zir::ZirExpression::Uint(e1), zir::ZirExpression::Uint(e2)) => {
|
||||
zir::BooleanExpression::UintEq(box e1, box e2)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
typed_absy::BooleanExpression::StructEq(box e1, box e2) => {
|
||||
let e1 = f.fold_struct_expression(e1);
|
||||
let e2 = f.fold_struct_expression(e2);
|
||||
|
||||
assert_eq!(e1.len(), e2.len());
|
||||
|
||||
e1.into_iter().zip(e2.into_iter()).fold(
|
||||
zir::BooleanExpression::Value(true),
|
||||
|acc, (e1, e2)| {
|
||||
zir::BooleanExpression::And(
|
||||
box acc,
|
||||
box match (e1, e2) {
|
||||
(
|
||||
zir::ZirExpression::FieldElement(e1),
|
||||
zir::ZirExpression::FieldElement(e2),
|
||||
) => zir::BooleanExpression::FieldEq(box e1, box e2),
|
||||
(zir::ZirExpression::Boolean(e1), zir::ZirExpression::Boolean(e2)) => {
|
||||
zir::BooleanExpression::BoolEq(box e1, box e2)
|
||||
}
|
||||
(zir::ZirExpression::Uint(e1), zir::ZirExpression::Uint(e2)) => {
|
||||
zir::BooleanExpression::UintEq(box e1, box e2)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
typed_absy::BooleanExpression::UintEq(box e1, box e2) => {
|
||||
let e1 = f.fold_uint_expression(e1);
|
||||
let e2 = f.fold_uint_expression(e2);
|
||||
|
||||
zir::BooleanExpression::UintEq(box e1, box e2)
|
||||
}
|
||||
typed_absy::BooleanExpression::Lt(box e1, box e2) => {
|
||||
let e1 = f.fold_field_expression(e1);
|
||||
let e2 = f.fold_field_expression(e2);
|
||||
|
|
|
@ -55,7 +55,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
|||
let r = VariableAccessRemover::apply(r);
|
||||
|
||||
// convert to zir, removing complex types
|
||||
let zir = Flattener::flatten(r.clone());
|
||||
let zir = Flattener::flatten(r);
|
||||
|
||||
// optimize uint expressions
|
||||
let zir = UintOptimizer::optimize(zir);
|
||||
|
|
|
@ -112,13 +112,10 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
|
|||
TypedStatement::Definition(TypedAssignee::Member(..), _) => {
|
||||
unreachable!("struct update should have been replaced with full struct redef")
|
||||
}
|
||||
// propagate lhs and rhs for conditions
|
||||
TypedStatement::Condition(e1, e2) => {
|
||||
// propagate the boolean
|
||||
TypedStatement::Assertion(e) => {
|
||||
// could stop execution here if condition is known to fail
|
||||
Some(TypedStatement::Condition(
|
||||
self.fold_expression(e1),
|
||||
self.fold_expression(e2),
|
||||
))
|
||||
Some(TypedStatement::Assertion(self.fold_boolean_expression(e)))
|
||||
}
|
||||
// only loops with variable bounds are expected here
|
||||
// we stop propagation here as constants maybe be modified inside the loop body
|
||||
|
@ -957,6 +954,11 @@ impl<'ast, T: Field> Folder<'ast, T> for Propagator<'ast, T> {
|
|||
&mut self,
|
||||
e: BooleanExpression<'ast, T>,
|
||||
) -> BooleanExpression<'ast, T> {
|
||||
// Note: we only propagate when we see constants, as comparing of arbitrary expressions would lead to
|
||||
// a lot of false negatives due to expressions not being in a canonical form
|
||||
// For example, `2 * a` is equivalent to `a + a`, but our notion of equality would not detect that here
|
||||
// These kind of reduction rules are easier to apply later in the process, when we have canonical representations
|
||||
// of expressions, ie `a + a` would always be written `2 * a`
|
||||
match e {
|
||||
BooleanExpression::Identifier(id) => match self
|
||||
.constants
|
||||
|
|
|
@ -53,6 +53,24 @@ fn force_no_reduce<'ast, T: Field>(e: UExpression<'ast, T>) -> UExpression<'ast,
|
|||
}
|
||||
|
||||
impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
|
||||
fn fold_boolean_expression(
|
||||
&mut self,
|
||||
e: BooleanExpression<'ast, T>,
|
||||
) -> BooleanExpression<'ast, T> {
|
||||
match e {
|
||||
BooleanExpression::UintEq(box left, box right) => {
|
||||
let left = self.fold_uint_expression(left);
|
||||
let right = self.fold_uint_expression(right);
|
||||
|
||||
let left = force_reduce(left);
|
||||
let right = force_reduce(right);
|
||||
|
||||
BooleanExpression::UintEq(box left, box right)
|
||||
}
|
||||
e => fold_boolean_expression(self, e),
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_uint_expression(&mut self, e: UExpression<'ast, T>) -> UExpression<'ast, T> {
|
||||
if e.metadata.is_some() {
|
||||
return e;
|
||||
|
@ -287,6 +305,7 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
|
|||
UExpression::right_shift(force_reduce(e), by).with_max(max)
|
||||
}
|
||||
IfElse(box condition, box consequence, box alternative) => {
|
||||
let condition = self.fold_boolean_expression(condition);
|
||||
let consequence = self.fold_uint_expression(consequence);
|
||||
let alternative = self.fold_uint_expression(alternative);
|
||||
|
||||
|
@ -397,17 +416,17 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
|
|||
)],
|
||||
},
|
||||
},
|
||||
// we need to put back in range to assert
|
||||
ZirStatement::Condition(lhs, rhs) => {
|
||||
match (self.fold_expression(lhs), self.fold_expression(rhs)) {
|
||||
(ZirExpression::Uint(lhs), ZirExpression::Uint(rhs)) => {
|
||||
vec![ZirStatement::Condition(
|
||||
force_reduce(lhs).into(),
|
||||
force_reduce(rhs).into(),
|
||||
)]
|
||||
}
|
||||
(lhs, rhs) => vec![ZirStatement::Condition(lhs, rhs)],
|
||||
}
|
||||
ZirStatement::Assertion(BooleanExpression::UintEq(box left, box right)) => {
|
||||
let left = self.fold_uint_expression(left);
|
||||
let right = self.fold_uint_expression(right);
|
||||
|
||||
// we can only compare two unsigned integers if they are in range
|
||||
let left = force_reduce(left);
|
||||
let right = force_reduce(right);
|
||||
|
||||
vec![ZirStatement::Assertion(BooleanExpression::UintEq(
|
||||
box left, box right,
|
||||
))]
|
||||
}
|
||||
s => fold_statement(self, s),
|
||||
}
|
||||
|
|
|
@ -84,13 +84,12 @@ impl<'ast> Unroller<'ast> {
|
|||
|
||||
match head {
|
||||
Access::Select(head) => {
|
||||
statements.insert(TypedStatement::Condition(
|
||||
statements.insert(TypedStatement::Assertion(
|
||||
BooleanExpression::Lt(
|
||||
box head.clone(),
|
||||
box FieldElementExpression::Number(T::from(size)),
|
||||
)
|
||||
.into(),
|
||||
BooleanExpression::Value(true).into(),
|
||||
));
|
||||
|
||||
ArrayExpressionInner::Value(
|
||||
|
@ -1089,13 +1088,12 @@ mod tests {
|
|||
assert_eq!(
|
||||
u.fold_statement(s),
|
||||
vec![
|
||||
TypedStatement::Condition(
|
||||
TypedStatement::Assertion(
|
||||
BooleanExpression::Lt(
|
||||
box FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
box FieldElementExpression::Number(Bn128Field::from(2))
|
||||
)
|
||||
.into(),
|
||||
BooleanExpression::Value(true).into()
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
TypedAssignee::Identifier(Variable::field_array(
|
||||
|
@ -1227,13 +1225,12 @@ mod tests {
|
|||
assert_eq!(
|
||||
u.fold_statement(s),
|
||||
vec![
|
||||
TypedStatement::Condition(
|
||||
TypedStatement::Assertion(
|
||||
BooleanExpression::Lt(
|
||||
box FieldElementExpression::Number(Bn128Field::from(1)),
|
||||
box FieldElementExpression::Number(Bn128Field::from(2))
|
||||
)
|
||||
.into(),
|
||||
BooleanExpression::Value(true).into()
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
TypedAssignee::Identifier(Variable::with_id_and_type(
|
||||
|
|
|
@ -39,7 +39,7 @@ impl<'ast, T: Field> VariableAccessRemover<'ast, T> {
|
|||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
self.statements.push(TypedStatement::Condition(
|
||||
self.statements.push(TypedStatement::Assertion(
|
||||
(0..size)
|
||||
.map(|index| {
|
||||
BooleanExpression::FieldEq(
|
||||
|
@ -53,7 +53,6 @@ impl<'ast, T: Field> VariableAccessRemover<'ast, T> {
|
|||
})
|
||||
.unwrap()
|
||||
.into(),
|
||||
BooleanExpression::Value(true).into(),
|
||||
));
|
||||
|
||||
(0..size)
|
||||
|
@ -170,7 +169,7 @@ mod tests {
|
|||
assert_eq!(
|
||||
VariableAccessRemover::new().fold_statement(access),
|
||||
vec![
|
||||
TypedStatement::Condition(
|
||||
TypedStatement::Assertion(
|
||||
BooleanExpression::Or(
|
||||
box BooleanExpression::FieldEq(
|
||||
box FieldElementExpression::Identifier("i".into()),
|
||||
|
@ -182,7 +181,6 @@ mod tests {
|
|||
)
|
||||
)
|
||||
.into(),
|
||||
BooleanExpression::Value(true).into()
|
||||
),
|
||||
TypedStatement::Definition(
|
||||
TypedAssignee::Identifier(Variable::field_element("b")),
|
||||
|
|
|
@ -165,9 +165,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
TypedStatement::Definition(f.fold_assignee(a), f.fold_expression(e))
|
||||
}
|
||||
TypedStatement::Declaration(v) => TypedStatement::Declaration(f.fold_variable(v)),
|
||||
TypedStatement::Condition(left, right) => {
|
||||
TypedStatement::Condition(f.fold_expression(left), f.fold_expression(right))
|
||||
}
|
||||
TypedStatement::Assertion(e) => TypedStatement::Assertion(f.fold_boolean_expression(e)),
|
||||
TypedStatement::For(v, from, to, statements) => TypedStatement::For(
|
||||
f.fold_variable(v),
|
||||
from,
|
||||
|
@ -325,6 +323,21 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
let e2 = f.fold_boolean_expression(e2);
|
||||
BooleanExpression::BoolEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::ArrayEq(box e1, box e2) => {
|
||||
let e1 = f.fold_array_expression(e1);
|
||||
let e2 = f.fold_array_expression(e2);
|
||||
BooleanExpression::ArrayEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::StructEq(box e1, box e2) => {
|
||||
let e1 = f.fold_struct_expression(e1);
|
||||
let e2 = f.fold_struct_expression(e2);
|
||||
BooleanExpression::StructEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::UintEq(box e1, box e2) => {
|
||||
let e1 = f.fold_uint_expression(e1);
|
||||
let e2 = f.fold_uint_expression(e2);
|
||||
BooleanExpression::UintEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::Lt(box e1, box e2) => {
|
||||
let e1 = f.fold_field_expression(e1);
|
||||
let e2 = f.fold_field_expression(e2);
|
||||
|
|
|
@ -300,7 +300,7 @@ pub enum TypedStatement<'ast, T> {
|
|||
Return(Vec<TypedExpression<'ast, T>>),
|
||||
Definition(TypedAssignee<'ast, T>, TypedExpression<'ast, T>),
|
||||
Declaration(Variable<'ast>),
|
||||
Condition(TypedExpression<'ast, T>, TypedExpression<'ast, T>),
|
||||
Assertion(BooleanExpression<'ast, T>),
|
||||
For(
|
||||
Variable<'ast>,
|
||||
FieldElementExpression<'ast, T>,
|
||||
|
@ -327,9 +327,7 @@ impl<'ast, T: fmt::Debug> fmt::Debug for TypedStatement<'ast, T> {
|
|||
TypedStatement::Definition(ref lhs, ref rhs) => {
|
||||
write!(f, "Definition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
TypedStatement::Condition(ref lhs, ref rhs) => {
|
||||
write!(f, "Condition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
TypedStatement::Assertion(ref e) => write!(f, "Assertion({:?})", e),
|
||||
TypedStatement::For(ref var, ref start, ref stop, ref list) => {
|
||||
write!(f, "for {:?} in {:?}..{:?} do\n", var, start, stop)?;
|
||||
for l in list {
|
||||
|
@ -376,7 +374,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedStatement<'ast, T> {
|
|||
}
|
||||
TypedStatement::Declaration(ref var) => write!(f, "{}", var),
|
||||
TypedStatement::Definition(ref lhs, ref rhs) => write!(f, "{} = {}", lhs, rhs),
|
||||
TypedStatement::Condition(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
TypedStatement::Assertion(ref e) => write!(f, "assert({})", e),
|
||||
TypedStatement::For(ref var, ref start, ref stop, ref list) => {
|
||||
write!(f, "for {} in {}..{} do\n", var, start, stop)?;
|
||||
for l in list {
|
||||
|
@ -639,6 +637,12 @@ pub enum BooleanExpression<'ast, T> {
|
|||
Box<BooleanExpression<'ast, T>>,
|
||||
Box<BooleanExpression<'ast, T>>,
|
||||
),
|
||||
ArrayEq(Box<ArrayExpression<'ast, T>>, Box<ArrayExpression<'ast, T>>),
|
||||
StructEq(
|
||||
Box<StructExpression<'ast, T>>,
|
||||
Box<StructExpression<'ast, T>>,
|
||||
),
|
||||
UintEq(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
|
||||
Ge(
|
||||
Box<FieldElementExpression<'ast, T>>,
|
||||
Box<FieldElementExpression<'ast, T>>,
|
||||
|
@ -906,6 +910,9 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
|
|||
BooleanExpression::Le(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
|
||||
BooleanExpression::FieldEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::BoolEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::ArrayEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::StructEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::UintEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::Ge(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
|
||||
BooleanExpression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
|
||||
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
|
||||
|
@ -985,6 +992,15 @@ impl<'ast, T: fmt::Debug> fmt::Debug for BooleanExpression<'ast, T> {
|
|||
BooleanExpression::BoolEq(ref lhs, ref rhs) => {
|
||||
write!(f, "BoolEq({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
BooleanExpression::ArrayEq(ref lhs, ref rhs) => {
|
||||
write!(f, "ArrayEq({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
BooleanExpression::StructEq(ref lhs, ref rhs) => {
|
||||
write!(f, "StructEq({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
BooleanExpression::UintEq(ref lhs, ref rhs) => {
|
||||
write!(f, "UintEq({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
BooleanExpression::Ge(ref lhs, ref rhs) => write!(f, "Ge({:?}, {:?})", lhs, rhs),
|
||||
BooleanExpression::Gt(ref lhs, ref rhs) => write!(f, "Gt({:?}, {:?})", lhs, rhs),
|
||||
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "And({:?}, {:?})", lhs, rhs),
|
||||
|
|
|
@ -130,9 +130,7 @@ pub fn fold_statement<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
ZirStatement::Definition(f.fold_assignee(a), f.fold_expression(e))
|
||||
}
|
||||
ZirStatement::Declaration(v) => ZirStatement::Declaration(f.fold_variable(v)),
|
||||
ZirStatement::Condition(left, right) => {
|
||||
ZirStatement::Condition(f.fold_expression(left), f.fold_expression(right))
|
||||
}
|
||||
ZirStatement::Assertion(e) => ZirStatement::Assertion(f.fold_boolean_expression(e)),
|
||||
ZirStatement::MultipleDefinition(variables, elist) => ZirStatement::MultipleDefinition(
|
||||
variables.into_iter().map(|v| f.fold_variable(v)).collect(),
|
||||
f.fold_expression_list(elist),
|
||||
|
@ -201,6 +199,11 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
|||
let e2 = f.fold_boolean_expression(e2);
|
||||
BooleanExpression::BoolEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::UintEq(box e1, box e2) => {
|
||||
let e1 = f.fold_uint_expression(e1);
|
||||
let e2 = f.fold_uint_expression(e2);
|
||||
BooleanExpression::UintEq(box e1, box e2)
|
||||
}
|
||||
BooleanExpression::Lt(box e1, box e2) => {
|
||||
let e1 = f.fold_field_expression(e1);
|
||||
let e2 = f.fold_field_expression(e2);
|
||||
|
|
|
@ -191,7 +191,7 @@ pub enum ZirStatement<'ast, T> {
|
|||
Return(Vec<ZirExpression<'ast, T>>),
|
||||
Definition(ZirAssignee<'ast>, ZirExpression<'ast, T>),
|
||||
Declaration(Variable<'ast>),
|
||||
Condition(ZirExpression<'ast, T>, ZirExpression<'ast, T>),
|
||||
Assertion(BooleanExpression<'ast, T>),
|
||||
MultipleDefinition(Vec<Variable<'ast>>, ZirExpressionList<'ast, T>),
|
||||
}
|
||||
|
||||
|
@ -212,9 +212,7 @@ impl<'ast, T: fmt::Debug> fmt::Debug for ZirStatement<'ast, T> {
|
|||
ZirStatement::Definition(ref lhs, ref rhs) => {
|
||||
write!(f, "Definition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
ZirStatement::Condition(ref lhs, ref rhs) => {
|
||||
write!(f, "Condition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
ZirStatement::Assertion(ref e) => write!(f, "Assertion({:?})", e),
|
||||
ZirStatement::MultipleDefinition(ref lhs, ref rhs) => {
|
||||
write!(f, "MultipleDefinition({:?}, {:?})", lhs, rhs)
|
||||
}
|
||||
|
@ -235,9 +233,9 @@ impl<'ast, T: fmt::Display> fmt::Display for ZirStatement<'ast, T> {
|
|||
}
|
||||
write!(f, "")
|
||||
}
|
||||
ZirStatement::Declaration(ref var) => write!(f, "{}", var),
|
||||
ZirStatement::Declaration(ref var) => write!(f, "assert({})", var),
|
||||
ZirStatement::Definition(ref lhs, ref rhs) => write!(f, "{} = {}", lhs, rhs),
|
||||
ZirStatement::Condition(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
ZirStatement::Assertion(ref e) => write!(f, "{}", e),
|
||||
ZirStatement::MultipleDefinition(ref ids, ref rhs) => {
|
||||
for (i, id) in ids.iter().enumerate() {
|
||||
write!(f, "{}", id)?;
|
||||
|
@ -399,6 +397,7 @@ pub enum BooleanExpression<'ast, T> {
|
|||
Box<BooleanExpression<'ast, T>>,
|
||||
Box<BooleanExpression<'ast, T>>,
|
||||
),
|
||||
UintEq(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
|
||||
Ge(
|
||||
Box<FieldElementExpression<'ast, T>>,
|
||||
Box<FieldElementExpression<'ast, T>>,
|
||||
|
@ -511,6 +510,7 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
|
|||
BooleanExpression::Le(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
|
||||
BooleanExpression::FieldEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::BoolEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::UintEq(ref lhs, ref rhs) => write!(f, "{} == {}", lhs, rhs),
|
||||
BooleanExpression::Ge(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
|
||||
BooleanExpression::Gt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
|
||||
BooleanExpression::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
|
||||
|
|
|
@ -15,7 +15,7 @@ fn out_of_range() {
|
|||
let source = r#"
|
||||
def main(private field a) -> (field):
|
||||
field x = if a < 5555 then 3333 else 4444 fi
|
||||
x == 3333
|
||||
assert(x == 3333)
|
||||
return 1
|
||||
"#
|
||||
.to_string();
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
def main(field a) -> (field):
|
||||
a == 1
|
||||
return 1
|
||||
def main(field a) -> ():
|
||||
assert(a == 1)
|
||||
return
|
|
@ -6,9 +6,9 @@ def local(field a) -> (field): // this costs 3 constraints per call
|
|||
|
||||
def main(field a) -> ():
|
||||
// calling a local function many times with the same arg should cost only once
|
||||
local(a) + local(a) + local(a) + local(a) + local(a) == 5 * (a ** 8)
|
||||
assert(local(a) + local(a) + local(a) + local(a) + local(a) == 5 * (a ** 8))
|
||||
|
||||
// calling an imported function many times with the same arg should cost only once
|
||||
dep(a) + dep(a) + dep(a) + dep(a) + dep(a) == 5 * (a ** 4)
|
||||
assert(dep(a) + dep(a) + dep(a) + dep(a) + dep(a) == 5 * (a ** 4))
|
||||
|
||||
return
|
||||
|
|
|
@ -4,15 +4,11 @@
|
|||
"tests": [
|
||||
{
|
||||
"input": {
|
||||
"values": [
|
||||
"12"
|
||||
]
|
||||
"values": []
|
||||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
"12"
|
||||
]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
def main(field g) -> (field):
|
||||
9 == 1 + 2 * 2 ** 2 // Checks precedence of arithmetic operators (expecting transitive behaviour)
|
||||
9 == 2 ** 2 * 2 + 1
|
||||
7 == 2 ** 2 * 2 - 1
|
||||
3 == 2 ** 2 / 2 + 1
|
||||
def main() -> ():
|
||||
assert(9 == 1 + 2 * 2 ** 2) // Checks precedence of arithmetic operators (expecting transitive behaviour)
|
||||
assert(9 == 2 ** 2 * 2 + 1)
|
||||
assert(7 == 2 ** 2 * 2 - 1)
|
||||
assert(3 == 2 ** 2 / 2 + 1)
|
||||
|
||||
field a = if 3 == 2 ** 2 / 2 + 1 && true then 1 else 0 fi // combines arithmetic with boolean operators
|
||||
field b = if 3 == 3 && 4 < 5 then 1 else 0 fi // checks precedence of boolean operators
|
||||
|
@ -11,6 +11,8 @@ def main(field g) -> (field):
|
|||
field e = if 2 >= 1 && 4 > 5 || 1 == 1 then 1 else 0 fi
|
||||
field f = if 1 < 2 && false || 4 < 5 && 2 >= 1 then 1 else 0 fi
|
||||
|
||||
assert(0x00 ^ 0x00 == 0x00)
|
||||
|
||||
//check if all statements have evalutated to true
|
||||
a * b * c * d * e * f == 1
|
||||
return g
|
||||
assert(a * b * c * d * e * f == 1)
|
||||
return
|
||||
|
|
4
zokrates_core_test/tests/tests/uint/eq.json
Normal file
4
zokrates_core_test/tests/tests/uint/eq.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"entry_point": "./tests/tests/uint/eq.zok",
|
||||
"tests": []
|
||||
}
|
3
zokrates_core_test/tests/tests/uint/eq.zok
Normal file
3
zokrates_core_test/tests/tests/uint/eq.zok
Normal file
|
@ -0,0 +1,3 @@
|
|||
def main(private u32 a, u32 b) -> (field):
|
||||
field result = if a * a == b then 1 else 0 fi
|
||||
return result
|
|
@ -60,47 +60,47 @@ def main(u32 e, u32 f, u32[4] terms) -> ():
|
|||
|
||||
// rotate
|
||||
u32 rotated = right_rotate_4(e)
|
||||
rotated == 0x81234567
|
||||
assert(rotated == 0x81234567)
|
||||
|
||||
// and
|
||||
(e & f) == 0x00204460
|
||||
assert((e & f) == 0x00204460)
|
||||
|
||||
// xor
|
||||
(e ^ f) == 0x1317131f
|
||||
assert((e ^ f) == 0x1317131f)
|
||||
|
||||
// shift
|
||||
e >> 12 == 0x00012345
|
||||
e << 12 == 0x45678000
|
||||
assert(e >> 12 == 0x00012345)
|
||||
assert(e << 12 == 0x45678000)
|
||||
|
||||
// not
|
||||
!e == 0xedcba987
|
||||
assert(!e == 0xedcba987)
|
||||
|
||||
// add
|
||||
terms[0] + terms[1] + terms[2] + terms[3] == 0xddddddda
|
||||
assert(terms[0] + terms[1] + terms[2] + terms[3] == 0xddddddda)
|
||||
|
||||
// to_bits
|
||||
bool[32] bits1 = to_bits(e)
|
||||
bool[32] expected1 = [false, false, false, true, false, false, true, false, false, false, true, true, false, true, false, false, false, true, false, true, false, true, true, false, false, true, true, true, true, false, false, false]
|
||||
bits1 == expected1
|
||||
e == from_bits(expected1)
|
||||
assert(bits1 == expected1)
|
||||
assert(e == from_bits(expected1))
|
||||
|
||||
bool[32] bits2 = to_bits(f)
|
||||
bool[32] expected2 = [false, false, false, false, false, false, false, true, false, false, true, false, false, false, true, true, false, true, false, false, false, true, false, true, false, true, true, false, false, true, true, true]
|
||||
bits2 == expected2
|
||||
f == from_bits(expected2)
|
||||
assert(bits2 == expected2)
|
||||
assert(f == from_bits(expected2))
|
||||
|
||||
// S0
|
||||
u32 e2 = right_rotate_2(e)
|
||||
u32 e13 = right_rotate_13(e)
|
||||
u32 e22 = right_rotate_22(e)
|
||||
u32 S0 = e2 ^ e13 ^ e22
|
||||
S0 == 0x66146474
|
||||
assert(S0 == 0x66146474)
|
||||
|
||||
// S1
|
||||
u32 e6 = right_rotate_6(e)
|
||||
u32 e11 = right_rotate_11(e)
|
||||
u32 e25 = right_rotate_25(e)
|
||||
u32 S1 = e6 ^ e11 ^ e25
|
||||
S1 == 0x3561abda
|
||||
assert(S1 == 0x3561abda)
|
||||
|
||||
return
|
|
@ -54,6 +54,7 @@ def right_rotate_22(u32 e) -> (u32):
|
|||
def right_rotate_25(u32 e) -> (u32):
|
||||
bool[32] b = to_bits(e)
|
||||
u32 res = from_bits([...b[7..], ...b[..7]])
|
||||
|
||||
return res
|
||||
|
||||
def main() -> ():
|
||||
|
@ -62,47 +63,47 @@ def main() -> ():
|
|||
|
||||
// rotate
|
||||
u32 rotated = right_rotate_4(e)
|
||||
rotated == 0x81234567
|
||||
assert(rotated == 0x81234567)
|
||||
|
||||
// and
|
||||
(e & f) == 0x00204460
|
||||
assert((e & f) == 0x00204460)
|
||||
|
||||
// xor
|
||||
(e ^ f) == 0x1317131f
|
||||
assert((e ^ f) == 0x1317131f)
|
||||
|
||||
// shift
|
||||
e >> 12 == 0x00012345
|
||||
e << 12 == 0x45678000
|
||||
assert(e >> 12 == 0x00012345)
|
||||
assert(e << 12 == 0x45678000)
|
||||
|
||||
// not
|
||||
!e == 0xedcba987
|
||||
assert(!e == 0xedcba987)
|
||||
|
||||
// add
|
||||
0xfefefefe + 0xefefefef + 0xffffffff + 0xeeeeeeee == 0xddddddda
|
||||
assert(0xfefefefe + 0xefefefef + 0xffffffff + 0xeeeeeeee == 0xddddddda)
|
||||
|
||||
// to_bits
|
||||
bool[32] bits1 = to_bits(e)
|
||||
bool[32] expected1 = [false, false, false, true, false, false, true, false, false, false, true, true, false, true, false, false, false, true, false, true, false, true, true, false, false, true, true, true, true, false, false, false]
|
||||
bits1 == expected1
|
||||
e == from_bits(expected1)
|
||||
assert(bits1 == expected1)
|
||||
assert(e == from_bits(expected1))
|
||||
|
||||
bool[32] bits2 = to_bits(f)
|
||||
bool[32] expected2 = [false, false, false, false, false, false, false, true, false, false, true, false, false, false, true, true, false, true, false, false, false, true, false, true, false, true, true, false, false, true, true, true]
|
||||
bits2 == expected2
|
||||
f == from_bits(expected2)
|
||||
assert(bits2 == expected2)
|
||||
assert(f == from_bits(expected2))
|
||||
|
||||
// S0
|
||||
u32 e2 = right_rotate_2(e)
|
||||
u32 e13 = right_rotate_13(e)
|
||||
u32 e22 = right_rotate_22(e)
|
||||
u32 S0 = e2 ^ e13 ^ e22
|
||||
S0 == 0x66146474
|
||||
assert(S0 == 0x66146474)
|
||||
|
||||
// S1
|
||||
u32 e6 = right_rotate_6(e)
|
||||
u32 e11 = right_rotate_11(e)
|
||||
u32 e25 = right_rotate_25(e)
|
||||
u32 S1 = e6 ^ e11 ^ e25
|
||||
S1 == 0x3561abda
|
||||
assert(S1 == 0x3561abda)
|
||||
|
||||
return
|
10
zokrates_js/.gitignore
vendored
10
zokrates_js/.gitignore
vendored
|
@ -1,7 +1,7 @@
|
|||
node_modules
|
||||
/dist
|
||||
/target
|
||||
/pkg
|
||||
/wasm-pack.log
|
||||
/stdlib
|
||||
dist
|
||||
target
|
||||
pkg
|
||||
wasm-pack.log
|
||||
stdlib
|
||||
stdlib.json
|
1172
zokrates_js/Cargo.lock
generated
1172
zokrates_js/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "zokrates_js"
|
||||
version = "1.0.22"
|
||||
version = "1.0.23"
|
||||
authors = ["Darko Macesic"]
|
||||
edition = "2018"
|
||||
|
||||
|
|
|
@ -19,19 +19,42 @@ npm install zokrates-js
|
|||
|
||||
## Usage
|
||||
|
||||
### Importing
|
||||
|
||||
Bundlers
|
||||
```js
|
||||
import { initialize } from 'zokrates-js';
|
||||
```
|
||||
|
||||
function importResolver(location, path) {
|
||||
Node
|
||||
```js
|
||||
const { initialize } = require('zokrates-js/node');
|
||||
```
|
||||
|
||||
### Example
|
||||
```js
|
||||
function importResolver(currentLocation, importLocation) {
|
||||
// implement your resolving logic here
|
||||
return {
|
||||
source: "def main() -> (): return",
|
||||
location: path
|
||||
location: importLocation
|
||||
};
|
||||
}
|
||||
|
||||
initialize().then((zokratesProvider) => {
|
||||
// we have to initialize the wasm module before calling api functions
|
||||
zokratesProvider.compile("def main(private field a) -> (field): return a", "main", importResolver)
|
||||
// compilation
|
||||
const artifacts = zokratesProvider.compile("def main(private field a) -> (field): return a * a", "main", importResolver);
|
||||
|
||||
// computation
|
||||
const { witness, output } = zokratesProvider.computeWitness(artifacts, ["2"]);
|
||||
|
||||
// run setup
|
||||
const keypair = zokratesProvider.setup(artifacts.program);
|
||||
|
||||
// generate proof
|
||||
const proof = zokratesProvider.generateProof(artifacts.program, witness, keypair.pk);
|
||||
|
||||
// export solidity verifier
|
||||
const verifier = zokratesProvider.exportSolidityVerifier(keypair.vk, "v1");
|
||||
});
|
||||
```
|
|
@ -5,7 +5,7 @@ const fs = require('fs');
|
|||
const path = require('path');
|
||||
|
||||
/** stdlib constants */
|
||||
const stdlibRoot = '../zokrates_stdlib/stdlib';
|
||||
const stdlibRoot = '../zokrates_stdlib/stdlib';
|
||||
const output = 'stdlib.json';
|
||||
|
||||
const options = {
|
||||
|
@ -15,7 +15,7 @@ const options = {
|
|||
/**
|
||||
* Serializes standard library directory tree to a json file.
|
||||
*/
|
||||
gulp.task('stdlib', function (done) {
|
||||
gulp.task('stdlib', (done) => {
|
||||
var stdlib = {};
|
||||
dree.scan(stdlibRoot, options, function (file) {
|
||||
const content = fs.readFileSync(file.path).toString();
|
||||
|
|
6
zokrates_js/index.d.ts
vendored
6
zokrates_js/index.d.ts
vendored
|
@ -4,6 +4,10 @@ declare module 'zokrates-js' {
|
|||
export type G2Affine = [G1Affine, G1Affine];
|
||||
export type ProvingKey = Uint8Array;
|
||||
|
||||
export interface CompileConfig {
|
||||
is_release: boolean
|
||||
}
|
||||
|
||||
export interface VerificationKey {
|
||||
alpha: G1Affine,
|
||||
beta: G2Affine,
|
||||
|
@ -49,7 +53,7 @@ declare module 'zokrates-js' {
|
|||
export type ResolveCallback = (location: string, path: string) => ResolverResult;
|
||||
|
||||
export interface ZoKratesProvider {
|
||||
compile(source: string, location: string, callback: ResolveCallback): CompilationArtifacts;
|
||||
compile(source: string, location: string, callback: ResolveCallback, config?: CompileConfig): CompilationArtifacts;
|
||||
setup(program: Uint8Array): SetupKeypair;
|
||||
computeWitness(artifacts: CompilationArtifacts, args: any[]): ComputationResult;
|
||||
exportSolidityVerifier(verifyingKey: VerificationKey, abi: SolidityAbi): string;
|
||||
|
|
|
@ -1,61 +1,9 @@
|
|||
import { appendExtension, getAbsolutePath } from './utils';
|
||||
import wrapper from './wrapper';
|
||||
import stdlib from './stdlib.json';
|
||||
|
||||
const initialize = async () => {
|
||||
|
||||
const EXTENSION_ZOK = '.zok';
|
||||
const RESERVED_PATHS = [
|
||||
'ecc/',
|
||||
'signature/',
|
||||
'hashes/',
|
||||
'utils/'
|
||||
];
|
||||
|
||||
// load web assembly module
|
||||
const zokrates = await import('./pkg/index.js');
|
||||
|
||||
const resolveModule = (currentLocation, importLocation, callback) => {
|
||||
if (isReserved(currentLocation) || isReserved(importLocation)) {
|
||||
return resolveFromStandardLibrary(currentLocation, importLocation);
|
||||
}
|
||||
return callback(currentLocation, importLocation);
|
||||
}
|
||||
|
||||
const isReserved = (path) => RESERVED_PATHS.some(p => path.startsWith(p));
|
||||
|
||||
const resolveFromStandardLibrary = (currentLocation, importLocation) => {
|
||||
let key = appendExtension(getAbsolutePath(currentLocation, importLocation), EXTENSION_ZOK);
|
||||
let source = stdlib[key];
|
||||
return source ? { source, location: key } : null;
|
||||
}
|
||||
|
||||
return {
|
||||
compile: (source, location, callback) => {
|
||||
let result = zokrates.compile(source, location, (currentLocation, importLocation) =>
|
||||
resolveModule(currentLocation, importLocation, callback)
|
||||
);
|
||||
return {
|
||||
program: Array.from(result.program),
|
||||
abi: result.abi
|
||||
}
|
||||
},
|
||||
setup: (program) => {
|
||||
let result = zokrates.setup(program);
|
||||
return {
|
||||
vk: result.vk,
|
||||
pk: Array.from(result.pk)
|
||||
};
|
||||
},
|
||||
computeWitness: (artifacts, args) => {
|
||||
return zokrates.compute_witness(artifacts, JSON.stringify(Array.from(args)));
|
||||
},
|
||||
exportSolidityVerifier: (verifyingKey, abiVersion) => {
|
||||
return zokrates.export_solidity_verifier(verifyingKey, abiVersion);
|
||||
},
|
||||
generateProof: (program, witness, provingKey) => {
|
||||
return zokrates.generate_proof(program, witness, provingKey);
|
||||
}
|
||||
}
|
||||
return wrapper({ zokrates, stdlib });
|
||||
}
|
||||
|
||||
export { initialize };
|
11
zokrates_js/node/index.js
Normal file
11
zokrates_js/node/index.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
const wrapper = require('../wrapper.js');
|
||||
const stdlib = require('../stdlib.json');
|
||||
|
||||
const initialize = async () => {
|
||||
return wrapper({
|
||||
zokrates: require('./pkg/index.js'),
|
||||
stdlib
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { initialize };
|
|
@ -10,21 +10,25 @@
|
|||
],
|
||||
"license": "GPLv3",
|
||||
"files": [
|
||||
"node",
|
||||
"pkg",
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"utils.js",
|
||||
"wrapper.js",
|
||||
"stdlib.json",
|
||||
"README.md"
|
||||
],
|
||||
"types": "index.d.ts",
|
||||
"scripts": {
|
||||
"cargo:build": "cargo build --target=wasm32-unknown-unknown",
|
||||
"wasm-pack:build": "wasm-pack build --out-name index --release --target bundler",
|
||||
"wasm-pack": "wasm-pack build --out-name index --release",
|
||||
"setup": "npm install && gulp stdlib",
|
||||
"prebuild": "npm run setup",
|
||||
"build": "rimraf pkg && npm run wasm-pack:build",
|
||||
"pretest": "npm run setup",
|
||||
"build": "npm run build:bundler && npm run build:node",
|
||||
"build:bundler": "rimraf pkg && npm run wasm-pack -- --target bundler && npm run clean-pkg",
|
||||
"build:node": "rimraf node/pkg && npm run wasm-pack -- --target nodejs -d node/pkg && npm run clean-node-pkg",
|
||||
"clean-pkg": "find pkg/* | grep -P \"^.*\\.(md|d\\.ts)$\" | xargs rm",
|
||||
"clean-node-pkg": "find node/pkg/* | grep -P \"^.*\\.(md|d\\.ts)$\" | xargs rm",
|
||||
"pretest": "npm run setup && npm run build:node",
|
||||
"test": "mocha --require esm --recursive tests"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -10,8 +10,8 @@ use zokrates_core::compile::{
|
|||
};
|
||||
use zokrates_core::imports::Error;
|
||||
use zokrates_core::ir;
|
||||
use zokrates_core::proof_system::{ProofSystem, SolidityAbi};
|
||||
use zokrates_core::proof_system::bellman::groth16::G16;
|
||||
use zokrates_core::proof_system::{ProofSystem, SolidityAbi};
|
||||
use zokrates_core::typed_absy::abi::Abi;
|
||||
use zokrates_core::typed_absy::types::Signature;
|
||||
use zokrates_field::Bn128Field;
|
||||
|
@ -77,7 +77,7 @@ impl<'a> Resolver<Error> for JsResolver<'a> {
|
|||
)
|
||||
.map_err(|_| {
|
||||
Error::new(format!(
|
||||
"Error thrown in callback: could not resolve {}",
|
||||
"Error thrown in JS callback: could not resolve {}",
|
||||
import_location.display()
|
||||
))
|
||||
})?;
|
||||
|
@ -99,15 +99,26 @@ pub fn compile(
|
|||
source: JsValue,
|
||||
location: JsValue,
|
||||
resolve: &js_sys::Function,
|
||||
config: JsValue,
|
||||
) -> Result<JsValue, JsValue> {
|
||||
let fmt_error = |e: &CompileError| format!("{}:{}", e.file().display(), e.value());
|
||||
let resolver = JsResolver::new(resolve);
|
||||
|
||||
let config: CompileConfig = {
|
||||
if config.is_object() {
|
||||
config
|
||||
.into_serde()
|
||||
.map_err(|e| JsValue::from_str(&format!("Invalid config format: {}", e)))?
|
||||
} else {
|
||||
CompileConfig::default()
|
||||
}
|
||||
};
|
||||
|
||||
let artifacts: CompilationArtifacts<Bn128Field> = core_compile(
|
||||
source.as_string().unwrap(),
|
||||
PathBuf::from(location.as_string().unwrap()),
|
||||
Some(&resolver),
|
||||
&CompileConfig::default().with_is_release(true),
|
||||
&config,
|
||||
)
|
||||
.map_err(|ce| {
|
||||
JsValue::from_str(&format!(
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
const assert = require('assert');
|
||||
const utils = require('../utils');
|
||||
const stdlib = require('../stdlib.json');
|
||||
|
||||
describe('stdlib', function() {
|
||||
|
||||
it('should resolve module from stdlib (1)', function() {
|
||||
let basePath = 'hashes/sha256/512bitPacked.zok';
|
||||
let relativePath = '../../utils/pack/u32/pack128';
|
||||
|
||||
let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok');
|
||||
assert.notEqual(stdlib[absolutePath], undefined);
|
||||
});
|
||||
|
||||
it('should resolve module from stdlib (2)', function() {
|
||||
let basePath = 'hashes/sha256/256bitPadded.zok';
|
||||
let relativePath = './512bit';
|
||||
|
||||
let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok');
|
||||
assert.notEqual(stdlib[absolutePath], undefined);
|
||||
});
|
||||
|
||||
it('should resolve module from stdlib (3)', function() {
|
||||
let basePath = 'hashes/pedersen/6bit.zok';
|
||||
let relativePath = 'ecc/babyjubjubParams';
|
||||
|
||||
let absolutePath = utils.appendExtension(utils.getAbsolutePath(basePath, relativePath), '.zok');
|
||||
assert.notEqual(stdlib[absolutePath], undefined);
|
||||
});
|
||||
});
|
123
zokrates_js/tests/tests.js
Normal file
123
zokrates_js/tests/tests.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
const assert = require('assert');
|
||||
const { initialize } = require('../node/index.js');
|
||||
|
||||
describe('tests', function() {
|
||||
|
||||
// initialize once before running tests
|
||||
before(function (done) {
|
||||
initialize().then(zokrates => {
|
||||
this.zokrates = zokrates;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("compilation", () => {
|
||||
it('should compile', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const artifacts = this.zokrates.compile("def main() -> (field): return 42", "main");
|
||||
assert.ok(artifacts !== undefined);
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid code', function() {
|
||||
assert.throws(() => this.zokrates.compile(":-)", "main"));
|
||||
});
|
||||
|
||||
it('should resolve stdlib module', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'import "hashes/sha256/512bit" as sha256\ndef main() -> (): return';
|
||||
this.zokrates.compile(code, "main");
|
||||
})
|
||||
});
|
||||
|
||||
it('should resolve user module', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'import "test" as test\ndef main() -> (field): return test()';
|
||||
this.zokrates.compile(code, "main", (_, path) => {
|
||||
return {
|
||||
source: "def main() -> (field): return 1",
|
||||
location: path
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid module', function() {
|
||||
assert.throws(() => {
|
||||
const code = 'import "test" as test\ndef main() -> (field): return test()';
|
||||
this.zokrates.compile(code, "main", (_loc, _path) => null);
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe("computation", () => {
|
||||
it('should compute with valid inputs', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
|
||||
const result = this.zokrates.computeWitness(artifacts, ["2"])
|
||||
const output = JSON.parse(result.output);
|
||||
|
||||
assert.deepEqual(output, ["4"]);
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid input count', function() {
|
||||
assert.throws(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
|
||||
this.zokrates.computeWitness(artifacts, ["1", "2"])
|
||||
})
|
||||
});
|
||||
|
||||
it('should throw on invalid input type', function() {
|
||||
assert.throws(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
|
||||
this.zokrates.computeWitness(artifacts, [true])
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe("setup", () => {
|
||||
it('should run setup', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
|
||||
this.zokrates.setup(artifacts.program);
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe("export-verifier", () => {
|
||||
it('should export solidity verifier', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
const keypair = this.zokrates.setup(artifacts.program);
|
||||
|
||||
const verifier = this.zokrates.exportSolidityVerifier(keypair.vk, "v1");
|
||||
assert.ok(verifier.length > 0)
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
describe("generate-proof", () => {
|
||||
it('should generate proof', function() {
|
||||
assert.doesNotThrow(() => {
|
||||
const code = 'def main(private field a) -> (field): return a * a';
|
||||
const artifacts = this.zokrates.compile(code, "main", null);
|
||||
const computationResult = this.zokrates.computeWitness(artifacts, ["2"])
|
||||
const keypair = this.zokrates.setup(artifacts.program);
|
||||
const proof = this.zokrates.generateProof(artifacts.program, computationResult.witness, keypair.pk);
|
||||
|
||||
assert.ok(proof !== undefined);
|
||||
assert.deepEqual(proof.inputs, ["0x0000000000000000000000000000000000000000000000000000000000000004"])
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,29 +0,0 @@
|
|||
const assert = require('assert')
|
||||
const utils = require('../utils');
|
||||
|
||||
describe('absolute path resolving', function() {
|
||||
|
||||
it('should resolve valid absolute path (root)', function() {
|
||||
let basePath = 'hashes/pedersen/6bit';
|
||||
let relativePath = 'ecc/babyjubjubParams';
|
||||
|
||||
let absolutePath = utils.getAbsolutePath(basePath, relativePath);
|
||||
assert.equal(absolutePath, 'ecc/babyjubjubParams');
|
||||
});
|
||||
|
||||
it('should resolve valid absolute path (../)', function() {
|
||||
let basePath = 'hashes/sha256/512bitPacked';
|
||||
let relativePath = '../../utils/pack/u32/pack128';
|
||||
|
||||
let absolutePath = utils.getAbsolutePath(basePath, relativePath);
|
||||
assert.equal(absolutePath, 'utils/pack/u32/pack128');
|
||||
});
|
||||
|
||||
it('should resolve valid absolute path (./)', function() {
|
||||
let basePath = 'hashes/sha256/256bitPadded';
|
||||
let relativePath = './512bit';
|
||||
|
||||
let absolutePath = utils.getAbsolutePath(basePath, relativePath);
|
||||
assert.equal(absolutePath, 'hashes/sha256/512bit');
|
||||
});
|
||||
});
|
|
@ -1,26 +0,0 @@
|
|||
export function getAbsolutePath(basePath, relativePath) {
|
||||
if (relativePath[0] !== '.') {
|
||||
return relativePath;
|
||||
}
|
||||
var stack = basePath.split('/');
|
||||
var chunks = relativePath.split('/');
|
||||
stack.pop();
|
||||
|
||||
for(var i = 0; i < chunks.length; i++) {
|
||||
if (chunks[i] == '.') {
|
||||
continue;
|
||||
} else if (chunks[i] == '..') {
|
||||
stack.pop();
|
||||
} else {
|
||||
stack.push(chunks[i]);
|
||||
}
|
||||
}
|
||||
return stack.join('/');
|
||||
}
|
||||
|
||||
export function appendExtension(path, extension) {
|
||||
if (path.endsWith(extension)) {
|
||||
return path;
|
||||
}
|
||||
return path.concat(extension);
|
||||
}
|
62
zokrates_js/wrapper.js
Normal file
62
zokrates_js/wrapper.js
Normal file
|
@ -0,0 +1,62 @@
|
|||
const getAbsolutePath = (basePath, relativePath) => {
|
||||
var stack = basePath.split('/');
|
||||
var chunks = relativePath.split('/');
|
||||
stack.pop();
|
||||
|
||||
for (var i = 0; i < chunks.length; i++) {
|
||||
if (chunks[i] == '.') {
|
||||
continue;
|
||||
} else if (chunks[i] == '..') {
|
||||
stack.pop();
|
||||
} else {
|
||||
stack.push(chunks[i]);
|
||||
}
|
||||
}
|
||||
return stack.join('/');
|
||||
}
|
||||
|
||||
const getImportPath = (currentLocation, importLocation) => {
|
||||
let path = getAbsolutePath(currentLocation, importLocation);
|
||||
const extension = importLocation.slice((path.lastIndexOf(".") - 1 >>> 0) + 2);
|
||||
return extension ? path : path.concat('.zok');
|
||||
}
|
||||
|
||||
module.exports = (dep) => {
|
||||
|
||||
const { zokrates, stdlib } = dep;
|
||||
|
||||
const resolveFromStdlib = (currentLocation, importLocation) => {
|
||||
let key = getImportPath(currentLocation, importLocation);
|
||||
let source = stdlib[key];
|
||||
return source ? { source, location: key } : null;
|
||||
}
|
||||
|
||||
return {
|
||||
compile: (source, location, callback) => {
|
||||
let importCallback = (currentLocation, importLocation) => {
|
||||
return resolveFromStdlib(currentLocation, importLocation) || callback(currentLocation, importLocation);
|
||||
};
|
||||
const { program, abi } = zokrates.compile(source, location, importCallback);
|
||||
return {
|
||||
program: Array.from(program),
|
||||
abi
|
||||
}
|
||||
},
|
||||
setup: (program) => {
|
||||
const { vk, pk } = zokrates.setup(program);
|
||||
return {
|
||||
vk,
|
||||
pk: Array.from(pk)
|
||||
};
|
||||
},
|
||||
computeWitness: (artifacts, args) => {
|
||||
return zokrates.compute_witness(artifacts, JSON.stringify(Array.from(args)));
|
||||
},
|
||||
exportSolidityVerifier: (verificationKey, abiVersion) => {
|
||||
return zokrates.export_solidity_verifier(verificationKey, abiVersion);
|
||||
},
|
||||
generateProof: (program, witness, provingKey) => {
|
||||
return zokrates.generate_proof(program, witness, provingKey);
|
||||
}
|
||||
}
|
||||
};
|
|
@ -37,7 +37,7 @@ ace.define("ace/mode/zokrates_highlight_rules",["require","exports","module","ac
|
|||
var ZoKratesHighlightRules = function () {
|
||||
|
||||
var keywords = (
|
||||
"endfor|as|return|byte|field|bool|if|then|fi|do|else|export|false|def|for|import|from|uint|in|public|private|struct|true"
|
||||
"assert|endfor|as|return|byte|field|bool|if|then|fi|do|else|export|false|def|for|import|from|uint|in|public|private|struct|true"
|
||||
);
|
||||
|
||||
var keywordMapper = this.createKeywordMapper({
|
||||
|
|
|
@ -46,7 +46,7 @@ statement = { (return_statement // does not require subsequent newline
|
|||
iteration_statement = { "for" ~ ty ~ identifier ~ "in" ~ expression ~ ".." ~ expression ~ "do" ~ NEWLINE* ~ statement* ~ "endfor"}
|
||||
return_statement = { "return" ~ expression_list}
|
||||
definition_statement = { optionally_typed_assignee_list ~ "=" ~ expression } // declare and assign, so only identifiers are allowed, unlike `assignment_statement`
|
||||
expression_statement = {expression}
|
||||
expression_statement = {"assert" ~ "(" ~ expression ~ ")"}
|
||||
|
||||
optionally_typed_assignee_list = _{ optionally_typed_assignee ~ ("," ~ optionally_typed_assignee)* }
|
||||
optionally_typed_assignee = { (ty ~ assignee) | (assignee) } // we don't use { ty? ~ identifier } as with a single token, it gets parsed as `ty` but we want `identifier`
|
||||
|
@ -124,6 +124,8 @@ op_unary = { op_not }
|
|||
WHITESPACE = _{ " " | "\t" | "\\" ~ NEWLINE}
|
||||
COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
|
||||
|
||||
keyword = @{"as"|"bool"|"byte"|"def"|"do"|"else"|"endfor"|"export"|"false"|"field"|"for"|"if"|"then"|"fi"|"import"|"from"|
|
||||
// the ordering of reserved keywords matters: if "as" is before "assert", then "assert" gets parsed as (as)(sert) and incorrectly
|
||||
// accepted
|
||||
keyword = @{"assert"|"as"|"bool"|"byte"|"def"|"do"|"else"|"endfor"|"export"|"false"|"field"|"for"|"if"|"then"|"fi"|"import"|"from"|
|
||||
"in"|"private"|"public"|"return"|"struct"|"true"|"u8"|"u16"|"u32"
|
||||
}
|
||||
|
|
|
@ -32,21 +32,22 @@ mod ast {
|
|||
static ref PREC_CLIMBER: PrecClimber<Rule> = build_precedence_climber();
|
||||
}
|
||||
|
||||
// based on https://docs.python.org/3/reference/expressions.html#operator-precedence
|
||||
fn build_precedence_climber() -> PrecClimber<Rule> {
|
||||
PrecClimber::new(vec![
|
||||
Operator::new(Rule::op_or, Assoc::Left),
|
||||
Operator::new(Rule::op_and, Assoc::Left),
|
||||
Operator::new(Rule::op_lt, Assoc::Left)
|
||||
| Operator::new(Rule::op_lte, Assoc::Left)
|
||||
| Operator::new(Rule::op_gt, Assoc::Left)
|
||||
| Operator::new(Rule::op_gte, Assoc::Left)
|
||||
| Operator::new(Rule::op_not_equal, Assoc::Left)
|
||||
| Operator::new(Rule::op_equal, Assoc::Left),
|
||||
Operator::new(Rule::op_bit_or, Assoc::Left),
|
||||
Operator::new(Rule::op_bit_xor, Assoc::Left),
|
||||
Operator::new(Rule::op_bit_and, Assoc::Left),
|
||||
Operator::new(Rule::op_equal, Assoc::Left)
|
||||
| Operator::new(Rule::op_not_equal, Assoc::Left),
|
||||
Operator::new(Rule::op_lte, Assoc::Left)
|
||||
| Operator::new(Rule::op_gte, Assoc::Left)
|
||||
| Operator::new(Rule::op_lt, Assoc::Left)
|
||||
| Operator::new(Rule::op_gt, Assoc::Left),
|
||||
Operator::new(Rule::op_right_shift, Assoc::Left)
|
||||
| Operator::new(Rule::op_left_shift, Assoc::Left),
|
||||
Operator::new(Rule::op_left_shift, Assoc::Left)
|
||||
| Operator::new(Rule::op_right_shift, Assoc::Left),
|
||||
Operator::new(Rule::op_add, Assoc::Left) | Operator::new(Rule::op_sub, Assoc::Left),
|
||||
Operator::new(Rule::op_mul, Assoc::Left) | Operator::new(Rule::op_div, Assoc::Left),
|
||||
Operator::new(Rule::op_pow, Assoc::Left),
|
||||
|
@ -1174,9 +1175,9 @@ mod tests {
|
|||
field a = 1
|
||||
a[32 + x][55] = y
|
||||
for field i in 0..3 do
|
||||
a == 1 + 2 + 3+ 4+ 5+ 6+ 6+ 7+ 8 + 4+ 5+ 3+ 4+ 2+ 3
|
||||
assert(a == 1 + 2 + 3+ 4+ 5+ 6+ 6+ 7+ 8 + 4+ 5+ 3+ 4+ 2+ 3)
|
||||
endfor
|
||||
a.member == 1
|
||||
assert(a.member == 1)
|
||||
return a
|
||||
"#;
|
||||
let res = generate_ast(&source);
|
||||
|
|
|
@ -4,7 +4,7 @@ from "ecc/babyjubjubParams" import BabyJubJubParams
|
|||
// Curve parameters are defined with the last argument
|
||||
// See appendix 3.3.1 of Zcash protocol specification:
|
||||
// https://github.com/zcash/zips/blob/master/protocol/protocol.pdf
|
||||
def main(field[2] pt, BabyJubJubParams context) -> (field):
|
||||
def main(field[2] pt, BabyJubJubParams context) -> (bool):
|
||||
|
||||
field a = context.JUBJUBA
|
||||
field d = context.JUBJUBD
|
||||
|
@ -13,6 +13,6 @@ def main(field[2] pt, BabyJubJubParams context) -> (field):
|
|||
field vv = pt[1] * pt[1]
|
||||
field uuvv = uu * vv
|
||||
|
||||
a * uu + vv == 1 + d * uuvv
|
||||
assert(a * uu + vv == 1 + d * uuvv)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
|
|
@ -6,14 +6,14 @@ from "ecc/babyjubjubParams" import BabyJubJubParams
|
|||
// Verifies that the point is not one of the low-order points.
|
||||
// If any of the points is multiplied by the cofactor, the resulting point
|
||||
// will be infinity.
|
||||
// Returns 1 if the point is not one of the low-order points, 0 otherwise.
|
||||
// Returns true if the point is not one of the low-order points, false otherwise.
|
||||
// Curve parameters are defined with the last argument
|
||||
// https://github.com/zcash-hackworks/sapling-crypto/blob/master/src/jubjub/edwards.rs#L166
|
||||
def main(field[2] pt, BabyJubJubParams context) -> (field):
|
||||
def main(field[2] pt, BabyJubJubParams context) -> (bool):
|
||||
|
||||
field cofactor = context.JUBJUBC
|
||||
|
||||
cofactor == 8
|
||||
assert(cofactor == 8)
|
||||
|
||||
// Co-factor currently hard-coded to 8 for efficiency reasons
|
||||
// See discussion here: https://github.com/Zokrates/ZoKrates/pull/301#discussion_r267203391
|
||||
|
@ -24,6 +24,4 @@ def main(field[2] pt, BabyJubJubParams context) -> (field):
|
|||
ptExp = add(ptExp, ptExp, context) // 4*pt
|
||||
ptExp = add(ptExp, ptExp, context) // 8*pt
|
||||
|
||||
field out = if ptExp[0] == 0 && ptExp[1] == 1 then 0 else 1 fi
|
||||
|
||||
return out
|
||||
return !(ptExp[0] == 0 && ptExp[1] == 1)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import "ecc/edwardsAdd" as add
|
||||
import "ecc/edwardsOnCurve" as assertOnCurve
|
||||
import "ecc/edwardsOnCurve" as onCurve
|
||||
from "ecc/babyjubjubParams" import BabyJubJubParams
|
||||
|
||||
// Function that implements scalar multiplication for a fixed base point
|
||||
|
@ -22,6 +22,6 @@ def main(bool[256] exponent, field[2] pt, BabyJubJubParams context) -> (field[2]
|
|||
doubledP = add(doubledP, doubledP, context)
|
||||
endfor
|
||||
|
||||
1 == assertOnCurve(accumulatedP, context)
|
||||
assert(onCurve(accumulatedP, context))
|
||||
|
||||
return accumulatedP
|
|
@ -34,9 +34,8 @@ def main(private field[2] R, private field S, field[2] A, u32[8] M0, u32[8] M1,
|
|||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
// Check if R is on curve and if it is not in a small subgroup. A is public input and can be checked offline
|
||||
field isOnCurve = onCurve(R, context) // throws if R is not on curve
|
||||
field isPrimeOrder = orderCheck(R, context)
|
||||
1 == isPrimeOrder
|
||||
assert(onCurve(R, context)) // throws if R is not on curve
|
||||
assert(orderCheck(R, context))
|
||||
|
||||
u32[8] Rx = unpack256u(R[0])
|
||||
u32[8] Ax = unpack256u(A[0])
|
||||
|
|
|
@ -6,6 +6,6 @@ def main(field i) -> (bool[128]):
|
|||
|
||||
bool[254] b = unpack(i)
|
||||
|
||||
b[0..126] == [false; 126]
|
||||
assert(b[0..126] == [false; 126])
|
||||
|
||||
return b[126..254]
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,34 +5,34 @@ from "ecc/babyjubjubParams" import BabyJubJubParams
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testDoubleViaAdd() -> (field):
|
||||
def testDoubleViaAdd() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
field[2] out = add(G, G, context)
|
||||
|
||||
out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830
|
||||
out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831
|
||||
assert(out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830)
|
||||
assert(out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def testIdentities() -> (field):
|
||||
def testIdentities() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
field[2] inf = context.INFINITY
|
||||
|
||||
G == add(G, inf, context)
|
||||
assert(G == add(G, inf, context))
|
||||
|
||||
field[2] nG = neg(G)
|
||||
field[2] nGaddG = add(G, nG, context)
|
||||
|
||||
inf == nGaddG
|
||||
assert(inf == nGaddG)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
|
||||
1 == testDoubleViaAdd()
|
||||
1 == testIdentities()
|
||||
assert(testDoubleViaAdd())
|
||||
assert(testIdentities())
|
||||
|
||||
return 1
|
||||
return
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ from "ecc/babyjubjubParams" import BabyJubJubParams
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testCompress() -> (field):
|
||||
def testCompress() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
field Gu = context.Gu
|
||||
|
@ -12,12 +12,12 @@ def testCompress() -> (field):
|
|||
|
||||
bool[256] Gcompressed = edwardsCompress([Gu, Gv])
|
||||
|
||||
Gcompressed == [true, false, true, false, true, true, true, false, false, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, true, true, true, true, true, true, true, true, false, false, false, true, true, false, true, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, true, false, true, true, true, true, false, false, false, false, false, false, true, true, false, false, false, true, true, false, true, true, false, true, true, true, true, false, true, true, true, false, true, true, true, true, true, true, true, false, true, false, false, true, false, false, true, false, false, true, true, false, false, false, false, true, true, false, true, false, true, false, true, false, true, true, false, false, false, false, false, true, true, true, true, true, true, true, false, false, true, true, false, true, false, true, false, false, true, true, true, false, true, false, true, false, false, true, true, true, false, true, true, false, true, false, false, false, false, true, true, false, false, true, false, true, true, false, false, false, false, true, true, false, false, false, false, false, true, true, true, false, true, false, false, false, true, false, false, true, true, false, true, false, false, true, false, false, false, true, true, false, true, true, true, false, true, true, false, false, false, true, true, true, true, false, true, true, true, true, true, true, true, true, false, false, true, true, false, false, true, false, false, false, true, false, true, false, true, false, false, true, false, true, true, false, true, false, true, true, true]
|
||||
assert(Gcompressed == [true, false, true, false, true, true, true, false, false, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, true, true, true, true, true, true, true, true, false, false, false, true, true, false, true, false, false, true, true, true, true, false, false, false, false, true, true, true, true, false, true, false, true, true, true, true, false, false, false, false, false, false, true, true, false, false, false, true, true, false, true, true, false, true, true, true, true, false, true, true, true, false, true, true, true, true, true, true, true, false, true, false, false, true, false, false, true, false, false, true, true, false, false, false, false, true, true, false, true, false, true, false, true, false, true, true, false, false, false, false, false, true, true, true, true, true, true, true, false, false, true, true, false, true, false, true, false, false, true, true, true, false, true, false, true, false, false, true, true, true, false, true, true, false, true, false, false, false, false, true, true, false, false, true, false, true, true, false, false, false, false, true, true, false, false, false, false, false, true, true, true, false, true, false, false, false, true, false, false, true, true, false, true, false, false, true, false, false, false, true, true, false, true, true, true, false, true, true, false, false, false, true, true, true, true, false, true, true, true, true, true, true, true, true, false, false, true, true, false, false, true, false, false, false, true, false, true, false, true, false, false, true, false, true, true, false, true, false, true, true, true])
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
|
||||
1 == testCompress()
|
||||
assert(testCompress())
|
||||
|
||||
return 1
|
||||
return
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,19 +4,19 @@ import "ecc/edwardsOnCurve" as onCurve
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testOnCurveTrue() -> (field):
|
||||
def testOnCurveTrue() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830
|
||||
field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831
|
||||
|
||||
1 == onCurve([testU, testV], context)
|
||||
assert(onCurve([testU, testV], context))
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
|
||||
1 == testOnCurveTrue()
|
||||
assert(testOnCurveTrue())
|
||||
// onCurve throws for false
|
||||
|
||||
return 1
|
||||
return
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,31 +4,31 @@ from "ecc/babyjubjubParams" import BabyJubJubParams
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testOrderCheckTrue() -> (field):
|
||||
def testOrderCheckTrue() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
field testU = 17324563846726889236817837922625232543153115346355010501047597319863650987830
|
||||
field testV = 20022170825455209233733649024450576091402881793145646502279487074566492066831
|
||||
|
||||
field out = orderCheck([testU, testV], context)
|
||||
out == 1
|
||||
bool out = orderCheck([testU, testV], context)
|
||||
assert(out)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def testOrderCheckFalse() -> (field):
|
||||
def testOrderCheckFalse() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
field testU = 4342719913949491028786768530115087822524712248835451589697801404893164183326
|
||||
field testV = 4826523245007015323400664741523384119579596407052839571721035538011798951543
|
||||
|
||||
field out = orderCheck([testU, testV], context)
|
||||
out == 0
|
||||
bool out = orderCheck([testU, testV], context)
|
||||
assert(!out)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
|
||||
1 == testOrderCheckFalse()
|
||||
1 == testOrderCheckTrue()
|
||||
assert(testOrderCheckFalse())
|
||||
assert(testOrderCheckTrue())
|
||||
|
||||
return 1
|
||||
return
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import "ecc/edwardsScalarMult" as mul
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testCyclic() -> (field):
|
||||
def testCyclic() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
|
@ -13,11 +13,11 @@ def testCyclic() -> (field):
|
|||
|
||||
field[2] out = mul(exp, G, context)
|
||||
|
||||
G == out
|
||||
assert(G == out)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def testMul2() -> (field):
|
||||
def testMul2() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
|
@ -25,12 +25,12 @@ def testMul2() -> (field):
|
|||
bool[256] exp = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false]
|
||||
field[2] out = mul(exp, G, context)
|
||||
|
||||
out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830
|
||||
out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831
|
||||
assert(out[0] == 17324563846726889236817837922625232543153115346355010501047597319863650987830)
|
||||
assert(out[1] == 20022170825455209233733649024450576091402881793145646502279487074566492066831)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def testAssociativity() -> (field):
|
||||
def testAssociativity() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
|
@ -55,13 +55,13 @@ def testAssociativity() -> (field):
|
|||
field[2] Gca = mul(a, Gc, context)
|
||||
field[2] Gcab = mul(b, Gca, context)
|
||||
|
||||
Gabc == Gbca
|
||||
Gbca == Gcab
|
||||
Gabc == Gcab
|
||||
assert(Gabc == Gbca)
|
||||
assert(Gbca == Gcab)
|
||||
assert(Gabc == Gcab)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def testMultiplicative() -> (field):
|
||||
def testMultiplicative() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
|
@ -81,16 +81,16 @@ def testMultiplicative() -> (field):
|
|||
|
||||
field[2] Gmab = mul(ab, G, context)
|
||||
|
||||
Gab == Gba
|
||||
Gba == Gmab
|
||||
Gab == Gmab
|
||||
assert(Gab == Gba)
|
||||
assert(Gba == Gmab)
|
||||
assert(Gab == Gmab)
|
||||
|
||||
return 1
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
1 == testMul2()
|
||||
1 == testCyclic()
|
||||
1 == testAssociativity()
|
||||
1 == testMultiplicative()
|
||||
def main() -> ():
|
||||
assert(testMul2())
|
||||
assert(testCyclic())
|
||||
assert(testAssociativity())
|
||||
assert(testMultiplicative())
|
||||
|
||||
return 1
|
||||
return
|
|
@ -8,7 +8,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": ["1"]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import "ecc/edwardsScalarMult" as multiply
|
|||
|
||||
// Code to create test cases:
|
||||
// https://github.com/Zokrates/pycrypto
|
||||
def testOwnershipTrue() -> (field):
|
||||
def testOwnershipTrue() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
field[2] G = [context.Gu, context.Gv]
|
||||
|
||||
|
@ -14,22 +14,22 @@ def testOwnershipTrue() -> (field):
|
|||
|
||||
bool out = proofOfOwnership(Pk, sk, context)
|
||||
|
||||
out == true
|
||||
return 1
|
||||
assert(out)
|
||||
return true
|
||||
|
||||
def testtOwnershipFalse() -> (field):
|
||||
def testtOwnershipFalse() -> (bool):
|
||||
BabyJubJubParams context = context()
|
||||
|
||||
field[2] Pk = [16328093915569409528980874702678312730273137210288183490878184636452430630129, 9377227749598842756429258362864743065769435972445705966557343775367597326529]
|
||||
field sk = 1997011358982923168928344992199991480689546837621580239342656433234255379025
|
||||
bool out = proofOfOwnership(Pk, sk, context)
|
||||
|
||||
out == false
|
||||
return 1
|
||||
assert(!out)
|
||||
return true
|
||||
|
||||
def main() -> (field):
|
||||
def main() -> ():
|
||||
|
||||
1 == testOwnershipTrue()
|
||||
1 == testtOwnershipFalse()
|
||||
assert(testOwnershipTrue())
|
||||
assert(testtOwnershipFalse())
|
||||
|
||||
return 1
|
||||
return
|
|
@ -7,9 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
"1"
|
||||
]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import "hashes/mimc7/mimc7R10"
|
||||
|
||||
def main() -> (field):
|
||||
mimc7R10(0, 0) == 6004544488495356385698286530147974336054653445122716140990101827963729149289
|
||||
mimc7R10(100, 0) == 2977550761518141183167168643824354554080911485709001361112529600968315693145
|
||||
mimc7R10(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 2977550761518141183167168643824354554080911485709001361112529600968315693145
|
||||
mimc7R10(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 11476724043755138071320043459606423473319855817296339514744600646762741571430
|
||||
mimc7R10(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 6004544488495356385698286530147974336054653445122716140990101827963729149289
|
||||
return 1
|
||||
def main() -> ():
|
||||
assert(mimc7R10(0, 0) == 6004544488495356385698286530147974336054653445122716140990101827963729149289)
|
||||
assert(mimc7R10(100, 0) == 2977550761518141183167168643824354554080911485709001361112529600968315693145)
|
||||
assert(mimc7R10(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 2977550761518141183167168643824354554080911485709001361112529600968315693145)
|
||||
assert(mimc7R10(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 11476724043755138071320043459606423473319855817296339514744600646762741571430)
|
||||
assert(mimc7R10(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 6004544488495356385698286530147974336054653445122716140990101827963729149289)
|
||||
return
|
|
@ -7,9 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
"1"
|
||||
]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import "hashes/mimc7/mimc7R20"
|
||||
|
||||
def main() -> (field):
|
||||
mimc7R20(0, 0) == 19139739902058628561064841933381604453445216873412991992755775746150759284829
|
||||
mimc7R20(100, 0) == 8623418512398828792274158979964869393034224267928014534933203776818702139758
|
||||
mimc7R20(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 8623418512398828792274158979964869393034224267928014534933203776818702139758
|
||||
mimc7R20(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 15315177265066649795408805007175121550344555424263995530745989936206840798041
|
||||
mimc7R20(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 19139739902058628561064841933381604453445216873412991992755775746150759284829
|
||||
return 1
|
||||
def main() -> ():
|
||||
assert(mimc7R20(0, 0) == 19139739902058628561064841933381604453445216873412991992755775746150759284829)
|
||||
assert(mimc7R20(100, 0) == 8623418512398828792274158979964869393034224267928014534933203776818702139758)
|
||||
assert(mimc7R20(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 8623418512398828792274158979964869393034224267928014534933203776818702139758)
|
||||
assert(mimc7R20(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 15315177265066649795408805007175121550344555424263995530745989936206840798041)
|
||||
assert(mimc7R20(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 19139739902058628561064841933381604453445216873412991992755775746150759284829)
|
||||
return
|
|
@ -7,9 +7,7 @@
|
|||
},
|
||||
"output": {
|
||||
"Ok": {
|
||||
"values": [
|
||||
"1"
|
||||
]
|
||||
"values": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import "hashes/mimc7/mimc7R50"
|
||||
|
||||
def main() -> (field):
|
||||
mimc7R50(0, 0) == 3049953358280347916081509186284461274525472221619157672645224540758481713173
|
||||
mimc7R50(100, 0) == 18511388995652647480418174218630545482006454713617579894396683237092568946789
|
||||
mimc7R50(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 18511388995652647480418174218630545482006454713617579894396683237092568946789
|
||||
mimc7R50(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 9149577627043020462780389988155990926223727917856424056384664564191878439702
|
||||
mimc7R50(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 3049953358280347916081509186284461274525472221619157672645224540758481713173
|
||||
return 1
|
||||
def main() -> ():
|
||||
assert(mimc7R50(0, 0) == 3049953358280347916081509186284461274525472221619157672645224540758481713173)
|
||||
assert(mimc7R50(100, 0) == 18511388995652647480418174218630545482006454713617579894396683237092568946789)
|
||||
assert(mimc7R50(100, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 18511388995652647480418174218630545482006454713617579894396683237092568946789)
|
||||
assert(mimc7R50(21888242871839275222246405745257275088548364400416034343698204186575808495618, 1) == 9149577627043020462780389988155990926223727917856424056384664564191878439702)
|
||||
assert(mimc7R50(21888242871839275222246405745257275088548364400416034343698204186575808495617, 21888242871839275222246405745257275088548364400416034343698204186575808495617) == 3049953358280347916081509186284461274525472221619157672645224540758481713173)
|
||||
return
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue