Merge branch 'develop' into display-empty-lincomb
This commit is contained in:
commit
02157bf312
16 changed files with 254 additions and 49 deletions
|
@ -2,6 +2,33 @@ version: 2
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
docker:
|
||||||
|
- image: rustlang/rust:nightly-slim
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Version information
|
||||||
|
command: rustc --version; cargo --version; rustup --version
|
||||||
|
- run:
|
||||||
|
name: Calculate dependencies
|
||||||
|
command: cargo generate-lockfile
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- run:
|
||||||
|
name: Build libsnark
|
||||||
|
command: LIBSNARK_SOURCE_PATH=$HOME/libsnark ./build_libsnark.sh
|
||||||
|
- run:
|
||||||
|
name: Build
|
||||||
|
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" ./build.sh
|
||||||
|
- save_cache:
|
||||||
|
paths:
|
||||||
|
- /usr/local/cargo/registry
|
||||||
|
- target/debug/.fingerprint
|
||||||
|
- target/debug/build
|
||||||
|
- target/debug/deps
|
||||||
|
key: v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
test:
|
||||||
docker:
|
docker:
|
||||||
- image: rustlang/rust:nightly-slim
|
- image: rustlang/rust:nightly-slim
|
||||||
steps:
|
steps:
|
||||||
|
@ -18,9 +45,6 @@ jobs:
|
||||||
- run:
|
- run:
|
||||||
name: Check format
|
name: Check format
|
||||||
command: rustup component add rustfmt-preview; cargo fmt --all -- --check
|
command: rustup component add rustfmt-preview; cargo fmt --all -- --check
|
||||||
# - run:
|
|
||||||
# name: Download wasm32 target
|
|
||||||
# command: rustup target add wasm32-unknown-unknown
|
|
||||||
- run:
|
- run:
|
||||||
name: Build libsnark
|
name: Build libsnark
|
||||||
command: LIBSNARK_SOURCE_PATH=$HOME/libsnark ./build_libsnark.sh
|
command: LIBSNARK_SOURCE_PATH=$HOME/libsnark ./build_libsnark.sh
|
||||||
|
@ -30,22 +54,76 @@ jobs:
|
||||||
- run:
|
- run:
|
||||||
name: Run tests
|
name: Run tests
|
||||||
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --test-threads=1
|
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --test-threads=1
|
||||||
# - run:
|
|
||||||
# name: Run tests with WASM enabled
|
|
||||||
# command: cd zokrates_core && cargo test --release --features wasm -- --test-threads=1
|
|
||||||
- run:
|
|
||||||
name: Run integration tests
|
|
||||||
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --ignored
|
|
||||||
- run:
|
- run:
|
||||||
name: Generate code coverage report
|
name: Generate code coverage report
|
||||||
command: ./scripts/cov.sh
|
command: ./scripts/cov.sh
|
||||||
|
wasm_test:
|
||||||
|
docker:
|
||||||
|
- image: rustlang/rust:nightly-slim
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
- run:
|
- run:
|
||||||
name: Publish book
|
name: Version information
|
||||||
command: ./scripts/publish_book.sh
|
command: rustc --version; cargo --version; rustup --version
|
||||||
- save_cache:
|
- run:
|
||||||
paths:
|
name: Calculate dependencies
|
||||||
- /usr/local/cargo/registry
|
command: cargo generate-lockfile
|
||||||
- target/debug/.fingerprint
|
- restore_cache:
|
||||||
- target/debug/build
|
keys:
|
||||||
- target/debug/deps
|
- v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
key: v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
|
- run:
|
||||||
|
name: Download wasm32 target
|
||||||
|
command: rustup target add wasm32-unknown-unknown
|
||||||
|
- run:
|
||||||
|
name: Run tests with WASM enabled
|
||||||
|
command: cd zokrates_core && cargo test --release --features wasm -- --test-threads=1
|
||||||
|
integration_test:
|
||||||
|
docker:
|
||||||
|
- image: rustlang/rust:nightly-slim
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Version information
|
||||||
|
command: rustc --version; cargo --version; rustup --version
|
||||||
|
- run:
|
||||||
|
name: Calculate dependencies
|
||||||
|
command: cargo generate-lockfile
|
||||||
|
- restore_cache:
|
||||||
|
keys:
|
||||||
|
- v4-cargo-cache-{{ arch }}-{{ checksum "Cargo.lock" }}
|
||||||
|
- run:
|
||||||
|
name: Build libsnark
|
||||||
|
command: LIBSNARK_SOURCE_PATH=$HOME/libsnark ./build_libsnark.sh
|
||||||
|
- run:
|
||||||
|
name: Run integration tests
|
||||||
|
command: WITH_LIBSNARK=1 LIBSNARK_SOURCE_PATH=$HOME/libsnark RUSTFLAGS="-D warnings" cargo test --release -- --ignored
|
||||||
|
deploy:
|
||||||
|
docker:
|
||||||
|
- image: circleci/python
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- setup_remote_docker:
|
||||||
|
docker_layer_caching: true
|
||||||
|
- run:
|
||||||
|
name: Release
|
||||||
|
command: ./scripts/release.sh
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
build-test-and-deploy:
|
||||||
|
jobs:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- wasm_test
|
||||||
|
- integration_test
|
||||||
|
- deploy:
|
||||||
|
filters:
|
||||||
|
branches:
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
requires:
|
||||||
|
- build
|
||||||
|
- test
|
||||||
|
- integration_test
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
# Exit if any subcommand fails
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ "$CIRCLE_BRANCH" == "master" ]; then
|
|
||||||
apt-get update
|
|
||||||
apt-get -qq install git python-minimal
|
|
||||||
python --version
|
|
||||||
cargo install mdbook
|
|
||||||
cd zokrates_book && mdbook build
|
|
||||||
git config --global user.email "stefan.deml+zokratesbot@decentriq.ch"
|
|
||||||
git clone https://github.com/Zokrates/zokrates.github.io.git
|
|
||||||
git clone https://github.com/davisp/ghp-import.git
|
|
||||||
cd zokrates.github.io
|
|
||||||
TAG=$(cat ../zokrates_cli/Cargo.toml | grep '^version' | awk '{print $3}' | sed -e 's/"//g') && echo $TAG
|
|
||||||
../ghp-import/ghp_import.py -n -p -f -m "Documentation upload. Version: $TAG" -b "master" -r https://zokratesbot:"$GH_TOKEN"@github.com/Zokrates/zokrates.github.io.git ../book
|
|
||||||
echo "Published book"
|
|
||||||
fi
|
|
||||||
|
|
49
scripts/release.sh
Executable file
49
scripts/release.sh
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
# Exit if any subcommand fails
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Get tag
|
||||||
|
TAG=$(cat ./zokrates_cli/Cargo.toml | grep '^version' | awk '{print $3}' | sed -e 's/"//g') && echo $TAG
|
||||||
|
|
||||||
|
# Use zokrates github bot
|
||||||
|
git config --global user.email $GH_USER
|
||||||
|
|
||||||
|
# Release on Dockerhub
|
||||||
|
|
||||||
|
## Build
|
||||||
|
docker build -t zokrates .
|
||||||
|
|
||||||
|
## Log into Dockerhub
|
||||||
|
echo $DOCKERHUB_PASS | docker login -u $DOCKERHUB_USER --password-stdin
|
||||||
|
|
||||||
|
## Release under `latest` tag
|
||||||
|
docker tag zokrates:latest zokrates/zokrates:latest
|
||||||
|
docker push zokrates/zokrates:latest
|
||||||
|
echo "Published zokrates/zokrates:latest"
|
||||||
|
|
||||||
|
## Release under $TAG tag
|
||||||
|
docker tag zokrates:latest zokrates/zokrates:$TAG
|
||||||
|
docker push zokrates/zokrates:$TAG
|
||||||
|
echo "Published zokrates/zokrates:$TAG"
|
||||||
|
|
||||||
|
# Release on Github
|
||||||
|
git tag $TAG
|
||||||
|
git push origin $TAG
|
||||||
|
|
||||||
|
# Publish book
|
||||||
|
MDBOOK_TAR="https://github.com/rust-lang-nursery/mdBook/releases/download/v0.2.1/mdbook-v0.2.1-x86_64-unknown-linux-gnu.tar.gz"
|
||||||
|
|
||||||
|
cd zokrates_book
|
||||||
|
|
||||||
|
## Install mdbook
|
||||||
|
wget -qO- $MDBOOK_TAR | tar xvz
|
||||||
|
|
||||||
|
## Build book
|
||||||
|
./mdbook build
|
||||||
|
|
||||||
|
## Deploy to github.io
|
||||||
|
git clone https://github.com/Zokrates/zokrates.github.io.git
|
||||||
|
git clone https://github.com/davisp/ghp-import.git
|
||||||
|
cd zokrates.github.io
|
||||||
|
../ghp-import/ghp_import.py -n -p -f -m "Documentation upload. Version: $TAG" -b "master" -r https://zokratesbot:"$GH_TOKEN"@github.com/Zokrates/zokrates.github.io.git ../book
|
||||||
|
echo "Published book"
|
||||||
|
|
0
shadow.code
Normal file
0
shadow.code
Normal file
|
@ -1,9 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "zokrates_wasm_plugin"
|
|
||||||
version = "0.1.0"
|
|
||||||
authors = ["Guillaume Ballet <gballet@gmail.com>"]
|
|
||||||
edition = "2018"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
parity-wasm = "0.35.3"
|
|
||||||
clap = "2.32.0"
|
|
|
@ -16,5 +16,6 @@
|
||||||
- [CLI](reference/cli.md)
|
- [CLI](reference/cli.md)
|
||||||
- [Backends](reference/backends.md)
|
- [Backends](reference/backends.md)
|
||||||
- [Verification](reference/verification.md)
|
- [Verification](reference/verification.md)
|
||||||
|
- [ZIR](reference/ir.md)
|
||||||
|
|
||||||
- [Tutorial: Proof of preimage](./sha256example.md)
|
- [Tutorial: Proof of preimage](./sha256example.md)
|
||||||
|
|
|
@ -1,4 +1,26 @@
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
Variables can have any name which does not start with a number. Underscores are not allowed in variable names.
|
Variables can have any name which does not start with a number. Underscores are not allowed in variable names.
|
||||||
Variables are mutable, and always passed by values to functions.
|
Variables are mutable, and always passed by value to functions.
|
||||||
|
|
||||||
|
### Shadowing
|
||||||
|
|
||||||
|
Shadowing is not allowed.
|
||||||
|
```zokrates
|
||||||
|
{{#include ../../../zokrates_cli/examples/book/no_shadowing.code}}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scope
|
||||||
|
|
||||||
|
#### Function
|
||||||
|
|
||||||
|
Functions have their own scope
|
||||||
|
```zokrates
|
||||||
|
{{#include ../../../zokrates_cli/examples/book/function_scope.code}}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### For-loop
|
||||||
|
For-loops have their own scope
|
||||||
|
```zokrates
|
||||||
|
{{#include ../../../zokrates_cli/examples/book/for_scope.code}}
|
||||||
|
```
|
|
@ -6,3 +6,4 @@ The reference covers the details of various areas of ZoKrates.
|
||||||
- [CLI](cli.md)
|
- [CLI](cli.md)
|
||||||
- [Backends](backends.md)
|
- [Backends](backends.md)
|
||||||
- [Verification](verification.md)
|
- [Verification](verification.md)
|
||||||
|
- [ZIR](ir.md)
|
||||||
|
|
19
zokrates_book/src/reference/ir.md
Normal file
19
zokrates_book/src/reference/ir.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# ZIR
|
||||||
|
|
||||||
|
ZIR is the intermediate representation ZoKrates uses to represent programs. It is close to R1CS but still encapsulates witness generation.
|
||||||
|
|
||||||
|
**Note that ZIR is still in development and can change without notice.**
|
||||||
|
|
||||||
|
When generating R1CS constraints, very large numbers are often used, which can make reading ZIR hard for humans.
|
||||||
|
To mitigate this, ZIR applies an isomorphism when displaying field elements: they are shown as members of the interval `[- (p - 1)/2, (p - 1)/2]`. In other words, the following mapping is used:
|
||||||
|
- elements in `[0, (p - 1)/2]` map to themselves
|
||||||
|
- elements in `[(p + 1)/2, p - 1]` map to themselves minus `p`
|
||||||
|
|
||||||
|
Therefore, instead of writing `p - 1` as:
|
||||||
|
```
|
||||||
|
21888242871839275222246405745257275088548364400416034343698204186575808495616
|
||||||
|
```
|
||||||
|
... in ZIR, we simply write:
|
||||||
|
```
|
||||||
|
-1
|
||||||
|
```
|
7
zokrates_cli/examples/book/for_scope.code
Normal file
7
zokrates_cli/examples/book/for_scope.code
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
def main() -> (field):
|
||||||
|
field a = 0
|
||||||
|
for field i in 0..5 do
|
||||||
|
a = a + i
|
||||||
|
endfor
|
||||||
|
// return i <- not allowed
|
||||||
|
return a
|
7
zokrates_cli/examples/book/function_scope.code
Normal file
7
zokrates_cli/examples/book/function_scope.code
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
def foo() -> (field):
|
||||||
|
// return myGlobal <- not allowed
|
||||||
|
return 42
|
||||||
|
|
||||||
|
def main() -> (field):
|
||||||
|
field myGlobal = 42
|
||||||
|
return foo()
|
7
zokrates_cli/examples/book/no_shadowing.code
Normal file
7
zokrates_cli/examples/book/no_shadowing.code
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
def main() -> (field):
|
||||||
|
field a = 2
|
||||||
|
// field a = 3 <- not allowed
|
||||||
|
for field i in 0..5 do
|
||||||
|
// field a = 7 <- not allowed
|
||||||
|
endfor
|
||||||
|
return a
|
4
zokrates_cli/examples/error/out_of_for_scope.code
Normal file
4
zokrates_cli/examples/error/out_of_for_scope.code
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
def main() -> (field):
|
||||||
|
for field i in 0..5 do
|
||||||
|
endfor
|
||||||
|
return i
|
|
@ -2,6 +2,6 @@ def foo() -> (field):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
def main() -> (field):
|
def main() -> (field):
|
||||||
bool a
|
field a = 2
|
||||||
field a = foo()
|
field a = foo()
|
||||||
return 1
|
return 1
|
|
@ -59,7 +59,7 @@ impl<T: Field> fmt::Display for LinComb<T> {
|
||||||
"{}",
|
"{}",
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(k, v)| format!("{} * {}", v, k))
|
.map(|(k, v)| format!("{} * {}", v.to_compact_dec_string(), k))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" + ")
|
.join(" + ")
|
||||||
),
|
),
|
||||||
|
|
|
@ -71,6 +71,9 @@ pub trait Field:
|
||||||
fn get_required_bits() -> usize;
|
fn get_required_bits() -> usize;
|
||||||
/// Tries to parse a string into this representation
|
/// Tries to parse a string into this representation
|
||||||
fn try_from_str<'a>(s: &'a str) -> Result<Self, ()>;
|
fn try_from_str<'a>(s: &'a str) -> Result<Self, ()>;
|
||||||
|
/// Returns a decimal string representing a the member of the equivalence class of this `Field` in Z/pZ
|
||||||
|
/// which lies in [-(p-1)/2, (p-1)/2]
|
||||||
|
fn to_compact_dec_string(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Serialize, Deserialize)]
|
#[derive(PartialEq, PartialOrd, Clone, Eq, Ord, Hash, Serialize, Deserialize)]
|
||||||
|
@ -129,6 +132,17 @@ impl Field for FieldPrime {
|
||||||
value: &x - x.div_floor(&*P) * &*P,
|
value: &x - x.div_floor(&*P) * &*P,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fn to_compact_dec_string(&self) -> String {
|
||||||
|
// values up to (p-1)/2 included are represented as positive, values between (p+1)/2 and p-1 as represented as negative by subtracting p
|
||||||
|
if self.value <= FieldPrime::max_value().value / 2 {
|
||||||
|
format!("{}", self.value.to_str_radix(10))
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
"({})",
|
||||||
|
(&self.value - (FieldPrime::max_value().value + BigInt::one())).to_str_radix(10)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FieldPrime {
|
impl Default for FieldPrime {
|
||||||
|
@ -612,6 +626,29 @@ mod tests {
|
||||||
let bv = fp.to_dec_string();
|
let bv = fp.to_dec_string();
|
||||||
assert_eq!(fp, FieldPrime::from_dec_string(bv));
|
assert_eq!(fp, FieldPrime::from_dec_string(bv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn compact_representation() {
|
||||||
|
let one = FieldPrime::from(1);
|
||||||
|
assert_eq!("1", &one.to_compact_dec_string());
|
||||||
|
let minus_one = FieldPrime::from(0) - one;
|
||||||
|
assert_eq!("(-1)", &minus_one.to_compact_dec_string());
|
||||||
|
// (p-1)/2 -> positive notation
|
||||||
|
let p_minus_one_over_two =
|
||||||
|
(FieldPrime::from(0) - FieldPrime::from(1)) / FieldPrime::from(2);
|
||||||
|
assert_eq!(
|
||||||
|
"10944121435919637611123202872628637544274182200208017171849102093287904247808",
|
||||||
|
&p_minus_one_over_two.to_compact_dec_string()
|
||||||
|
);
|
||||||
|
// (p-1)/2 + 1 -> negative notation (p-1)/2 + 1 - p == (-p+1)/2
|
||||||
|
let p_minus_one_over_two_plus_one = ((FieldPrime::from(0) - FieldPrime::from(1))
|
||||||
|
/ FieldPrime::from(2))
|
||||||
|
+ FieldPrime::from(1);
|
||||||
|
assert_eq!(
|
||||||
|
"(-10944121435919637611123202872628637544274182200208017171849102093287904247808)",
|
||||||
|
&p_minus_one_over_two_plus_one.to_compact_dec_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue