diff --git a/scripts/release.sh b/scripts/release.sh index 25a0c6c3..3e260d9c 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -28,6 +28,7 @@ docker push zokrates/zokrates:$TAG echo "Published zokrates/zokrates:$TAG" # Release on Github +git tag latest git tag $TAG git push origin $TAG diff --git a/zokrates_book/src/concepts/operators.md b/zokrates_book/src/concepts/operators.md index 6153893c..990e6e2d 100644 --- a/zokrates_book/src/concepts/operators.md +++ b/zokrates_book/src/concepts/operators.md @@ -4,20 +4,22 @@ The following table lists the precedence and associativity of all available oper | Operator | Description | Associativity | Remarks | |------------------------------|--------------------------------------------------------------|------------------------------------|---------| -| **
| Power | Left | (1) | +| **
| Power | Left | [^1] | | *
/
| Multiplication
Division
| Left
Left | | | +
-
| Addition
Subtraction
| Left
Left | | -| <<
>>
| Left shift
Right shift
| Left
Left | (2) | +| <<
>>
| Left shift
Right shift
| Left
Left | [^2] | | & | Bitwise AND | Left
Left | | | \| | Bitwise OR | Left
Left | | | ^ | Bitwise XOR | Left
Left | | -| >=

>
<=
< | Greater or equal
Greater
Lower or equal
Lower | Left
Left
Left
Left | (3) | +| >=

>
<=
< | Greater or equal
Greater
Lower or equal
Lower | Left
Left
Left
Left | [^3] | | !=
==
| Not Equal
Equal
| Left
Left | | | && | Boolean AND | Left | | | \|\| | Boolean OR | Left | | -1. The exponent must be a compile-time constant -2. The right operand must be a compile time constant -3. Both operands are be asserted to be strictly lower than the biggest power of 2 lower than `p/2` \ No newline at end of file +[^1]: The exponent must be a compile-time constant + +[^2]: The right operand must be a compile time constant + +[^3]: Both operands are be asserted to be strictly lower than the biggest power of 2 lower than `p/2` \ No newline at end of file diff --git a/zokrates_book/src/concepts/stdlib.md b/zokrates_book/src/concepts/stdlib.md index a0e8cd4a..6f154649 100644 --- a/zokrates_book/src/concepts/stdlib.md +++ b/zokrates_book/src/concepts/stdlib.md @@ -1,97 +1,44 @@ ## Standard library -ZoKrates comes with a number of reusable components which are defined at `./stdlib/` in the ZoKrates root repository. In order to import the standard library as described in the [imports](./imports.html) section the `$ZOKRATES_HOME` environment variable needs to be set to the `stdlib` folder. +ZoKrates comes with a number of reusable components in the form of a Standard Library. In order to import it as described in the [imports](./imports.html) section, the `$ZOKRATES_HOME` environment variable must be set to the `stdlib` folder. -The following section highlights a subset of available imports: +The full ZoKrates Standard Library can be found [here](https://github.com/Zokrates/ZoKrates/tree/latest/zokrates_stdlib/stdlib). ### Hashes -#### sha256 +#### Sha256 -```zokrates -import "hashes/sha256/512Padded.zok" -``` +The sha526 hash function comes in a variety of flavours. It can be a good choice when pseudo-randomness, or compatibility with off-circuit systems such as the EVM are required, at the cost of a higher number of constraints. -A function that takes 2 `u32[8]` arrays as inputs and returns their sha256 compression function as a `u32[8]`. +#### Pedersen -#### sha256compression +Pedersen hashing takes advantage of the BabyJubJub embedded elliptic curve on ALT_BN128 to provide a collision-resistant, cheap hash function. One tradeoff is a relatively high cost when computing it inside the EVM. -```zokrates -import "hashes/sha256/512bit.zok" -``` +#### MiMC -A function that takes 2 `u32[8]` arrays as inputs and returns their sha256 compression function as a `u32[8]`. -The difference with `512Padded` is that no padding is added at the end of the message, which makes it more efficient but also less compatible with Solidity. +MiMC is an alternative hash function which comes at a reduced cost and is also relatively cheap inside the EVM. -There also is support for 2-round (1024-bit input) and 3-round (1536-bit input) variants, using `hashes/1024bit.zok` and `hashes/1536bit.zok` respectively. +### Elliptic curve cryptography -#### sha256packed +Thanks to the existence of BabyJubJub, an efficient elliptic curve embedded in ALT_BN128, we provide tools to perform elliptic curve operations such as: -```zokrates -import "hashes/sha256/512bitPacked.zok" -``` +- Point operations +- Proving knowledge of a private EdDSA key +- Proving validity of an EdDSA signature -A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 bits (big-endian), concatenates them and applies sha256. It then returns an array of 2 field elements, each representing 128 bits of the result. +Check out this [python repository](https://github.com/Zokrates/pycrypto) for tooling, for example to generate EdDSA signatures to then check in a SNARK. -### Public-key Cryptography +### Utils -#### Proof of private-key ownership +#### Packing / Unpacking -```zokrates -import "ecc/proofOfOwnership.zok" -``` +As some operations require their input to be provided in the form of bits, we provide tools to convert back and forth between field elements and their bit representations. -Verifies match of a given public/private keypair. Checks if the following equation holds for the provided keypair: -`pk = sk*G` -where `G` is the chosen base point of the subgroup and `*` denotes scalar multiplication in the subgroup. +#### Casts -#### Signature verification +Helpers to convert between types representing binary data. -```zokrates -import "signatures/verifyEddsa.zok" -``` +#### Multiplexer -Verifies an EdDSA Signature. Checks the correctness of a given EdDSA Signature `(R,S)` for the provided public key `A` and message `(M0, M1)`. Check out this [python repository](https://github.com/Zokrates/pycrypto) for tooling to create valid signatures. - -### Packing / Unpacking - -#### pack128 - -```zokrates -import "utils/pack/u32/pack128" -``` - -Packs a `u32[4]` as one field element. - -#### unpack128 - -```zokrates -import "utils/pack/unpack128" -``` - -Unpacks a field element to a `u32[4]`, throwing if it doesn't fit. - -#### pack256 - -```zokrates -import "utils/pack/u32/pack256" -``` - -Packs a `u32[8]` as one field element. Overflows can occur. - -#### nonStrictUnpack256 - -```zokrates -import "utils/pack/u32/nonStrictUnpack256" -``` - -Unpacks a field element to a `u32[4]`. Uniqueness of the output is not guaranteed. - -### Casts - -Different helpers to convert between types. - -```zokrates -import "utils/casts/bool_128_to_u32_4" -``` +Optimised tools to branch inside circuits. diff --git a/zokrates_book/src/concepts/types.md b/zokrates_book/src/concepts/types.md index 31c5f002..93e5c605 100644 --- a/zokrates_book/src/concepts/types.md +++ b/zokrates_book/src/concepts/types.md @@ -8,7 +8,7 @@ ZoKrates currently exposes two primitive types and two complex types: This is the most basic type in ZoKrates, and it represents a positive integer in `[0, p - 1]` where `p` is a (large) prime number. -The prime `p` is set to `21888242871839275222246405745257275088548364400416034343698204186575808495617` as imposed by the pairing curve supported by Ethereum. +As an example, `p` is set to `21888242871839275222246405745257275088548364400416034343698204186575808495617` when working with the [ALT_BN128](/reference/proving_schemes.html#alt_bn128) curve supported by Ethereum. While `field` values mostly behave like unsigned integers, one should keep in mind that they overflow at `p` and not some power of 2, so that we have: @@ -26,11 +26,11 @@ Unsigned integers enable implementing programs which rely bit strings, such as h ## Complex Types -ZoKrates provides two complex types, Arrays and Structs. +ZoKrates provides two complex types: arrays and structs. ### Arrays -ZoKrates supports static arrays, i.e., their length needs to be known at compile time. +ZoKrates supports static arrays, i.e., whose length needs to be known at compile time. Arrays can contain elements of any type and have arbitrary dimensions. The following example code shows examples of how to use arrays: diff --git a/zokrates_cli/examples/book/hashexample.zok b/zokrates_cli/examples/book/hashexample.zok index 510f45e2..24f1e824 100644 --- a/zokrates_cli/examples/book/hashexample.zok +++ b/zokrates_cli/examples/book/hashexample.zok @@ -1,4 +1,4 @@ -from "hashes/sha256/512bitPacked" import main +import "hashes/sha256/512bitPacked" as sha256packed def main(private field a, private field b, private field c, private field d) -> (field[2]): field[2] h = sha256packed([a, b, c, d]) diff --git a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok index 355eebce..c6953b0d 100644 --- a/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok +++ b/zokrates_cli/examples/merkleTree/pedersenPathProof3.zok @@ -4,8 +4,11 @@ import "ecc/babyjubjubParams" as context from "ecc/babyjubjubParams" import BabyJubJubParams import "hashes/utils/256bitsDirectionHelper" as multiplex +def multiplex(bool selector, u32[8] left, u32[8] right) -> (u32[8]): + return if selector then right else left fi + // 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 +// directionSelector=> true if current digest is on the rhs of the hash def main(u32[8] rootDigest, private u32[8] leafDigest, private bool[3] directionSelector, u32[8] PathDigest0, private u32[8] PathDigest1, private u32[8] PathDigest2) -> (): BabyJubJubParams context = context() diff --git a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok index 1757ad7a..ae24269a 100644 --- a/zokrates_cli/examples/merkleTree/sha256PathProof3.zok +++ b/zokrates_cli/examples/merkleTree/sha256PathProof3.zok @@ -1,5 +1,7 @@ import "hashes/sha256/512bit" as sha256 -import "utils/multiplexer/256bit" as multiplex + +def multiplex(bool selector, u32[8] left, u32[8] right) -> (u32[8]): + return if selector then right else left fi // Merkle-Tree inclusion proof for tree depth 3 diff --git a/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok b/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok deleted file mode 100644 index 74d9e138..00000000 --- a/zokrates_stdlib/stdlib/hashes/pedersen/6bit.zok +++ /dev/null @@ -1,21 +0,0 @@ -import "utils/multiplexer/lookup3bitSigned" as sel3s -import "utils/multiplexer/lookup2bit" as sel2 -import "ecc/babyjubjubParams" as context -from "ecc/babyjubjubParams" import BabyJubJubParams -import "ecc/edwardsAdd" as add - -def main(bool[6] e) -> (field[2]): - BabyJubJubParams context = context() - - field[2] a = context.INFINITY //Infinity - - //Round 0 - field cx = sel3s([e[0], e[1], e[2]], [13418723823902222986275588345615650707197303761863176429873001977640541977977 , 8366451672790208592553809639953117385619257483837439526516290319251622927412, 1785026334726838136757054176272745265857971873904476677125553010508875025629, 15763987975760561753692294837740043971877392788040801334205375164715487005236]) - field cy = sel2([e[0], e[1]], [15255921313433251341520743036334816584226787412845488772781699434149539664639 , 10916775373885716961512013142444429405184550001421868906213743991404593770484, 18533662942827602783563125901366807026309605479742251601915445402562880550265, 12754584346112149619040942896930712185968371085994381911052593922432846916845]) - a = add(a, [cx, cy], context) - //Round 1 - cx = sel3s([e[3], e[4], e[5]], [10096735692467598736728394557736034054031417419721869067082824451240861468728 , 6979151010236415881632946866847657030447196774231162748523315765559549846746, 12137947022495312670974525048647679757468392619153927921382150023166867027471, 10624360821702266736197468438435445939719745367234393212061381062942588576905]) - cy = sel2([e[3], e[4]], [16704592219657141368520262522286248296157931669321735564513068002743507745908 , 11518684165372839249156788740134693928233608013641661856685773776747280808438, 21502372109496595498116676984635248026663470429940273577484250291841812814697, 17522620677401472201433112250371604936150385414760411280739362011041111141253]) - a = add(a, [cx, cy], context) - - return a \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok index db57847c..502c31a5 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1024bit.zok @@ -1,8 +1,10 @@ import "./IVconstants" as IVconstants import "./shaRound" as sha256 -// A function that takes 4 bool[256] arrays as inputs -// and applies 2 rounds of sha256 compression. +// A function that takes 4 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied + def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d) -> (u32[8]): u32[8] IV = IVconstants() diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok index e4f40a9b..c336e389 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1024bitPadded.zok @@ -1,6 +1,7 @@ import "./1536bit" as sha256 -// Take two bool[256] arrays as input -// and returns their sha256 full round output as an array of 256 bool. + +// A function that takes four u32[8] array as input, concatenates them, pads the result, +// and returns the sha256 output as a u32[8] def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d) -> (u32[8]): // Hash is computed on the full 1024bit block size diff --git a/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok index c303944e..3e53f9fc 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/1536bit.zok @@ -1,9 +1,10 @@ import "./IVconstants" as IVconstants import "./shaRound" as sha256 -// A function that takes 6 u32[8] arrays as inputs -// and applies 3 rounds of sha256 compression. -// It returns an array of 256 bool. +// A function that takes 6 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied + def main(u32[8] a, u32[8] b, u32[8] c, u32[8] d, u32[8] e, u32[8] f) -> (u32[8]): u32[8] IV = IVconstants() diff --git a/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok index af4faca5..e0b1a5c7 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/256bitPadded.zok @@ -1,7 +1,7 @@ import "./512bit" as sha256 -// A function that takes 1 bool[256] array as input -// and returns the sha256 full round output as an array of 256 bool. +// A function that takes a u32[8] array as input, pads it, +// and returns the sha256 output as a u32[8] def main(u32[8] a) -> (u32[8]): // Hash is computed on 256 bits of input diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok index 4202ecac..a0b3f63e 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bit.zok @@ -1,8 +1,9 @@ import "./IVconstants" as IVconstants import "./shaRound" as sha256 -// A function that takes 2 u32[8] arrays as inputs -// and returns their sha256 compression function as an array of 8 u32. +// A function that takes 2 u32[8] arrays as inputs, concatenates them, +// and returns their sha256 compression as a u32[8]. +// Note: no padding is applied def main(u32[8] a, u32[8] b) -> (u32[8]): diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok index 8c5f9107..049ddf5f 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bitPacked.zok @@ -1,7 +1,7 @@ import "../../utils/pack/u32/pack128" as pack128 import "../../utils/pack/u32/unpack128" as unpack128 import "./512bitPadded" as sha256 -// A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 +// A function that takes an array of 4 field elements as input, unpacks each of them to 128 // bits (big endian), concatenates them and applies sha256. // It then returns an array of two field elements, each representing 128 bits of the result. def main(field[4] preimage) -> (field[2]): diff --git a/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok index 00f6798d..33b59bb1 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/512bitPadded.zok @@ -1,7 +1,7 @@ import "./1024bit" as sha256 -// A function that takes 2 bool[256] arrays as inputs -// and returns their sha256 full round output as an array of 256 bool. +// A function that takes 2 u32[8] arrays as inputs, concatenates them, pads them, +// and returns their sha256 hash as a u32[8] def main(u32[8] a, u32[8] b) -> (u32[8]): // Hash is computed on the full 512bit block size diff --git a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok index aa1c1d23..2cdf2cef 100644 --- a/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok +++ b/zokrates_stdlib/stdlib/hashes/sha256/shaRound.zok @@ -67,6 +67,8 @@ def temp2(u32 a, u32 b, u32 c) -> (u32): // temp2 := S0 + maj return S0 + maj +// A function that computes one round of the SHA256 compression function given an input and the current value of the hash +// this is used by other components however many times needed def main(u32[16] input, u32[8] current) -> (u32[8]): u32 h0 = current[0] diff --git a/zokrates_stdlib/stdlib/hashes/utils/256bitsDirectionHelper.zok b/zokrates_stdlib/stdlib/hashes/utils/256bitsDirectionHelper.zok index 18e6050c..8b2db310 100644 --- a/zokrates_stdlib/stdlib/hashes/utils/256bitsDirectionHelper.zok +++ b/zokrates_stdlib/stdlib/hashes/utils/256bitsDirectionHelper.zok @@ -1,2 +1,3 @@ +// Concatenate two u32[8] arrays in an order defined by a boolean selector def main(bool selector, u32[8] lhs, u32[8] rhs) -> (u32[16]): return if selector then [...rhs, ...lhs] else [...lhs, ...rhs] fi \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok b/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok index 8f6d40c1..1aa332e4 100644 --- a/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok +++ b/zokrates_stdlib/stdlib/utils/casts/1024to256array.zok @@ -1,3 +1,2 @@ def main(bool[1024] input) -> (bool[256], bool[256], bool[256], bool[256]): - return input[0..256], input[256..512], input[512..768], input[768..1024] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/256bit.zok b/zokrates_stdlib/stdlib/utils/multiplexer/256bit.zok deleted file mode 100644 index c3d111c4..00000000 --- a/zokrates_stdlib/stdlib/utils/multiplexer/256bit.zok +++ /dev/null @@ -1,2 +0,0 @@ -def main(bool selector, u32[8] lhs, u32[8] rhs) -> (u32[8]): - return if selector then rhs else lhs fi \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/2bit.zok b/zokrates_stdlib/stdlib/utils/multiplexer/2bit.zok deleted file mode 100644 index 3b910b6b..00000000 --- a/zokrates_stdlib/stdlib/utils/multiplexer/2bit.zok +++ /dev/null @@ -1,2 +0,0 @@ -def main(bool selector, bool[2] lhs, bool[2] rhs) -> (bool[2]): - return if selector then rhs else lhs fi \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/lookup1bit.zok b/zokrates_stdlib/stdlib/utils/multiplexer/lookup1bit.zok index 00abfc69..67b68cf2 100644 --- a/zokrates_stdlib/stdlib/utils/multiplexer/lookup1bit.zok +++ b/zokrates_stdlib/stdlib/utils/multiplexer/lookup1bit.zok @@ -1,6 +1,4 @@ -// /** -// * One-bit window lookup table using one constraint -// */ +// One-bit window lookup table using one constraint def main(bool selector, field[2] target) -> (field): field out = if selector then target[1] else target[0] fi diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/lookup2bit.zok b/zokrates_stdlib/stdlib/utils/multiplexer/lookup2bit.zok index fcfc2b16..4713d7dd 100644 --- a/zokrates_stdlib/stdlib/utils/multiplexer/lookup2bit.zok +++ b/zokrates_stdlib/stdlib/utils/multiplexer/lookup2bit.zok @@ -1,7 +1,5 @@ -// /** -// * Two-bit window lookup table using one constraint -// * Maps the bits `b` to a list of constant `c` -// */ +// Two-bit window lookup table using one constraint +// Maps the bits `b` to a list of field elements `c` def main(bool[2] b, field[4] c) -> (field): field alpha = c[1] - c[0] + if b[1] then (c[3] - c[2] - c[1] + c[0]) else 0 fi diff --git a/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok b/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok index db4c3bd6..f6e8cc4b 100644 --- a/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok +++ b/zokrates_stdlib/stdlib/utils/multiplexer/lookup3bitSigned.zok @@ -1,8 +1,6 @@ import "./lookup2bit" as lookup -// /** -// * Three-bit window lookup (2bits + signature bit) in 2bit table -// * using two constraints. Maps the bits `b` to a list of constants `c` -// */ +// Three-bit window lookup (2bits + signature bit) in 2bit table +// using two constraints. Maps the bits `b` to a list of constants `c` def main(bool[3] b, field[4] c) -> (field): field alpha = lookup([b[0], b[1]], c) diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok b/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok index 31942bee..da139dcb 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/nonStrictUnpack256.zok @@ -1,11 +1,10 @@ #pragma curve bn128 -// Non-strict version: -// Note that this does not strongly enforce that the commitment is -// in the field. - import "EMBED/unpack" as unpack +// Unpack a field element as 256 big-endian bits +// Note: uniqueness of the output is not guaranteed +// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)` def main(field i) -> (bool[256]): bool[254] b = unpack(i) diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok b/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok index 2fd8f956..93a05d6c 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/pack128.zok @@ -1,5 +1,6 @@ #pragma curve bn128 +// pack 128 big-endian bits into one field element def main(bool[128] bits) -> (field): field out = 0 diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/pack256.zok b/zokrates_stdlib/stdlib/utils/pack/bool/pack256.zok index b5016aa1..1c76c7ff 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/pack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/pack256.zok @@ -1,5 +1,8 @@ #pragma curve bn128 +// pack 256 big-endian bits into one field element +// Note: This is not a injective operation as `p` is smaller than `2**256 - 1` for bn128 +// For example, `[0, 0,..., 0]` and `bits(p)` both point to `0` def main(bool[256] input) -> (field): field out = 0 diff --git a/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok b/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok index 6a7eb5b4..1d950a40 100644 --- a/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/bool/unpack128.zok @@ -2,6 +2,8 @@ import "EMBED/unpack" as unpack +// Unpack a field element as 128 big-endian bits +// Precondition: the input is smaller or equal to `2**128 - 1` def main(field i) -> (bool[128]): bool[254] b = unpack(i) diff --git a/zokrates_stdlib/stdlib/utils/pack/u32/nonStrictUnpack256.zok b/zokrates_stdlib/stdlib/utils/pack/u32/nonStrictUnpack256.zok index c2832467..a38a80da 100644 --- a/zokrates_stdlib/stdlib/utils/pack/u32/nonStrictUnpack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/u32/nonStrictUnpack256.zok @@ -1,12 +1,11 @@ #pragma curve bn128 -// Non-strict version: -// Note that this does not strongly enforce that the commitment is -// in the field. - import "../bool/nonStrictUnpack256" as unpack import "../../casts/bool_256_to_u32_8" as from_bits +// Unpack a field element as a u32[8] (big-endian) +// Note: uniqueness of the output is not guaranteed +// For example, `0` can map to `[0, 0, ..., 0]` or to `bits(p)` def main(field i) -> (u32[8]): return from_bits(unpack(i)) \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/utils/pack/u32/pack128.zok b/zokrates_stdlib/stdlib/utils/pack/u32/pack128.zok index e2d000d4..2de7c0dd 100644 --- a/zokrates_stdlib/stdlib/utils/pack/u32/pack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/u32/pack128.zok @@ -3,6 +3,7 @@ import "EMBED/u32_to_bits" as to_bits import "../bool/pack128" +// pack 128 big-endian bits into one field element def main(u32[4] input) -> (field): bool[128] bits = [...to_bits(input[0]), ...to_bits(input[1]), ...to_bits(input[2]), ...to_bits(input[3])] diff --git a/zokrates_stdlib/stdlib/utils/pack/u32/pack256.zok b/zokrates_stdlib/stdlib/utils/pack/u32/pack256.zok index 17daa427..36d12a69 100644 --- a/zokrates_stdlib/stdlib/utils/pack/u32/pack256.zok +++ b/zokrates_stdlib/stdlib/utils/pack/u32/pack256.zok @@ -3,6 +3,9 @@ import "EMBED/u32_to_bits" as to_bits import "../bool/pack256" +// pack 256 big-endian bits into one field element +// Note: This is not a injective operation as `p` is smaller than `2**256 - 1 for bn128 +// For example, `[0, 0,..., 0]` and `bits(p)` both point to `0` def main(u32[8] input) -> (field): bool[256] bits = [...to_bits(input[0]), ...to_bits(input[1]), ...to_bits(input[2]), ...to_bits(input[3]), ...to_bits(input[4]), ...to_bits(input[5]), ...to_bits(input[6]), ...to_bits(input[7])] diff --git a/zokrates_stdlib/stdlib/utils/pack/u32/unpack128.zok b/zokrates_stdlib/stdlib/utils/pack/u32/unpack128.zok index 2c09ca81..90bddcd9 100644 --- a/zokrates_stdlib/stdlib/utils/pack/u32/unpack128.zok +++ b/zokrates_stdlib/stdlib/utils/pack/u32/unpack128.zok @@ -3,5 +3,7 @@ import "../bool/unpack128" as unpack import "../../casts/bool_128_to_u32_4" as from_bits +// Unpack a field element as 128 big-endian bits +// Precondition: the input is smaller or equal to `2**128 - 1` def main(field i) -> (u32[4]): return from_bits(unpack(i)) \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.json b/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.json deleted file mode 100644 index 9d170267..00000000 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "entry_point": "./tests/tests/hashes/pedersen/6bit.zok", - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [] - }, - "output": { - "Ok": { - "values": [] - } - } - } - ] -} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok b/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok deleted file mode 100644 index 80413fa2..00000000 --- a/zokrates_stdlib/tests/tests/hashes/pedersen/6bit.zok +++ /dev/null @@ -1,19 +0,0 @@ -//Python code used to create test vector: -// -// from zokrates.gadgets.pedersenHasher import PedersenHasher -// import bitstring -// hasher = PedersenHasher("test", 2) -// bs = bitstring.BitArray('0b110000') -// hasher.hash_bits(bs) - -import "hashes/pedersen/6bit" as pedersen - -def main() -> (): - - bool[6] e = [true, true, false, false, false, false] - field[2] d = pedersen(e) - - assert(5483803361072598088157572477433311028290255512997784196805059543720485966024 == d[0]) - assert(8712718144085345152615259409576985937188455136179509057889474614313734076278 == d[1]) - - return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.json b/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.json deleted file mode 100644 index 420e1c27..00000000 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "entry_point": "./tests/tests/utils/multiplexer/256bit.zok", - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [] - }, - "output": { - "Ok": { - "values": [] - } - } - } - ] -} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok deleted file mode 100644 index 0c41d0ca..00000000 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/256bit.zok +++ /dev/null @@ -1,32 +0,0 @@ -import "utils/multiplexer/256bit" as multiplex - -def left() -> (bool): - bool bit = false //left - - u32[8] a = [0x1b19dea8, 0xba4e3c16, 0x43eb67a4, 0x2667fd3c, 0xc50a189f, 0x54977e2f, 0x8ab0beee, 0x332b2a38] - - u32[8] b = [0x03f3f628, 0xe067520d, 0x9a36f714, 0xa5ba86cd, 0x2dbcae1d, 0x37e034b3, 0x84786de3, 0xedb8b557] - - u32[8] output = [0x1b19dea8, 0xba4e3c16, 0x43eb67a4, 0x2667fd3c, 0xc50a189f, 0x54977e2f, 0x8ab0beee, 0x332b2a38] - assert(output == multiplex(bit, a, b)) - - return true - -def right() -> (bool): - bool bit = true //right - - u32[8] a = [0x1b19dea8, 0xba4e3c16, 0x43eb67a4, 0x2667fd3c, 0xc50a189f, 0x54977e2f, 0x8ab0beee, 0x332b2a38] - - u32[8] b = [0x03f3f628, 0xe067520d, 0x9a36f714, 0xa5ba86cd, 0x2dbcae1d, 0x37e034b3, 0x84786de3, 0xedb8b557] - - u32[8] output = [0x03f3f628, 0xe067520d, 0x9a36f714, 0xa5ba86cd, 0x2dbcae1d, 0x37e034b3, 0x84786de3, 0xedb8b557] - assert(output == multiplex(bit, a, b)) - - return true - -def main() -> (): - - assert(left()) - assert(right()) - - return \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.json b/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.json deleted file mode 100644 index 750472d6..00000000 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "entry_point": "./tests/tests/utils/multiplexer/2bit.zok", - "curves": ["Bn128"], - "tests": [ - { - "input": { - "values": [] - }, - "output": { - "Ok": { - "values": [] - } - } - } - ] -} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok b/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok deleted file mode 100644 index 2e7b1907..00000000 --- a/zokrates_stdlib/tests/tests/utils/multiplexer/2bit.zok +++ /dev/null @@ -1,28 +0,0 @@ -import "utils/multiplexer/2bit" as multiplex - -def left() -> (bool): - bool bit = false //left - bool[2] a = [false, true] - bool[2] b = [true, false] - - bool[2] output = [false, true] - assert(output == multiplex(bit, a, b)) - - return true - -def right() -> (bool): - bool bit = true //right - bool[2] a = [false, true] - bool[2] b = [true, false] - - bool[2] output = [true, false] - assert(output == multiplex(bit, a, b)) - - return true - -def main() -> (): - - assert(left()) - assert(right()) - - return \ No newline at end of file