1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00

Merge pull request #1210 from Zokrates/rc/0.8.1

Release 0.8.1
This commit is contained in:
Thibaut Schaeffer 2022-08-23 12:52:49 +02:00 committed by GitHub
commit 574435914d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 1576 additions and 9815 deletions

View file

@ -106,7 +106,7 @@ jobs:
- run:
name: Build
no_output_timeout: "30m"
command: npm run build:dev && npm pack --dry-run
command: npm ci && npm run build:dev && npm pack --dry-run
- save-sccache-cache
zokrates_js_test:
docker:
@ -127,7 +127,7 @@ jobs:
- run:
name: Run tests
no_output_timeout: "30m"
command: npm run test
command: npm ci && npm run test
- save-sccache-cache
cross_build:
parameters:
@ -164,11 +164,6 @@ jobs:
name: "Publish artifacts on GitHub"
command: |
go install github.com/github-release/github-release@latest
github-release release \
-s ${GH_TOKEN} \
-u ${CIRCLE_PROJECT_USERNAME} \
-r ${CIRCLE_PROJECT_REPONAME} \
-t ${CIRCLE_TAG} || true
find /tmp/artifacts -type f -name *.tar.gz -exec basename {} \; | xargs -I {} github-release upload \
-s ${GH_TOKEN} \
-u ${CIRCLE_PROJECT_USERNAME} \
@ -214,8 +209,8 @@ commands:
install_cross:
steps:
- run:
name: Install rust-embedded/cross
command: cargo install --git https://github.com/rust-embedded/cross
name: Install cross
command: cargo install cross --git https://github.com/cross-rs/cross
tar_artifacts:
parameters:
target:

View file

@ -1,11 +0,0 @@
Language: Cpp
BasedOnStyle: WebKit
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
# make adding new members at the end less noisy in diffs
BreakConstructorInitializersBeforeComma: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true

View file

@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
https://github.com/Zokrates/ZoKrates/compare/latest...develop
## [0.8.1] - 2022-08-22
### Release
- https://github.com/Zokrates/ZoKrates/releases/tag/0.8.1 <!-- markdown-link-check-disable-line -->
### Changes
- Error out at compile time if the type of a logged value could not be inferred (#1209, @dark64)
- Add `backend` option in `zokrates-js`, bring back bellman, add a log writer to support printing logs in js (#1199, @dark64)
- Fix padding bug in keccak implementation, add support for keccak-224 and sha3-224 (#1197, @dark64)
- Update syntax highlighters (#1195, @schaeff)
- Avoid validity checks on the deserialization of the proving key to improve proving time (#1192, @dark64)
## [0.8.0] - 2022-07-07
### Release

27
Cargo.lock generated
View file

@ -1480,6 +1480,12 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "json"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd"
[[package]]
name = "keccak"
version = "0.1.2"
@ -2993,7 +2999,7 @@ dependencies = [
[[package]]
name = "zokrates_ark"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"ark-bls12-377",
"ark-bn254",
@ -3020,7 +3026,7 @@ dependencies = [
[[package]]
name = "zokrates_ast"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"ark-bls12-377",
"cfg-if 0.1.10",
@ -3066,7 +3072,7 @@ dependencies = [
[[package]]
name = "zokrates_cli"
version = "0.8.0"
version = "0.8.1"
dependencies = [
"assert_cli",
"blake2 0.8.1",
@ -3111,7 +3117,7 @@ version = "0.1.1"
[[package]]
name = "zokrates_core"
version = "0.7.0"
version = "0.7.1"
dependencies = [
"cfg-if 0.1.10",
"csv",
@ -3193,7 +3199,7 @@ dependencies = [
[[package]]
name = "zokrates_interpreter"
version = "0.1.0"
version = "0.1.1"
dependencies = [
"ark-bls12-377",
"num 0.1.42",
@ -3208,18 +3214,23 @@ dependencies = [
[[package]]
name = "zokrates_js"
version = "1.1.0"
version = "1.1.2"
dependencies = [
"console_error_panic_hook",
"indexmap",
"js-sys",
"json",
"lazy_static",
"serde",
"serde_json",
"toml",
"typed-arena",
"walkdir",
"wasm-bindgen",
"zokrates_abi",
"zokrates_ark",
"zokrates_ast",
"zokrates_bellman",
"zokrates_circom",
"zokrates_common",
"zokrates_core",
@ -3230,7 +3241,7 @@ dependencies = [
[[package]]
name = "zokrates_parser"
version = "0.3.0"
version = "0.3.1"
dependencies = [
"glob 0.2.11",
"pest",
@ -3281,7 +3292,7 @@ dependencies = [
[[package]]
name = "zokrates_stdlib"
version = "0.3.0"
version = "0.3.1"
dependencies = [
"fs_extra",
"zokrates_test",

View file

@ -8,9 +8,7 @@ RUN cd src; ./build_release.sh
FROM ubuntu:20.04
ENV ZOKRATES_HOME=/home/zokrates/.zokrates
RUN apt-get update \
&& apt-get install -y --no-install-recommends libgmp3-dev \
&& useradd -u 1000 -m zokrates
RUN useradd -u 1000 -m zokrates
USER zokrates
WORKDIR /home/zokrates

View file

@ -1,7 +1,6 @@
FROM ubuntu:20.04
SHELL ["/bin/bash", "-c"]
ARG RUST_VERSION=nightly
ARG DEBIAN_FRONTEND=noninteractive
ENV RUSTUP_HOME=/usr/local/rustup \
@ -25,12 +24,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
&& rm -rf /var/lib/apt/lists/*
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain none -y \
&& rustup toolchain install $RUST_VERSION --allow-downgrade --profile minimal --component rustfmt clippy \
&& curl -sL https://deb.nodesource.com/setup_16.x | bash - && apt-get install -y nodejs && npm i -g solc \
&& curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh \
&& curl -sL https://raw.githubusercontent.com/Sarcasm/run-clang-format/master/run-clang-format.py > /opt/run-clang-format.py \
&& chmod +x /opt/run-clang-format.py \
&& ln -s /opt/run-clang-format.py /usr/bin \
&& rustup --version; cargo --version; rustc --version; wasm-pack --version; echo nodejs $(node -v);
RUN cd /opt && curl -LO https://github.com/mozilla/geckodriver/releases/download/v0.28.0/geckodriver-v0.28.0-linux64.tar.gz \

View file

@ -1,13 +0,0 @@
#!/bin/bash
apt-get update && apt-get install -y --no-install-recommends \
build-essential \
cmake \
libboost-dev \
libboost-program-options-dev \
libgmp3-dev \
libprocps-dev \
libssl-dev \
pkg-config \
python-markdown \
&& rm -rf /var/lib/apt/lists/* \

View file

@ -33,6 +33,14 @@ git tag -f $TAG
git push origin -f latest
git push origin $TAG
# Create a release draft
curl \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: token $GH_TOKEN" \
https://api.github.com/repos/Zokrates/ZoKrates/releases \
-d "{\"tag_name\":\"$TAG\",\"draft\":true}"
# Build zokrates js
docker build -t zokrates_js -f zokrates_js/Dockerfile .

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_ark"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -25,7 +25,7 @@ impl<T: Field + ArkFieldExtensions> NonUniversalBackend<T, GM17> for Ark {
let (pk, vk) = ArkGM17::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
pk.serialize_unchecked(&mut pk_vec).unwrap();
let vk = VerificationKey {
h: parse_g2::<T>(&vk.h_g2),
@ -54,7 +54,7 @@ impl<T: Field + ArkFieldExtensions> Backend<T, GM17> for Ark {
.map(parse_fr::<T>)
.collect::<Vec<_>>();
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(
&mut proving_key.as_slice(),
)
.unwrap();

View file

@ -34,7 +34,7 @@ impl<T: Field + ArkFieldExtensions> Backend<T, G16> for Ark {
.map(parse_fr::<T>)
.collect::<Vec<_>>();
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_uncompressed(
let pk = ProvingKey::<<T as ArkFieldExtensions>::ArkEngine>::deserialize_unchecked(
&mut proving_key.as_slice(),
)
.unwrap();
@ -97,7 +97,7 @@ impl<T: Field + ArkFieldExtensions> NonUniversalBackend<T, G16> for Ark {
let (pk, vk) = Groth16::<T::ArkEngine>::circuit_specific_setup(computation, rng).unwrap();
let mut pk_vec: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut pk_vec).unwrap();
pk.serialize_unchecked(&mut pk_vec).unwrap();
let vk = VerificationKey {
alpha: parse_g1::<T>(&vk.alpha_g1),

View file

@ -164,7 +164,7 @@ impl<T: Field + ArkFieldExtensions> UniversalBackend<T, marlin::Marlin> for Ark
})?;
let mut serialized_pk: Vec<u8> = Vec::new();
pk.serialize_uncompressed(&mut serialized_pk).unwrap();
pk.serialize_unchecked(&mut serialized_pk).unwrap();
// Precompute some useful values for solidity contract
let fs_seed = to_bytes![&MarlinInst::<T>::PROTOCOL_NAME, &vk].unwrap();
@ -225,7 +225,7 @@ impl<T: Field + ArkFieldExtensions> Backend<T, marlin::Marlin> for Ark {
T::ArkEngine,
DensePolynomial<<<T as ArkFieldExtensions>::ArkEngine as PairingEngine>::Fr>,
>,
>::deserialize_uncompressed(&mut proving_key.as_slice())
>::deserialize_unchecked(&mut proving_key.as_slice())
.unwrap();
let public_inputs = computation.public_inputs_values();

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_ast"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
[features]

View file

@ -4,6 +4,27 @@ use crate::zir::types::UBitwidth;
use crate::zir::*;
use zokrates_field::Field;
pub trait Fold<'ast, T: Field>: Sized {
fn fold<F: Folder<'ast, T>>(self, f: &mut F) -> Self;
}
impl<'ast, T: Field> Fold<'ast, T> for FieldElementExpression<'ast, T> {
fn fold<F: Folder<'ast, T>>(self, f: &mut F) -> Self {
f.fold_field_expression(self)
}
}
impl<'ast, T: Field> Fold<'ast, T> for BooleanExpression<'ast, T> {
fn fold<F: Folder<'ast, T>>(self, f: &mut F) -> Self {
f.fold_boolean_expression(self)
}
}
impl<'ast, T: Field> Fold<'ast, T> for UExpression<'ast, T> {
fn fold<F: Folder<'ast, T>>(self, f: &mut F) -> Self {
f.fold_uint_expression(self)
}
}
pub trait Folder<'ast, T: Field>: Sized {
fn fold_program(&mut self, p: ZirProgram<'ast, T>) -> ZirProgram<'ast, T> {
fold_program(self, p)
@ -39,6 +60,22 @@ pub trait Folder<'ast, T: Field>: Sized {
fold_statement(self, s)
}
fn fold_conditional_expression<E: Expr<'ast, T> + Fold<'ast, T> + Conditional<'ast, T>>(
&mut self,
ty: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
fold_conditional_expression(self, ty, e)
}
fn fold_select_expression<E: Expr<'ast, T> + Fold<'ast, T> + Select<'ast, T>>(
&mut self,
ty: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> SelectOrExpression<'ast, T, E> {
fold_select_expression(self, ty, e)
}
fn fold_expression(&mut self, e: ZirExpression<'ast, T>) -> ZirExpression<'ast, T> {
match e {
ZirExpression::FieldElement(e) => self.fold_field_expression(e).into(),
@ -141,10 +178,12 @@ pub fn fold_field_expression<'ast, T: Field, F: Folder<'ast, T>>(
FieldElementExpression::Identifier(id) => {
FieldElementExpression::Identifier(f.fold_name(id))
}
FieldElementExpression::Select(a, box i) => FieldElementExpression::Select(
a.into_iter().map(|a| f.fold_field_expression(a)).collect(),
box f.fold_uint_expression(i),
),
FieldElementExpression::Select(e) => {
match f.fold_select_expression(&Type::FieldElement, e) {
SelectOrExpression::Select(s) => FieldElementExpression::Select(s),
SelectOrExpression::Expression(u) => u,
}
}
FieldElementExpression::Add(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
@ -170,11 +209,11 @@ pub fn fold_field_expression<'ast, T: Field, F: Folder<'ast, T>>(
let e2 = f.fold_uint_expression(e2);
FieldElementExpression::Pow(box e1, box e2)
}
FieldElementExpression::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond);
let cons = f.fold_field_expression(cons);
let alt = f.fold_field_expression(alt);
FieldElementExpression::Conditional(box cond, box cons, box alt)
FieldElementExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::FieldElement, c) {
ConditionalOrExpression::Conditional(s) => FieldElementExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
}
}
}
}
@ -186,12 +225,10 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
match e {
BooleanExpression::Value(v) => BooleanExpression::Value(v),
BooleanExpression::Identifier(id) => BooleanExpression::Identifier(f.fold_name(id)),
BooleanExpression::Select(a, box i) => BooleanExpression::Select(
a.into_iter()
.map(|a| f.fold_boolean_expression(a))
.collect(),
box f.fold_uint_expression(i),
),
BooleanExpression::Select(e) => match f.fold_select_expression(&Type::Boolean, e) {
SelectOrExpression::Select(s) => BooleanExpression::Select(s),
SelectOrExpression::Expression(u) => u,
},
BooleanExpression::FieldEq(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
@ -212,41 +249,21 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
let e2 = f.fold_field_expression(e2);
BooleanExpression::FieldLt(box e1, box e2)
}
BooleanExpression::FieldLe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
BooleanExpression::FieldLe(box e1, box e2)
}
BooleanExpression::FieldGt(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
BooleanExpression::FieldGt(box e1, box e2)
}
BooleanExpression::FieldGe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
BooleanExpression::FieldGe(box e1, box e2)
}
BooleanExpression::UintLt(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1);
let e2 = f.fold_uint_expression(e2);
BooleanExpression::UintLt(box e1, box e2)
}
BooleanExpression::FieldLe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1);
let e2 = f.fold_field_expression(e2);
BooleanExpression::FieldLe(box e1, box e2)
}
BooleanExpression::UintLe(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1);
let e2 = f.fold_uint_expression(e2);
BooleanExpression::UintLe(box e1, box e2)
}
BooleanExpression::UintGt(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1);
let e2 = f.fold_uint_expression(e2);
BooleanExpression::UintGt(box e1, box e2)
}
BooleanExpression::UintGe(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1);
let e2 = f.fold_uint_expression(e2);
BooleanExpression::UintGe(box e1, box e2)
}
BooleanExpression::Or(box e1, box e2) => {
let e1 = f.fold_boolean_expression(e1);
let e2 = f.fold_boolean_expression(e2);
@ -261,12 +278,11 @@ pub fn fold_boolean_expression<'ast, T: Field, F: Folder<'ast, T>>(
let e = f.fold_boolean_expression(e);
BooleanExpression::Not(box e)
}
BooleanExpression::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond);
let cons = f.fold_boolean_expression(cons);
let alt = f.fold_boolean_expression(alt);
BooleanExpression::Conditional(box cond, box cons, box alt)
}
BooleanExpression::Conditional(c) => match f.fold_conditional_expression(&Type::Boolean, c)
{
ConditionalOrExpression::Conditional(s) => BooleanExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
}
}
@ -282,16 +298,16 @@ pub fn fold_uint_expression<'ast, T: Field, F: Folder<'ast, T>>(
pub fn fold_uint_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
f: &mut F,
_: UBitwidth,
ty: UBitwidth,
e: UExpressionInner<'ast, T>,
) -> UExpressionInner<'ast, T> {
match e {
UExpressionInner::Value(v) => UExpressionInner::Value(v),
UExpressionInner::Identifier(id) => UExpressionInner::Identifier(f.fold_name(id)),
UExpressionInner::Select(a, box i) => UExpressionInner::Select(
a.into_iter().map(|a| f.fold_uint_expression(a)).collect(),
box f.fold_uint_expression(i),
),
UExpressionInner::Select(e) => match f.fold_select_expression(&ty, e) {
SelectOrExpression::Select(s) => UExpressionInner::Select(s),
SelectOrExpression::Expression(u) => u,
},
UExpressionInner::Add(box left, box right) => {
let left = f.fold_uint_expression(left);
let right = f.fold_uint_expression(right);
@ -355,12 +371,10 @@ pub fn fold_uint_expression_inner<'ast, T: Field, F: Folder<'ast, T>>(
UExpressionInner::Not(box e)
}
UExpressionInner::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond);
let cons = f.fold_uint_expression(cons);
let alt = f.fold_uint_expression(alt);
UExpressionInner::Conditional(box cond, box cons, box alt)
}
UExpressionInner::Conditional(c) => match f.fold_conditional_expression(&ty, c) {
ConditionalOrExpression::Conditional(s) => UExpressionInner::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
}
}
@ -391,3 +405,36 @@ pub fn fold_program<'ast, T: Field, F: Folder<'ast, T>>(
main: f.fold_function(p.main),
}
}
pub fn fold_conditional_expression<
'ast,
T: Field,
E: Expr<'ast, T> + Fold<'ast, T> + Conditional<'ast, T>,
F: Folder<'ast, T>,
>(
f: &mut F,
_: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> ConditionalOrExpression<'ast, T, E> {
ConditionalOrExpression::Conditional(ConditionalExpression::new(
f.fold_boolean_expression(*e.condition),
e.consequence.fold(f),
e.alternative.fold(f),
))
}
pub fn fold_select_expression<
'ast,
T: Field,
E: Expr<'ast, T> + Fold<'ast, T> + Select<'ast, T>,
F: Folder<'ast, T>,
>(
f: &mut F,
_: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> SelectOrExpression<'ast, T, E> {
SelectOrExpression::Select(SelectExpression::new(
e.array.into_iter().map(|e| e.fold(f)).collect(),
e.index.fold(f),
))
}

View file

@ -8,7 +8,7 @@ mod uint;
mod variable;
pub use self::parameter::Parameter;
pub use self::types::Type;
pub use self::types::{Type, UBitwidth};
pub use self::variable::Variable;
use crate::common::{FlatEmbed, FormatString};
use crate::typed::ConcreteType;
@ -23,7 +23,7 @@ pub use self::folder::Folder;
pub use self::identifier::{Identifier, SourceIdentifier};
/// A typed program as a collection of modules, one of them being the main
#[derive(PartialEq, Eq, Debug)]
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct ZirProgram<'ast, T> {
pub main: ZirFunction<'ast, T>,
}
@ -138,14 +138,15 @@ impl<'ast, T: fmt::Display> ZirStatement<'ast, T> {
write!(f, "{}", "\t".repeat(depth))?;
match self {
ZirStatement::Return(ref exprs) => {
write!(f, "return ")?;
for (i, expr) in exprs.iter().enumerate() {
write!(f, "{}", expr)?;
if i < exprs.len() - 1 {
write!(f, ", ")?;
}
}
write!(f, ";")
write!(
f,
"return {};",
exprs
.iter()
.map(|e| e.to_string())
.collect::<Vec<_>>()
.join(", ")
)
}
ZirStatement::Definition(ref lhs, ref rhs) => {
write!(f, "{} = {};", lhs, rhs)
@ -181,7 +182,7 @@ impl<'ast, T: fmt::Display> ZirStatement<'ast, T> {
}
ZirStatement::Log(ref l, ref expressions) => write!(
f,
"log(\"{}\"), {})",
"log(\"{}\"), {});",
l,
expressions
.iter()
@ -203,6 +204,63 @@ pub trait Typed {
fn get_type(&self) -> Type;
}
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub struct ConditionalExpression<'ast, T, E> {
pub condition: Box<BooleanExpression<'ast, T>>,
pub consequence: Box<E>,
pub alternative: Box<E>,
}
impl<'ast, T, E> ConditionalExpression<'ast, T, E> {
pub fn new(condition: BooleanExpression<'ast, T>, consequence: E, alternative: E) -> Self {
ConditionalExpression {
condition: box condition,
consequence: box consequence,
alternative: box alternative,
}
}
}
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for ConditionalExpression<'ast, T, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{} ? {} : {}",
self.condition, self.consequence, self.alternative
)
}
}
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
pub struct SelectExpression<'ast, T, E> {
pub array: Vec<E>,
pub index: Box<UExpression<'ast, T>>,
}
impl<'ast, T, E> SelectExpression<'ast, T, E> {
pub fn new(array: Vec<E>, index: UExpression<'ast, T>) -> Self {
SelectExpression {
array,
index: box index,
}
}
}
impl<'ast, T: fmt::Display, E: fmt::Display> fmt::Display for SelectExpression<'ast, T, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}[{}]",
self.array
.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", "),
self.index
)
}
}
/// A typed expression
#[derive(Clone, PartialEq, Hash, Eq)]
pub enum ZirExpression<'ast, T> {
@ -291,7 +349,7 @@ pub enum ZirExpressionList<'ast, T> {
pub enum FieldElementExpression<'ast, T> {
Number(T),
Identifier(Identifier<'ast>),
Select(Vec<Self>, Box<UExpression<'ast, T>>),
Select(SelectExpression<'ast, T, Self>),
Add(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
@ -312,11 +370,7 @@ pub enum FieldElementExpression<'ast, T> {
Box<FieldElementExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
),
Conditional(
Box<BooleanExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
Conditional(ConditionalExpression<'ast, T, FieldElementExpression<'ast, T>>),
}
/// An expression of type `bool`
@ -324,7 +378,7 @@ pub enum FieldElementExpression<'ast, T> {
pub enum BooleanExpression<'ast, T> {
Value(bool),
Identifier(Identifier<'ast>),
Select(Vec<Self>, Box<UExpression<'ast, T>>),
Select(SelectExpression<'ast, T, Self>),
FieldLt(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
@ -333,22 +387,12 @@ pub enum BooleanExpression<'ast, T> {
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FieldGe(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FieldGt(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
FieldEq(
Box<FieldElementExpression<'ast, T>>,
Box<FieldElementExpression<'ast, T>>,
),
UintLt(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintLe(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintGe(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintGt(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
UintEq(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
BoolEq(
Box<BooleanExpression<'ast, T>>,
@ -363,11 +407,7 @@ pub enum BooleanExpression<'ast, T> {
Box<BooleanExpression<'ast, T>>,
),
Not(Box<BooleanExpression<'ast, T>>),
Conditional(
Box<BooleanExpression<'ast, T>>,
Box<BooleanExpression<'ast, T>>,
Box<BooleanExpression<'ast, T>>,
),
Conditional(ConditionalExpression<'ast, T, BooleanExpression<'ast, T>>),
}
pub struct ConjunctionIterator<T> {
@ -438,26 +478,14 @@ impl<'ast, T: fmt::Display> fmt::Display for FieldElementExpression<'ast, T> {
match *self {
FieldElementExpression::Number(ref i) => write!(f, "{}", i),
FieldElementExpression::Identifier(ref var) => write!(f, "{}", var),
FieldElementExpression::Select(ref a, ref i) => write!(
f,
"[{}][{}]",
a.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", "),
i
),
FieldElementExpression::Select(ref e) => write!(f, "{}", e),
FieldElementExpression::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
FieldElementExpression::Sub(ref lhs, ref rhs) => write!(f, "({} - {})", lhs, rhs),
FieldElementExpression::Mult(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
FieldElementExpression::Div(ref lhs, ref rhs) => write!(f, "({} / {})", lhs, rhs),
FieldElementExpression::Pow(ref lhs, ref rhs) => write!(f, "{}**{}", lhs, rhs),
FieldElementExpression::Conditional(ref condition, ref consequent, ref alternative) => {
write!(
f,
"if {} {{ {} }} else {{ {} }}",
condition, consequent, alternative
)
FieldElementExpression::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
@ -468,15 +496,7 @@ impl<'ast, T: fmt::Display> fmt::Display for UExpression<'ast, T> {
match self.inner {
UExpressionInner::Value(ref v) => write!(f, "{}", v),
UExpressionInner::Identifier(ref var) => write!(f, "{}", var),
UExpressionInner::Select(ref a, ref i) => write!(
f,
"[{}][{}]",
a.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", "),
i
),
UExpressionInner::Select(ref e) => write!(f, "{}", e),
UExpressionInner::Add(ref lhs, ref rhs) => write!(f, "({} + {})", lhs, rhs),
UExpressionInner::Sub(ref lhs, ref rhs) => write!(f, "({} - {})", lhs, rhs),
UExpressionInner::Mult(ref lhs, ref rhs) => write!(f, "({} * {})", lhs, rhs),
@ -488,12 +508,8 @@ impl<'ast, T: fmt::Display> fmt::Display for UExpression<'ast, T> {
UExpressionInner::LeftShift(ref e, ref by) => write!(f, "({} << {})", e, by),
UExpressionInner::RightShift(ref e, ref by) => write!(f, "({} >> {})", e, by),
UExpressionInner::Not(ref e) => write!(f, "!{}", e),
UExpressionInner::Conditional(ref condition, ref consequent, ref alternative) => {
write!(
f,
"if {} {{ {} }} else {{ {} }}",
condition, consequent, alternative
)
UExpressionInner::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
@ -504,35 +520,19 @@ impl<'ast, T: fmt::Display> fmt::Display for BooleanExpression<'ast, T> {
match *self {
BooleanExpression::Identifier(ref var) => write!(f, "{}", var),
BooleanExpression::Value(b) => write!(f, "{}", b),
BooleanExpression::Select(ref a, ref i) => write!(
f,
"[{}][{}]",
a.iter()
.map(|a| a.to_string())
.collect::<Vec<_>>()
.join(", "),
i
),
BooleanExpression::FieldLt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
BooleanExpression::FieldLe(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
BooleanExpression::FieldGe(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
BooleanExpression::FieldGt(ref lhs, ref rhs) => write!(f, "{} > {}", lhs, rhs),
BooleanExpression::UintLt(ref lhs, ref rhs) => write!(f, "{} < {}", lhs, rhs),
BooleanExpression::UintLe(ref lhs, ref rhs) => write!(f, "{} <= {}", lhs, rhs),
BooleanExpression::UintGe(ref lhs, ref rhs) => write!(f, "{} >= {}", lhs, rhs),
BooleanExpression::UintGt(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::Or(ref lhs, ref rhs) => write!(f, "{} || {}", lhs, rhs),
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "{} && {}", lhs, rhs),
BooleanExpression::Select(ref e) => write!(f, "{}", e),
BooleanExpression::FieldLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::UintLt(ref lhs, ref rhs) => write!(f, "({} < {})", lhs, rhs),
BooleanExpression::FieldLe(ref lhs, ref rhs) => write!(f, "({} <= {})", lhs, rhs),
BooleanExpression::UintLe(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::Or(ref lhs, ref rhs) => write!(f, "({} || {})", lhs, rhs),
BooleanExpression::And(ref lhs, ref rhs) => write!(f, "({} && {})", lhs, rhs),
BooleanExpression::Not(ref exp) => write!(f, "!{}", exp),
BooleanExpression::Conditional(ref condition, ref consequent, ref alternative) => {
write!(
f,
"if {} {{ {} }} else {{ {} }}",
condition, consequent, alternative
)
BooleanExpression::Conditional(ref c) => {
write!(f, "{}", c)
}
}
}
@ -584,7 +584,81 @@ impl<'ast, T: fmt::Debug> fmt::Debug for ZirExpressionList<'ast, T> {
}
// Common behaviour accross expressions
pub trait Expr<'ast, T>: fmt::Display + PartialEq {
type Inner;
type Ty: Clone + IntoType;
fn ty(&self) -> &Self::Ty;
fn into_inner(self) -> Self::Inner;
fn as_inner(&self) -> &Self::Inner;
fn as_inner_mut(&mut self) -> &mut Self::Inner;
}
impl<'ast, T: Field> Expr<'ast, T> for FieldElementExpression<'ast, T> {
type Inner = Self;
type Ty = Type;
fn ty(&self) -> &Self::Ty {
&Type::FieldElement
}
fn into_inner(self) -> Self::Inner {
self
}
fn as_inner(&self) -> &Self::Inner {
self
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
self
}
}
impl<'ast, T: Field> Expr<'ast, T> for BooleanExpression<'ast, T> {
type Inner = Self;
type Ty = Type;
fn ty(&self) -> &Self::Ty {
&Type::Boolean
}
fn into_inner(self) -> Self::Inner {
self
}
fn as_inner(&self) -> &Self::Inner {
self
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
self
}
}
impl<'ast, T: Field> Expr<'ast, T> for UExpression<'ast, T> {
type Inner = UExpressionInner<'ast, T>;
type Ty = UBitwidth;
fn ty(&self) -> &Self::Ty {
&self.bitwidth
}
fn into_inner(self) -> Self::Inner {
self.inner
}
fn as_inner(&self) -> &Self::Inner {
&self.inner
}
fn as_inner_mut(&mut self) -> &mut Self::Inner {
&mut self.inner
}
}
pub trait Conditional<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
@ -593,13 +667,22 @@ pub trait Conditional<'ast, T> {
) -> Self;
}
pub enum ConditionalOrExpression<'ast, T, E: Expr<'ast, T>> {
Conditional(ConditionalExpression<'ast, T, E>),
Expression(E::Inner),
}
impl<'ast, T> Conditional<'ast, T> for FieldElementExpression<'ast, T> {
fn conditional(
condition: BooleanExpression<'ast, T>,
consequence: Self,
alternative: Self,
) -> Self {
FieldElementExpression::Conditional(box condition, box consequence, box alternative)
FieldElementExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
}
}
@ -609,7 +692,11 @@ impl<'ast, T> Conditional<'ast, T> for BooleanExpression<'ast, T> {
consequence: Self,
alternative: Self,
) -> Self {
BooleanExpression::Conditional(box condition, box consequence, box alternative)
BooleanExpression::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
}
}
@ -621,7 +708,56 @@ impl<'ast, T> Conditional<'ast, T> for UExpression<'ast, T> {
) -> Self {
let bitwidth = consequence.bitwidth;
UExpressionInner::Conditional(box condition, box consequence, box alternative)
.annotate(bitwidth)
UExpressionInner::Conditional(ConditionalExpression::new(
condition,
consequence,
alternative,
))
.annotate(bitwidth)
}
}
pub trait Select<'ast, T>: Sized {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self;
}
pub enum SelectOrExpression<'ast, T, E: Expr<'ast, T>> {
Select(SelectExpression<'ast, T, E>),
Expression(E::Inner),
}
impl<'ast, T> Select<'ast, T> for FieldElementExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
FieldElementExpression::Select(SelectExpression::new(array, index))
}
}
impl<'ast, T> Select<'ast, T> for BooleanExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
BooleanExpression::Select(SelectExpression::new(array, index))
}
}
impl<'ast, T> Select<'ast, T> for UExpression<'ast, T> {
fn select(array: Vec<Self>, index: UExpression<'ast, T>) -> Self {
let bitwidth = array[0].bitwidth;
UExpressionInner::Select(SelectExpression::new(array, index)).annotate(bitwidth)
}
}
pub trait IntoType {
fn into_type(self) -> Type;
}
impl IntoType for Type {
fn into_type(self) -> Type {
self
}
}
impl IntoType for UBitwidth {
fn into_type(self) -> Type {
Type::Uint(self)
}
}

View file

@ -4,6 +4,27 @@ use crate::zir::types::UBitwidth;
use crate::zir::*;
use zokrates_field::Field;
pub trait ResultFold<'ast, T: Field>: Sized {
fn fold<F: ResultFolder<'ast, T>>(self, f: &mut F) -> Result<Self, F::Error>;
}
impl<'ast, T: Field> ResultFold<'ast, T> for FieldElementExpression<'ast, T> {
fn fold<F: ResultFolder<'ast, T>>(self, f: &mut F) -> Result<Self, F::Error> {
f.fold_field_expression(self)
}
}
impl<'ast, T: Field> ResultFold<'ast, T> for BooleanExpression<'ast, T> {
fn fold<F: ResultFolder<'ast, T>>(self, f: &mut F) -> Result<Self, F::Error> {
f.fold_boolean_expression(self)
}
}
impl<'ast, T: Field> ResultFold<'ast, T> for UExpression<'ast, T> {
fn fold<F: ResultFolder<'ast, T>>(self, f: &mut F) -> Result<Self, F::Error> {
f.fold_uint_expression(self)
}
}
pub trait ResultFolder<'ast, T: Field>: Sized {
type Error;
@ -76,6 +97,24 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
}
}
fn fold_conditional_expression<
E: Expr<'ast, T> + ResultFold<'ast, T> + Conditional<'ast, T>,
>(
&mut self,
ty: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, Self::Error> {
fold_conditional_expression(self, ty, e)
}
fn fold_select_expression<E: Clone + Expr<'ast, T> + ResultFold<'ast, T> + Select<'ast, T>>(
&mut self,
ty: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> Result<SelectOrExpression<'ast, T, E>, Self::Error> {
fold_select_expression(self, ty, e)
}
fn fold_field_expression(
&mut self,
e: FieldElementExpression<'ast, T>,
@ -173,12 +212,12 @@ pub fn fold_field_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
FieldElementExpression::Identifier(id) => {
FieldElementExpression::Identifier(f.fold_name(id)?)
}
FieldElementExpression::Select(a, box i) => FieldElementExpression::Select(
a.into_iter()
.map(|a| f.fold_field_expression(a))
.collect::<Result<_, _>>()?,
box f.fold_uint_expression(i)?,
),
FieldElementExpression::Select(e) => {
match f.fold_select_expression(&Type::FieldElement, e)? {
SelectOrExpression::Select(s) => FieldElementExpression::Select(s),
SelectOrExpression::Expression(u) => u,
}
}
FieldElementExpression::Add(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
@ -204,11 +243,11 @@ pub fn fold_field_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
let e2 = f.fold_uint_expression(e2)?;
FieldElementExpression::Pow(box e1, box e2)
}
FieldElementExpression::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond)?;
let cons = f.fold_field_expression(cons)?;
let alt = f.fold_field_expression(alt)?;
FieldElementExpression::Conditional(box cond, box cons, box alt)
FieldElementExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::FieldElement, c)? {
ConditionalOrExpression::Conditional(s) => FieldElementExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
}
}
})
}
@ -220,12 +259,10 @@ pub fn fold_boolean_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
Ok(match e {
BooleanExpression::Value(v) => BooleanExpression::Value(v),
BooleanExpression::Identifier(id) => BooleanExpression::Identifier(f.fold_name(id)?),
BooleanExpression::Select(a, box i) => BooleanExpression::Select(
a.into_iter()
.map(|a| f.fold_boolean_expression(a))
.collect::<Result<_, _>>()?,
box f.fold_uint_expression(i)?,
),
BooleanExpression::Select(e) => match f.fold_select_expression(&Type::Boolean, e)? {
SelectOrExpression::Select(s) => BooleanExpression::Select(s),
SelectOrExpression::Expression(u) => u,
},
BooleanExpression::FieldEq(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
@ -246,41 +283,21 @@ pub fn fold_boolean_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
let e2 = f.fold_field_expression(e2)?;
BooleanExpression::FieldLt(box e1, box e2)
}
BooleanExpression::FieldLe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
BooleanExpression::FieldLe(box e1, box e2)
}
BooleanExpression::FieldGt(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
BooleanExpression::FieldGt(box e1, box e2)
}
BooleanExpression::FieldGe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
BooleanExpression::FieldGe(box e1, box e2)
}
BooleanExpression::UintLt(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1)?;
let e2 = f.fold_uint_expression(e2)?;
BooleanExpression::UintLt(box e1, box e2)
}
BooleanExpression::FieldLe(box e1, box e2) => {
let e1 = f.fold_field_expression(e1)?;
let e2 = f.fold_field_expression(e2)?;
BooleanExpression::FieldLe(box e1, box e2)
}
BooleanExpression::UintLe(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1)?;
let e2 = f.fold_uint_expression(e2)?;
BooleanExpression::UintLe(box e1, box e2)
}
BooleanExpression::UintGt(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1)?;
let e2 = f.fold_uint_expression(e2)?;
BooleanExpression::UintGt(box e1, box e2)
}
BooleanExpression::UintGe(box e1, box e2) => {
let e1 = f.fold_uint_expression(e1)?;
let e2 = f.fold_uint_expression(e2)?;
BooleanExpression::UintGe(box e1, box e2)
}
BooleanExpression::Or(box e1, box e2) => {
let e1 = f.fold_boolean_expression(e1)?;
let e2 = f.fold_boolean_expression(e2)?;
@ -295,11 +312,11 @@ pub fn fold_boolean_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
let e = f.fold_boolean_expression(e)?;
BooleanExpression::Not(box e)
}
BooleanExpression::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond)?;
let cons = f.fold_boolean_expression(cons)?;
let alt = f.fold_boolean_expression(alt)?;
BooleanExpression::Conditional(box cond, box cons, box alt)
BooleanExpression::Conditional(c) => {
match f.fold_conditional_expression(&Type::Boolean, c)? {
ConditionalOrExpression::Conditional(s) => BooleanExpression::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
}
}
})
}
@ -316,18 +333,16 @@ pub fn fold_uint_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
pub fn fold_uint_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
f: &mut F,
_: UBitwidth,
ty: UBitwidth,
e: UExpressionInner<'ast, T>,
) -> Result<UExpressionInner<'ast, T>, F::Error> {
Ok(match e {
UExpressionInner::Value(v) => UExpressionInner::Value(v),
UExpressionInner::Identifier(id) => UExpressionInner::Identifier(f.fold_name(id)?),
UExpressionInner::Select(a, box i) => UExpressionInner::Select(
a.into_iter()
.map(|a| f.fold_uint_expression(a))
.collect::<Result<_, _>>()?,
box f.fold_uint_expression(i)?,
),
UExpressionInner::Select(e) => match f.fold_select_expression(&ty, e)? {
SelectOrExpression::Select(s) => UExpressionInner::Select(s),
SelectOrExpression::Expression(u) => u,
},
UExpressionInner::Add(box left, box right) => {
let left = f.fold_uint_expression(left)?;
let right = f.fold_uint_expression(right)?;
@ -391,13 +406,10 @@ pub fn fold_uint_expression_inner<'ast, T: Field, F: ResultFolder<'ast, T>>(
UExpressionInner::Not(box e)
}
UExpressionInner::Conditional(box cond, box cons, box alt) => {
let cond = f.fold_boolean_expression(cond)?;
let cons = f.fold_uint_expression(cons)?;
let alt = f.fold_uint_expression(alt)?;
UExpressionInner::Conditional(box cond, box cons, box alt)
}
UExpressionInner::Conditional(c) => match f.fold_conditional_expression(&ty, c)? {
ConditionalOrExpression::Conditional(s) => UExpressionInner::Conditional(s),
ConditionalOrExpression::Expression(u) => u,
},
})
}
@ -431,3 +443,41 @@ pub fn fold_program<'ast, T: Field, F: ResultFolder<'ast, T>>(
main: f.fold_function(p.main)?,
})
}
pub fn fold_conditional_expression<
'ast,
T: Field,
E: Expr<'ast, T> + ResultFold<'ast, T> + Conditional<'ast, T>,
F: ResultFolder<'ast, T>,
>(
f: &mut F,
_: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, F::Error> {
Ok(ConditionalOrExpression::Conditional(
ConditionalExpression::new(
f.fold_boolean_expression(*e.condition)?,
e.consequence.fold(f)?,
e.alternative.fold(f)?,
),
))
}
pub fn fold_select_expression<
'ast,
T: Field,
E: Expr<'ast, T> + ResultFold<'ast, T> + Select<'ast, T>,
F: ResultFolder<'ast, T>,
>(
f: &mut F,
_: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> Result<SelectOrExpression<'ast, T, E>, F::Error> {
Ok(SelectOrExpression::Select(SelectExpression::new(
e.array
.into_iter()
.map(|e| e.fold(f))
.collect::<Result<Vec<_>, _>>()?,
e.index.fold(f)?,
)))
}

View file

@ -1,8 +1,9 @@
use crate::zir::identifier::Identifier;
use crate::zir::types::UBitwidth;
use crate::zir::BooleanExpression;
use zokrates_field::Field;
use super::{ConditionalExpression, SelectExpression};
impl<'ast, T: Field> UExpression<'ast, T> {
#[allow(clippy::should_implement_trait)]
pub fn add(self, other: Self) -> UExpression<'ast, T> {
@ -20,7 +21,7 @@ impl<'ast, T: Field> UExpression<'ast, T> {
pub fn select(values: Vec<Self>, index: Self) -> UExpression<'ast, T> {
let bitwidth = values[0].bitwidth;
UExpressionInner::Select(values, box index).annotate(bitwidth)
UExpressionInner::Select(SelectExpression::new(values, index)).annotate(bitwidth)
}
pub fn mult(self, other: Self) -> UExpression<'ast, T> {
@ -178,7 +179,7 @@ pub struct UExpression<'ast, T> {
pub enum UExpressionInner<'ast, T> {
Value(u128),
Identifier(Identifier<'ast>),
Select(Vec<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
Select(SelectExpression<'ast, T, UExpression<'ast, T>>),
Add(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
Sub(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
Mult(Box<UExpression<'ast, T>>, Box<UExpression<'ast, T>>),
@ -190,11 +191,7 @@ pub enum UExpressionInner<'ast, T> {
LeftShift(Box<UExpression<'ast, T>>, u32),
RightShift(Box<UExpression<'ast, T>>, u32),
Not(Box<UExpression<'ast, T>>),
Conditional(
Box<BooleanExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
Box<UExpression<'ast, T>>,
),
Conditional(ConditionalExpression<'ast, T, UExpression<'ast, T>>),
}
impl<'ast, T> UExpressionInner<'ast, T> {

View file

@ -64,14 +64,19 @@ Returns a `ZoKratesProvider` configured with given options.
```js
initialize().then((defaultProvider) => {
let zokratesProvider = defaultProvider.withOptions({ curve: "bls12_381", scheme: "g16" });
let zokratesProvider = defaultProvider.withOptions({
backend: "ark",
curve: "bls12_381",
scheme: "g16"
});
// ...
});
```
Options:
* `curve` - Elliptic curve (`bn128` | `bls12_381` | `bls12_377` | `bw6_761`)
* `scheme` - Proving scheme (`g16` | `gm17` | `marlin`)
* `backend` - Backend (options: `ark` | `bellman`, default: `ark`)
* `curve` - Elliptic curve (options: `bn128` | `bls12_381` | `bls12_377` | `bw6_761`, default: `bn128`)
* `scheme` - Proving scheme (options: `g16` | `gm17` | `marlin`, default: `g16`)
Returns: `ZoKratesProvider`
@ -123,12 +128,13 @@ const fileSystemResolver = (from, to) => {
};
```
##### computeWitness(artifacts, args)
##### computeWitness(artifacts, args[, options])
Computes a valid assignment of the variables, which include the results of the computation.
Parameters:
* `artifacts` - Compilation artifacts
* `args` - Array of arguments (eg. `["1", "2", true]`)
* `options` - Computation options
Returns: `ComputationResult`

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_cli"
version = "0.8.0"
version = "0.8.1"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>", "Thibaut Schaeffer <thibaut@schaeff.fr>"]
repository = "https://github.com/Zokrates/ZoKrates.git"
edition = "2018"

View file

@ -0,0 +1,4 @@
def main() {
log("{}", 1 + 1); // 1 is of internal type {integer}
return;
}

View file

@ -0,0 +1,4 @@
def main() {
log("{} {}", 1f);
return;
}

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_core"
version = "0.7.0"
version = "0.7.1"
edition = "2018"
authors = ["Jacob Eberhardt <jacob.eberhardt@tu-berlin.de>", "Dennis Kuhnert <mail@kyroy.com>"]
repository = "https://github.com/Zokrates/ZoKrates"

View file

@ -8,7 +8,9 @@
mod utils;
use self::utils::flat_expression_from_bits;
use zokrates_ast::zir::{ShouldReduce, UMetadata, ZirExpressionList};
use zokrates_ast::zir::{
ConditionalExpression, SelectExpression, ShouldReduce, UMetadata, ZirExpressionList,
};
use zokrates_interpreter::Interpreter;
use crate::compile::CompileConfig;
@ -558,13 +560,15 @@ impl<'ast, T: Field> Flattener<'ast, T> {
/// * `alternative` - the alternative of type U.
/// # Remarks
/// * U is the type of the expression
fn flatten_if_else_expression<U: Flatten<'ast, T>>(
fn flatten_conditional_expression<U: Flatten<'ast, T>>(
&mut self,
statements_flattened: &mut FlatStatements<T>,
condition: BooleanExpression<'ast, T>,
consequence: U,
alternative: U,
e: ConditionalExpression<'ast, T, U>,
) -> FlatUExpression<T> {
let condition = *e.condition;
let consequence = *e.consequence;
let alternative = *e.alternative;
let condition_flat =
self.flatten_boolean_expression(statements_flattened, condition.clone());
@ -859,8 +863,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
BooleanExpression::Identifier(x) => {
FlatExpression::Identifier(*self.layout.get(&x).unwrap())
}
BooleanExpression::Select(a, box index) => self
.flatten_select_expression(statements_flattened, a, index)
BooleanExpression::Select(e) => self
.flatten_select_expression(statements_flattened, e)
.get_field_unchecked(),
BooleanExpression::FieldLt(box lhs, box rhs) => {
// Get the bit width to know the size of the binary decompositions for this Field
@ -949,14 +953,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
);
FlatExpression::Add(box eq, box lt)
}
BooleanExpression::FieldGt(lhs, rhs) => self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::FieldLt(rhs, lhs),
),
BooleanExpression::FieldGe(lhs, rhs) => self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::FieldLe(rhs, lhs),
),
BooleanExpression::UintLt(box lhs, box rhs) => {
let bit_width = lhs.bitwidth.to_usize();
assert!(lhs.metadata.as_ref().unwrap().should_reduce.to_bool());
@ -987,14 +983,6 @@ impl<'ast, T: Field> Flattener<'ast, T> {
);
FlatExpression::Add(box eq, box lt)
}
BooleanExpression::UintGt(lhs, rhs) => self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::UintLt(rhs, lhs),
),
BooleanExpression::UintGe(lhs, rhs) => self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::UintLe(rhs, lhs),
),
BooleanExpression::Or(box lhs, box rhs) => {
let x = self.flatten_boolean_expression(statements_flattened, lhs);
let y = self.flatten_boolean_expression(statements_flattened, rhs);
@ -1036,13 +1024,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
true => T::from(1),
false => T::from(0),
}),
BooleanExpression::Conditional(box condition, box consequence, box alternative) => self
.flatten_if_else_expression(
statements_flattened,
condition,
consequence,
alternative,
)
BooleanExpression::Conditional(e) => self
.flatten_conditional_expression(statements_flattened, e)
.get_field_unchecked(),
}
}
@ -1473,9 +1456,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
});
FlatUExpression::with_field(field).bits(bits)
}
UExpressionInner::Select(a, box index) => {
self.flatten_select_expression(statements_flattened, a, index)
}
UExpressionInner::Select(e) => self.flatten_select_expression(statements_flattened, e),
UExpressionInner::Not(box e) => {
let e = self.flatten_uint_expression(statements_flattened, e);
@ -1633,13 +1614,9 @@ impl<'ast, T: Field> Flattener<'ast, T> {
FlatUExpression::with_field(r)
}
UExpressionInner::Conditional(box condition, box consequence, box alternative) => self
.flatten_if_else_expression(
statements_flattened,
condition,
consequence,
alternative,
),
UExpressionInner::Conditional(e) => {
self.flatten_conditional_expression(statements_flattened, e)
}
UExpressionInner::Xor(box left, box right) => {
let left_metadata = left.metadata.clone().unwrap();
let right_metadata = right.metadata.clone().unwrap();
@ -2039,10 +2016,12 @@ impl<'ast, T: Field> Flattener<'ast, T> {
fn flatten_select_expression<U: Flatten<'ast, T>>(
&mut self,
statements_flattened: &mut FlatStatements<T>,
a: Vec<U>,
index: UExpression<'ast, T>,
e: SelectExpression<'ast, T, U>,
) -> FlatUExpression<T> {
let (range_check, result) = a
let array = e.array;
let index = *e.index;
let (range_check, result) = array
.into_iter()
.enumerate()
.map(|(i, e)| {
@ -2108,8 +2087,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
FieldElementExpression::Identifier(x) => {
FlatExpression::Identifier(*self.layout.get(&x).unwrap_or_else(|| panic!("{}", x)))
}
FieldElementExpression::Select(a, box index) => self
.flatten_select_expression(statements_flattened, a, index)
FieldElementExpression::Select(e) => self
.flatten_select_expression(statements_flattened, e)
.get_field_unchecked(),
FieldElementExpression::Add(box left, box right) => {
let left_flattened = self.flatten_field_expression(statements_flattened, left);
@ -2294,17 +2273,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
_ => panic!("Expected number as pow exponent"),
}
}
FieldElementExpression::Conditional(
box condition,
box consequence,
box alternative,
) => self
.flatten_if_else_expression(
statements_flattened,
condition,
consequence,
alternative,
)
FieldElementExpression::Conditional(e) => self
.flatten_conditional_expression(statements_flattened, e)
.get_field_unchecked(),
}
}
@ -2428,8 +2398,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
error.into(),
)
}
BooleanExpression::FieldLt(box lhs, box rhs)
| BooleanExpression::FieldGt(box rhs, box lhs) => {
BooleanExpression::FieldLt(box lhs, box rhs) => {
let lhs = self.flatten_field_expression(statements_flattened, lhs);
let rhs = self.flatten_field_expression(statements_flattened, rhs);
@ -2459,8 +2428,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
}
}
}
BooleanExpression::FieldLe(box lhs, box rhs)
| BooleanExpression::FieldGe(box rhs, box lhs) => {
BooleanExpression::FieldLe(box lhs, box rhs) => {
let lhs = self.flatten_field_expression(statements_flattened, lhs);
let rhs = self.flatten_field_expression(statements_flattened, rhs);
@ -3531,13 +3499,13 @@ mod tests {
#[test]
fn if_else() {
let config = CompileConfig::default();
let expression = FieldElementExpression::Conditional(
box BooleanExpression::FieldEq(
let expression = FieldElementExpression::conditional(
BooleanExpression::FieldEq(
box FieldElementExpression::Number(Bn128Field::from(32)),
box FieldElementExpression::Number(Bn128Field::from(4)),
),
box FieldElementExpression::Number(Bn128Field::from(12)),
box FieldElementExpression::Number(Bn128Field::from(51)),
FieldElementExpression::Number(Bn128Field::from(12)),
FieldElementExpression::Number(Bn128Field::from(51)),
);
let mut flattener = Flattener::new(config);
@ -3554,13 +3522,6 @@ mod tests {
box FieldElementExpression::Number(Bn128Field::from(4)),
);
flattener.flatten_boolean_expression(&mut FlatStatements::new(), expression_le);
let mut flattener = Flattener::new(config);
let expression_ge = BooleanExpression::FieldGe(
box FieldElementExpression::Number(Bn128Field::from(32)),
box FieldElementExpression::Number(Bn128Field::from(4)),
);
flattener.flatten_boolean_expression(&mut FlatStatements::new(), expression_ge);
}
#[test]
@ -3568,8 +3529,8 @@ mod tests {
let config = CompileConfig::default();
let mut flattener = Flattener::new(config);
let expression = FieldElementExpression::Conditional(
box BooleanExpression::And(
let expression = FieldElementExpression::conditional(
BooleanExpression::And(
box BooleanExpression::FieldEq(
box FieldElementExpression::Number(Bn128Field::from(4)),
box FieldElementExpression::Number(Bn128Field::from(4)),
@ -3579,8 +3540,8 @@ mod tests {
box FieldElementExpression::Number(Bn128Field::from(20)),
),
),
box FieldElementExpression::Number(Bn128Field::from(12)),
box FieldElementExpression::Number(Bn128Field::from(51)),
FieldElementExpression::Number(Bn128Field::from(12)),
FieldElementExpression::Number(Bn128Field::from(51)),
);
flattener.flatten_field_expression(&mut FlatStatements::new(), expression);

View file

@ -1804,15 +1804,30 @@ impl<'ast, T: Field> Checker<'ast, T> {
.collect::<Result<Vec<_>, _>>()
.map_err(|e| vec![e])?;
let mut errors = vec![];
for e in &expressions {
if let TypedExpression::Int(e) = e {
errors.push(ErrorInner {
pos: Some(pos),
message: format!("Cannot determine type for expression `{}`", e),
});
}
}
if expressions.len() != l.len() {
return Err(vec![ErrorInner {
errors.push(ErrorInner {
pos: Some(pos),
message: format!(
"Wrong argument count in log call: expected {}, got {}",
l.len(),
expressions.len()
),
}]);
});
}
if !errors.is_empty() {
return Err(errors);
}
Ok(TypedStatement::Log(l, expressions))

View file

@ -1,7 +1,7 @@
use std::marker::PhantomData;
use zokrates_ast::typed::types::UBitwidth;
use zokrates_ast::typed::{self, Expr, Typed};
use zokrates_ast::zir;
use zokrates_ast::zir::{self, Select};
use zokrates_field::Field;
use std::convert::{TryFrom, TryInto};
@ -746,36 +746,35 @@ fn fold_select_expression<'ast, T: Field, E>(
let ty = a[0].get_type();
match ty {
zir::Type::Boolean => zir::BooleanExpression::Select(
zir::Type::Boolean => zir::BooleanExpression::select(
a.into_iter()
.map(|e| match e {
zir::ZirExpression::Boolean(e) => e.clone(),
_ => unreachable!(),
})
.collect(),
box index.clone(),
index.clone(),
)
.into(),
zir::Type::FieldElement => zir::FieldElementExpression::Select(
zir::Type::FieldElement => zir::FieldElementExpression::select(
a.into_iter()
.map(|e| match e {
zir::ZirExpression::FieldElement(e) => e.clone(),
_ => unreachable!(),
})
.collect(),
box index.clone(),
index.clone(),
)
.into(),
zir::Type::Uint(bitwidth) => zir::UExpressionInner::Select(
zir::Type::Uint(_) => zir::UExpression::select(
a.into_iter()
.map(|e| match e {
zir::ZirExpression::Uint(e) => e.clone(),
_ => unreachable!(),
})
.collect(),
box index.clone(),
index.clone(),
)
.annotate(bitwidth)
.into(),
}
})
@ -987,12 +986,12 @@ fn fold_boolean_expression<'ast, T: Field>(
typed::BooleanExpression::FieldGt(box e1, box e2) => {
let e1 = f.fold_field_expression(statements_buffer, e1);
let e2 = f.fold_field_expression(statements_buffer, e2);
zir::BooleanExpression::FieldGt(box e1, box e2)
zir::BooleanExpression::FieldLt(box e2, box e1)
}
typed::BooleanExpression::FieldGe(box e1, box e2) => {
let e1 = f.fold_field_expression(statements_buffer, e1);
let e2 = f.fold_field_expression(statements_buffer, e2);
zir::BooleanExpression::FieldGe(box e1, box e2)
zir::BooleanExpression::FieldLe(box e2, box e1)
}
typed::BooleanExpression::UintLt(box e1, box e2) => {
let e1 = f.fold_uint_expression(statements_buffer, e1);
@ -1007,12 +1006,12 @@ fn fold_boolean_expression<'ast, T: Field>(
typed::BooleanExpression::UintGt(box e1, box e2) => {
let e1 = f.fold_uint_expression(statements_buffer, e1);
let e2 = f.fold_uint_expression(statements_buffer, e2);
zir::BooleanExpression::UintGt(box e1, box e2)
zir::BooleanExpression::UintLt(box e2, box e1)
}
typed::BooleanExpression::UintGe(box e1, box e2) => {
let e1 = f.fold_uint_expression(statements_buffer, e1);
let e2 = f.fold_uint_expression(statements_buffer, e2);
zir::BooleanExpression::UintGe(box e1, box e2)
zir::BooleanExpression::UintLe(box e2, box e1)
}
typed::BooleanExpression::Or(box e1, box e2) => {
let e1 = f.fold_boolean_expression(statements_buffer, e1);

View file

@ -55,22 +55,15 @@ fn force_no_reduce<T: Field>(e: UExpression<T>) -> UExpression<T> {
}
impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
fn fold_field_expression(
fn fold_select_expression<E: Expr<'ast, T> + Fold<'ast, T> + Select<'ast, T>>(
&mut self,
e: FieldElementExpression<'ast, T>,
) -> FieldElementExpression<'ast, T> {
match e {
FieldElementExpression::Select(a, box i) => {
let a = a
.into_iter()
.map(|e| self.fold_field_expression(e))
.collect();
let i = self.fold_uint_expression(i);
_: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> SelectOrExpression<'ast, T, E> {
let array = e.array.into_iter().map(|e| e.fold(self)).collect();
let index = e.index.fold(self);
FieldElementExpression::Select(a, box force_reduce(i))
}
_ => fold_field_expression(self, e),
}
SelectOrExpression::Select(SelectExpression::new(array, force_reduce(index)))
}
fn fold_boolean_expression(
@ -78,15 +71,6 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
e: BooleanExpression<'ast, T>,
) -> BooleanExpression<'ast, T> {
match e {
BooleanExpression::Select(a, box i) => {
let a = a
.into_iter()
.map(|e| self.fold_boolean_expression(e))
.collect();
let i = self.fold_uint_expression(i);
BooleanExpression::Select(a, box force_reduce(i))
}
BooleanExpression::UintEq(box left, box right) => {
let left = self.fold_uint_expression(left);
let right = self.fold_uint_expression(right);
@ -114,24 +98,6 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
BooleanExpression::UintLe(box left, box right)
}
BooleanExpression::UintGt(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::UintGt(box left, box right)
}
BooleanExpression::UintGe(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::UintGe(box left, box right)
}
e => fold_boolean_expression(self, e),
}
}
@ -161,12 +127,15 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
.cloned()
.unwrap_or_else(|| panic!("identifier should have been defined: {}", id)),
),
Select(values, box index) => {
Select(e) => {
let index = *e.index;
let array = e.array;
let index = self.fold_uint_expression(index);
let index = force_reduce(index);
let values: Vec<_> = values
let values: Vec<_> = array
.into_iter()
.map(|v| force_no_reduce(self.fold_uint_expression(v)))
.collect();
@ -389,10 +358,10 @@ impl<'ast, T: Field> Folder<'ast, T> for UintOptimizer<'ast, T> {
UExpression::right_shift(force_reduce(e), by).with_max(max)
}
Conditional(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);
Conditional(e) => {
let condition = self.fold_boolean_expression(*e.condition);
let consequence = e.consequence.fold(self);
let alternative = e.alternative.fold(self);
let consequence_max = consequence.metadata.clone().unwrap().max;
let alternative_max = alternative.metadata.clone().unwrap().max;

View file

@ -1,8 +1,18 @@
use std::collections::HashMap;
use std::fmt;
use zokrates_ast::zir::result_folder::fold_boolean_expression;
use zokrates_ast::zir::result_folder::fold_field_expression;
use zokrates_ast::zir::result_folder::fold_statement;
use zokrates_ast::zir::result_folder::fold_uint_expression_inner;
use zokrates_ast::zir::result_folder::ResultFold;
use zokrates_ast::zir::result_folder::ResultFolder;
use zokrates_ast::zir::types::UBitwidth;
use zokrates_ast::zir::Conditional;
use zokrates_ast::zir::ConditionalExpression;
use zokrates_ast::zir::ConditionalOrExpression;
use zokrates_ast::zir::Expr;
use zokrates_ast::zir::SelectExpression;
use zokrates_ast::zir::SelectOrExpression;
use zokrates_ast::zir::{
BooleanExpression, FieldElementExpression, Identifier, RuntimeError, UExpression,
UExpressionInner, ZirExpression, ZirProgram, ZirStatement,
@ -136,24 +146,6 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
}
_ => Ok(FieldElementExpression::Identifier(id)),
},
FieldElementExpression::Select(e, box index) => {
let index = self.fold_uint_expression(index)?;
let e: Vec<FieldElementExpression<'ast, T>> = e
.into_iter()
.map(|e| self.fold_field_expression(e))
.collect::<Result<_, _>>()?;
match index.into_inner() {
UExpressionInner::Value(v) => e
.get(v as usize)
.cloned()
.ok_or(Error::OutOfBounds(v as usize, e.len())),
i => Ok(FieldElementExpression::Select(
e,
box i.annotate(UBitwidth::B32),
)),
}
}
FieldElementExpression::Add(box e1, box e2) => {
match (
self.fold_field_expression(e1)?,
@ -237,28 +229,7 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
)),
}
}
FieldElementExpression::Conditional(
box condition,
box consequence,
box alternative,
) => {
let condition = self.fold_boolean_expression(condition)?;
let consequence = self.fold_field_expression(consequence)?;
let alternative = self.fold_field_expression(alternative)?;
match (condition, consequence, alternative) {
(_, consequence, alternative) if consequence == alternative => Ok(consequence),
(BooleanExpression::Value(true), consequence, _) => Ok(consequence),
(BooleanExpression::Value(false), _, alternative) => Ok(alternative),
(condition, consequence, alternative) => {
Ok(FieldElementExpression::Conditional(
box condition,
box consequence,
box alternative,
))
}
}
}
e => fold_field_expression(self, e),
}
}
@ -274,21 +245,6 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
}
_ => Ok(BooleanExpression::Identifier(id)),
},
BooleanExpression::Select(e, box index) => {
let index = self.fold_uint_expression(index)?;
let e: Vec<BooleanExpression<'ast, T>> = e
.into_iter()
.map(|e| self.fold_boolean_expression(e))
.collect::<Result<_, _>>()?;
match index.as_inner() {
UExpressionInner::Value(v) => e
.get(*v as usize)
.cloned()
.ok_or(Error::OutOfBounds(*v as usize, e.len())),
_ => Ok(BooleanExpression::Select(e, box index)),
}
}
BooleanExpression::FieldLt(box e1, box e2) => {
match (
self.fold_field_expression(e1)?,
@ -317,34 +273,6 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
(e1, e2) => Ok(BooleanExpression::FieldLe(box e1, box e2)),
}
}
BooleanExpression::FieldGe(box e1, box e2) => {
match (
self.fold_field_expression(e1)?,
self.fold_field_expression(e2)?,
) {
(FieldElementExpression::Number(n1), FieldElementExpression::Number(n2)) => {
Ok(BooleanExpression::Value(n1 >= n2))
}
(e1, e2) => Ok(BooleanExpression::FieldGe(box e1, box e2)),
}
}
BooleanExpression::FieldGt(box e1, box e2) => {
match (
self.fold_field_expression(e1)?,
self.fold_field_expression(e2)?,
) {
(FieldElementExpression::Number(n1), FieldElementExpression::Number(n2)) => {
Ok(BooleanExpression::Value(n1 > n2))
}
(_, FieldElementExpression::Number(c)) if c == T::max_value() => {
Ok(BooleanExpression::Value(false))
}
(FieldElementExpression::Number(c), _) if c == T::zero() => {
Ok(BooleanExpression::Value(false))
}
(e1, e2) => Ok(BooleanExpression::FieldGt(box e1, box e2)),
}
}
BooleanExpression::FieldEq(box e1, box e2) => {
match (
self.fold_field_expression(e1)?,
@ -384,28 +312,6 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
_ => Ok(BooleanExpression::UintLe(box e1, box e2)),
}
}
BooleanExpression::UintGe(box e1, box e2) => {
let e1 = self.fold_uint_expression(e1)?;
let e2 = self.fold_uint_expression(e2)?;
match (e1.as_inner(), e2.as_inner()) {
(UExpressionInner::Value(v1), UExpressionInner::Value(v2)) => {
Ok(BooleanExpression::Value(v1 >= v2))
}
_ => Ok(BooleanExpression::UintGe(box e1, box e2)),
}
}
BooleanExpression::UintGt(box e1, box e2) => {
let e1 = self.fold_uint_expression(e1)?;
let e2 = self.fold_uint_expression(e2)?;
match (e1.as_inner(), e2.as_inner()) {
(UExpressionInner::Value(v1), UExpressionInner::Value(v2)) => {
Ok(BooleanExpression::Value(v1 > v2))
}
_ => Ok(BooleanExpression::UintGt(box e1, box e2)),
}
}
BooleanExpression::UintEq(box e1, box e2) => {
let e1 = self.fold_uint_expression(e1)?;
let e2 = self.fold_uint_expression(e2)?;
@ -475,22 +381,33 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
BooleanExpression::Value(v) => Ok(BooleanExpression::Value(!v)),
e => Ok(BooleanExpression::Not(box e)),
},
BooleanExpression::Conditional(box condition, box consequence, box alternative) => {
let condition = self.fold_boolean_expression(condition)?;
let consequence = self.fold_boolean_expression(consequence)?;
let alternative = self.fold_boolean_expression(alternative)?;
e => fold_boolean_expression(self, e),
}
}
match (condition, consequence, alternative) {
(_, consequence, alternative) if consequence == alternative => Ok(consequence),
(BooleanExpression::Value(true), consequence, _) => Ok(consequence),
(BooleanExpression::Value(false), _, alternative) => Ok(alternative),
(condition, consequence, alternative) => Ok(BooleanExpression::Conditional(
box condition,
box consequence,
box alternative,
)),
}
}
fn fold_select_expression<
E: Clone + Expr<'ast, T> + ResultFold<'ast, T> + zokrates_ast::zir::Select<'ast, T>,
>(
&mut self,
_: &E::Ty,
e: SelectExpression<'ast, T, E>,
) -> Result<zokrates_ast::zir::SelectOrExpression<'ast, T, E>, Self::Error> {
let index = self.fold_uint_expression(*e.index)?;
let array = e
.array
.into_iter()
.map(|e| e.fold(self))
.collect::<Result<Vec<_>, _>>()?;
match index.as_inner() {
UExpressionInner::Value(v) => array
.get(*v as usize)
.cloned()
.ok_or(Error::OutOfBounds(*v as usize, array.len()))
.map(|e| SelectOrExpression::Expression(e.into_inner())),
_ => Ok(SelectOrExpression::Expression(
E::select(array, index).into_inner(),
)),
}
}
@ -505,22 +422,6 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
Some(ZirExpression::Uint(e)) => Ok(e.as_inner().clone()),
_ => Ok(UExpressionInner::Identifier(id)),
},
UExpressionInner::Select(e, box index) => {
let index = self.fold_uint_expression(index)?;
let e: Vec<UExpression<'ast, T>> = e
.into_iter()
.map(|e| self.fold_uint_expression(e))
.collect::<Result<_, _>>()?;
match index.into_inner() {
UExpressionInner::Value(v) => e
.get(v as usize)
.cloned()
.ok_or(Error::OutOfBounds(v as usize, e.len()))
.map(|e| e.into_inner()),
i => Ok(UExpressionInner::Select(e, box i.annotate(UBitwidth::B32))),
}
}
UExpressionInner::Add(box e1, box e2) => {
let e1 = self.fold_uint_expression(e1)?;
let e2 = self.fold_uint_expression(e2)?;
@ -687,22 +588,34 @@ impl<'ast, T: Field> ResultFolder<'ast, T> for ZirPropagator<'ast, T> {
e => Ok(UExpressionInner::Not(box e.annotate(bitwidth))),
}
}
UExpressionInner::Conditional(box condition, box consequence, box alternative) => {
let condition = self.fold_boolean_expression(condition)?;
let consequence = self.fold_uint_expression(consequence)?.into_inner();
let alternative = self.fold_uint_expression(alternative)?.into_inner();
e => fold_uint_expression_inner(self, bitwidth, e),
}
}
match (condition, consequence, alternative) {
(_, consequence, alternative) if consequence == alternative => Ok(consequence),
(BooleanExpression::Value(true), consequence, _) => Ok(consequence),
(BooleanExpression::Value(false), _, alternative) => Ok(alternative),
(condition, consequence, alternative) => Ok(UExpressionInner::Conditional(
box condition,
box consequence.annotate(bitwidth),
box alternative.annotate(bitwidth),
)),
}
}
fn fold_conditional_expression<
E: Expr<'ast, T> + ResultFold<'ast, T> + Conditional<'ast, T>,
>(
&mut self,
_: &E::Ty,
e: ConditionalExpression<'ast, T, E>,
) -> Result<ConditionalOrExpression<'ast, T, E>, Self::Error> {
let condition = self.fold_boolean_expression(*e.condition)?;
let consequence = e.consequence.fold(self)?;
let alternative = e.alternative.fold(self)?;
match (condition, consequence, alternative) {
(_, consequence, alternative) if consequence == alternative => Ok(
ConditionalOrExpression::Expression(consequence.into_inner()),
),
(BooleanExpression::Value(true), consequence, _) => Ok(
ConditionalOrExpression::Expression(consequence.into_inner()),
),
(BooleanExpression::Value(false), _, alternative) => Ok(
ConditionalOrExpression::Expression(alternative.into_inner()),
),
(condition, consequence, alternative) => Ok(ConditionalOrExpression::Conditional(
ConditionalExpression::new(condition, consequence, alternative),
)),
}
}
}
@ -754,6 +667,8 @@ mod tests {
#[cfg(test)]
mod field {
use zokrates_ast::zir::Select;
use super::*;
#[test]
@ -761,23 +676,23 @@ mod tests {
let mut propagator = ZirPropagator::default();
assert_eq!(
propagator.fold_field_expression(FieldElementExpression::Select(
propagator.fold_field_expression(FieldElementExpression::select(
vec![
FieldElementExpression::Number(Bn128Field::from(1)),
FieldElementExpression::Number(Bn128Field::from(2)),
],
box UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(1).annotate(UBitwidth::B32),
)),
Ok(FieldElementExpression::Number(Bn128Field::from(2)))
);
assert_eq!(
propagator.fold_field_expression(FieldElementExpression::Select(
propagator.fold_field_expression(FieldElementExpression::select(
vec![
FieldElementExpression::Number(Bn128Field::from(1)),
FieldElementExpression::Number(Bn128Field::from(2)),
],
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
UExpressionInner::Value(3).annotate(UBitwidth::B32),
)),
Err(Error::OutOfBounds(3, 2))
);
@ -923,28 +838,28 @@ mod tests {
let mut propagator = ZirPropagator::default();
assert_eq!(
propagator.fold_field_expression(FieldElementExpression::Conditional(
box BooleanExpression::Value(true),
box FieldElementExpression::Number(Bn128Field::from(1)),
box FieldElementExpression::Number(Bn128Field::from(2)),
propagator.fold_field_expression(FieldElementExpression::conditional(
BooleanExpression::Value(true),
FieldElementExpression::Number(Bn128Field::from(1)),
FieldElementExpression::Number(Bn128Field::from(2)),
)),
Ok(FieldElementExpression::Number(Bn128Field::from(1)))
);
assert_eq!(
propagator.fold_field_expression(FieldElementExpression::Conditional(
box BooleanExpression::Value(false),
box FieldElementExpression::Number(Bn128Field::from(1)),
box FieldElementExpression::Number(Bn128Field::from(2)),
propagator.fold_field_expression(FieldElementExpression::conditional(
BooleanExpression::Value(false),
FieldElementExpression::Number(Bn128Field::from(1)),
FieldElementExpression::Number(Bn128Field::from(2)),
)),
Ok(FieldElementExpression::Number(Bn128Field::from(2)))
);
assert_eq!(
propagator.fold_field_expression(FieldElementExpression::Conditional(
box BooleanExpression::Identifier("a".into()),
box FieldElementExpression::Number(Bn128Field::from(2)),
box FieldElementExpression::Number(Bn128Field::from(2)),
propagator.fold_field_expression(FieldElementExpression::conditional(
BooleanExpression::Identifier("a".into()),
FieldElementExpression::Number(Bn128Field::from(2)),
FieldElementExpression::Number(Bn128Field::from(2)),
)),
Ok(FieldElementExpression::Number(Bn128Field::from(2)))
);
@ -953,6 +868,8 @@ mod tests {
#[cfg(test)]
mod bool {
use zokrates_ast::zir::Select;
use super::*;
#[test]
@ -960,23 +877,23 @@ mod tests {
let mut propagator = ZirPropagator::<Bn128Field>::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::Select(
propagator.fold_boolean_expression(BooleanExpression::select(
vec![
BooleanExpression::Value(false),
BooleanExpression::Value(true),
],
box UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(1).annotate(UBitwidth::B32),
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::Select(
propagator.fold_boolean_expression(BooleanExpression::select(
vec![
BooleanExpression::Value(false),
BooleanExpression::Value(true),
],
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
UExpressionInner::Value(3).annotate(UBitwidth::B32),
)),
Err(Error::OutOfBounds(3, 2))
);
@ -1040,64 +957,6 @@ mod tests {
);
}
#[test]
fn field_ge() {
let mut propagator = ZirPropagator::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGe(
box FieldElementExpression::Number(Bn128Field::from(3)),
box FieldElementExpression::Number(Bn128Field::from(2)),
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGe(
box FieldElementExpression::Number(Bn128Field::from(3)),
box FieldElementExpression::Number(Bn128Field::from(3)),
)),
Ok(BooleanExpression::Value(true))
);
}
#[test]
fn field_gt() {
let mut propagator = ZirPropagator::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGt(
box FieldElementExpression::Number(Bn128Field::from(3)),
box FieldElementExpression::Number(Bn128Field::from(2)),
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGt(
box FieldElementExpression::Number(Bn128Field::from(3)),
box FieldElementExpression::Number(Bn128Field::from(3)),
)),
Ok(BooleanExpression::Value(false))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGt(
box FieldElementExpression::Number(Bn128Field::from(0)),
box FieldElementExpression::Identifier("a".into()),
)),
Ok(BooleanExpression::Value(false))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::FieldGt(
box FieldElementExpression::Identifier("a".into()),
box FieldElementExpression::Number(Bn128Field::max_value()),
)),
Ok(BooleanExpression::Value(false))
);
}
#[test]
fn field_eq() {
let mut propagator = ZirPropagator::default();
@ -1161,48 +1020,6 @@ mod tests {
);
}
#[test]
fn uint_ge() {
let mut propagator = ZirPropagator::<Bn128Field>::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::UintGe(
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::UintGe(
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
)),
Ok(BooleanExpression::Value(true))
);
}
#[test]
fn uint_gt() {
let mut propagator = ZirPropagator::<Bn128Field>::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::UintGt(
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::UintGt(
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
)),
Ok(BooleanExpression::Value(false))
);
}
#[test]
fn uint_eq() {
let mut propagator = ZirPropagator::<Bn128Field>::default();
@ -1327,28 +1144,28 @@ mod tests {
let mut propagator = ZirPropagator::<Bn128Field>::default();
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::Conditional(
box BooleanExpression::Value(true),
box BooleanExpression::Value(true),
box BooleanExpression::Value(false)
propagator.fold_boolean_expression(BooleanExpression::conditional(
BooleanExpression::Value(true),
BooleanExpression::Value(true),
BooleanExpression::Value(false)
)),
Ok(BooleanExpression::Value(true))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::Conditional(
box BooleanExpression::Value(false),
box BooleanExpression::Value(true),
box BooleanExpression::Value(false)
propagator.fold_boolean_expression(BooleanExpression::conditional(
BooleanExpression::Value(false),
BooleanExpression::Value(true),
BooleanExpression::Value(false)
)),
Ok(BooleanExpression::Value(false))
);
assert_eq!(
propagator.fold_boolean_expression(BooleanExpression::Conditional(
box BooleanExpression::Identifier("a".into()),
box BooleanExpression::Value(true),
box BooleanExpression::Value(true)
propagator.fold_boolean_expression(BooleanExpression::conditional(
BooleanExpression::Identifier("a".into()),
BooleanExpression::Value(true),
BooleanExpression::Value(true)
)),
Ok(BooleanExpression::Value(true))
);
@ -1366,13 +1183,14 @@ mod tests {
assert_eq!(
propagator.fold_uint_expression_inner(
UBitwidth::B32,
UExpressionInner::Select(
UExpression::select(
vec![
UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
],
box UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(1).annotate(UBitwidth::B32),
)
.into_inner()
),
Ok(UExpressionInner::Value(2))
);
@ -1380,13 +1198,14 @@ mod tests {
assert_eq!(
propagator.fold_uint_expression_inner(
UBitwidth::B32,
UExpressionInner::Select(
UExpression::select(
vec![
UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
],
box UExpressionInner::Value(3).annotate(UBitwidth::B32),
UExpressionInner::Value(3).annotate(UBitwidth::B32),
)
.into_inner()
),
Err(Error::OutOfBounds(3, 2))
);
@ -1752,11 +1571,12 @@ mod tests {
assert_eq!(
propagator.fold_uint_expression_inner(
UBitwidth::B32,
UExpressionInner::Conditional(
box BooleanExpression::Value(true),
box UExpressionInner::Value(1).annotate(UBitwidth::B32),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
UExpression::conditional(
BooleanExpression::Value(true),
UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
)
.into_inner()
),
Ok(UExpressionInner::Value(1))
);
@ -1764,11 +1584,12 @@ mod tests {
assert_eq!(
propagator.fold_uint_expression_inner(
UBitwidth::B32,
UExpressionInner::Conditional(
box BooleanExpression::Value(false),
box UExpressionInner::Value(1).annotate(UBitwidth::B32),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
UExpression::conditional(
BooleanExpression::Value(false),
UExpressionInner::Value(1).annotate(UBitwidth::B32),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
)
.into_inner()
),
Ok(UExpressionInner::Value(2))
);
@ -1776,11 +1597,12 @@ mod tests {
assert_eq!(
propagator.fold_uint_expression_inner(
UBitwidth::B32,
UExpressionInner::Conditional(
box BooleanExpression::Identifier("a".into()),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
box UExpressionInner::Value(2).annotate(UBitwidth::B32),
UExpression::conditional(
BooleanExpression::Identifier("a".into()),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
UExpressionInner::Value(2).annotate(UBitwidth::B32),
)
.into_inner()
),
Ok(UExpressionInner::Value(2))
);

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_interpreter"
version = "0.1.0"
version = "0.1.1"
edition = "2021"
[features]

View file

@ -106,6 +106,8 @@ impl Interpreter {
}
writeln!(log_stream).map_err(|_| Error::LogStream)?;
log_stream.flush().map_err(|_| Error::LogStream)?;
}
}
}

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_js"
version = "1.1.0"
version = "1.1.2"
authors = ["Darko Macesic"]
edition = "2018"
@ -13,14 +13,21 @@ serde = { version = "^1.0.59", features = ["derive"] }
serde_json = { version = "1.0", features = ["preserve_order"] }
wasm-bindgen = { version = "0.2.46", features = ["serde-serialize"] }
typed-arena = "1.4.1"
zokrates_core = { path = "../zokrates_core", default-features = false, features = ["ark"] }
lazy_static = "1.4.0"
zokrates_core = { path = "../zokrates_core", default-features = false, features = ["ark", "bellman"] }
zokrates_ark = { path = "../zokrates_ark", default-features = false}
zokrates_common = { path = "../zokrates_common", default-features = false, features = ["ark"] }
zokrates_bellman = { path = "../zokrates_bellman", default-features = false}
zokrates_common = { path = "../zokrates_common", default-features = false, features = ["ark", "bellman"] }
zokrates_proof_systems = { path = "../zokrates_proof_systems", default-features = false }
zokrates_ast = { path = "../zokrates_ast", default-features = false, features = ["ark"] }
zokrates_interpreter = { path = "../zokrates_interpreter", default-features = false, features = ["ark"] }
zokrates_ast = { path = "../zokrates_ast", default-features = false, features = ["ark", "bellman"] }
zokrates_interpreter = { path = "../zokrates_interpreter", default-features = false, features = ["ark", "bellman"] }
zokrates_field = { path = "../zokrates_field", default-features = false }
zokrates_abi = { path = "../zokrates_abi", default-features = false, features = ["ark"] }
zokrates_abi = { path = "../zokrates_abi", default-features = false, features = ["ark", "bellman"] }
zokrates_circom = { path = "../zokrates_circom" }
console_error_panic_hook = "0.1.6"
indexmap = "~1.6.2" # see https://github.com/rustwasm/wasm-bindgen/issues/2770#issuecomment-1041102532
indexmap = "~1.6.2" # see https://github.com/rustwasm/wasm-bindgen/issues/2770#issuecomment-1041102532
[build-dependencies]
json = "0.12.4"
walkdir = "2.3.2"
toml = "0.5.9"

46
zokrates_js/build.rs Normal file
View file

@ -0,0 +1,46 @@
use std::path::Path;
use std::{env, fs};
use walkdir::WalkDir;
fn main() {
export_stdlib();
export_metadata();
}
fn export_stdlib() {
let root = "../zokrates_stdlib/stdlib";
let mut stdlib = json::JsonValue::new_object();
for entry in WalkDir::new(root)
.into_iter()
.map(Result::unwrap)
.filter(|e| !e.file_type().is_dir())
{
let path: &Path = entry.path();
let source = fs::read_to_string(path).unwrap();
stdlib
.insert(path.strip_prefix(root).unwrap().to_str().unwrap(), source)
.unwrap();
}
let out_dir = env::var_os("OUT_DIR").unwrap();
let dest_path = Path::new(&out_dir).join("stdlib.json");
fs::write(dest_path, stdlib.dump()).unwrap();
}
fn export_metadata() {
let path = "../zokrates_cli/Cargo.toml";
let config: toml::Value = toml::from_str(&fs::read_to_string(path).unwrap()).unwrap();
let mut metadata = json::JsonValue::new_object();
metadata
.insert("version", config["package"]["version"].as_str().unwrap())
.unwrap();
fs::write(
"metadata.js",
format!("module.exports = {}", metadata.dump()),
)
.unwrap();
}

View file

@ -1,41 +0,0 @@
const gulp = require("gulp");
const dree = require("dree");
const fs = require("fs");
const path = require("path");
const toml = require("toml");
const stdlibRoot = "../zokrates_stdlib/stdlib";
const options = {
extensions: ["zok"],
};
// Serializes the standard library directory tree to a js file.
gulp.task("stdlib", (done) => {
var stdlib = {};
dree.scan(stdlibRoot, options, function (file) {
const content = fs.readFileSync(file.path).toString();
stdlib[file.relativePath] = content;
});
fs.writeFileSync(
path.resolve(__dirname, "stdlib.js"),
`module.exports = ${JSON.stringify(stdlib)}`
);
done();
});
gulp.task("metadata", (done) => {
const config = toml.parse(
fs.readFileSync("../zokrates_cli/Cargo.toml").toString()
);
const metadata = JSON.stringify({
version: config.package.version,
});
fs.writeFileSync(
path.resolve(__dirname, "metadata.js"),
`module.exports = ${metadata}`
);
done();
});
gulp.task("setup", gulp.parallel("stdlib", "metadata"));

View file

@ -1,4 +1,5 @@
declare module "zokrates-js" {
export type Backend = "ark" | "bellman";
export type Curve = "bn128" | "bls12_381" | "bls12_377" | "bw6_761";
export type Scheme = "g16" | "gm17" | "marlin";
@ -12,6 +13,7 @@ declare module "zokrates-js" {
export interface CompileConfig {
isolate_branches?: boolean;
debug?: boolean;
}
export interface CompileOptions {
@ -32,8 +34,11 @@ declare module "zokrates-js" {
location: string;
}
export type LogCallback = (log: string) => void;
export interface ComputeOptions {
snarkjs?: boolean;
logCallback?: LogCallback;
}
export interface ComputationResult {
@ -63,6 +68,7 @@ declare module "zokrates-js" {
}
export type Options = {
backend: Backend;
scheme: Scheme;
curve: Curve;
};

View file

@ -1,10 +1,9 @@
import wrapper from "./wrapper.js";
import stdlib from "./stdlib.js";
import lib from "./lib.js";
import metadata from "./metadata.js";
const initialize = async () => {
const zokrates = await import("./pkg/index.js");
return wrapper({ zokrates, stdlib });
const pkg = await import("./pkg/index.js");
return lib(pkg);
};
export { initialize, metadata };
export { initialize, metadata };

View file

@ -1,38 +1,4 @@
const 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("/");
};
const getImportPath = (currentLocation, importLocation) => {
let path = getAbsolutePath(currentLocation, importLocation);
const extension = path.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;
};
module.exports = (pkg) => {
const defaultProvider = {
compile: (source, compileOptions = {}) => {
var {
@ -45,31 +11,33 @@ module.exports = (dep) => {
config = { snarkjs, ...config };
const callback = (currentLocation, importLocation) => {
return (
resolveFromStdlib(currentLocation, importLocation) ||
resolveCallback(currentLocation, importLocation)
);
};
const ptr = zokrates.compile(source, location, callback, config, curve);
return Object.assign(
const ptr = pkg.compile(source, location, resolveCallback, config, curve);
const result = Object.assign(
{
program: ptr.program(),
abi: ptr.abi(),
},
snarkjs ? { snarkjs: { program: ptr.snarkjs_program() } } : {}
);
ptr.free();
return result;
},
computeWitness: (input, args, computeOptions = {}) => {
const { program, abi } =
input instanceof Uint8Array ? { program: input, abi: null } : input;
const { snarkjs = false } = computeOptions;
const ptr = zokrates.compute_witness(program, abi, JSON.stringify(args), {
snarkjs: snarkjs,
});
const { snarkjs = false, logCallback = console.log } = computeOptions;
const ptr = pkg.compute_witness(
program,
abi,
JSON.stringify(args),
{
snarkjs: snarkjs,
},
logCallback
);
return Object.assign(
const result = Object.assign(
{
witness: ptr.witness(),
output: ptr.output(),
@ -82,28 +50,31 @@ module.exports = (dep) => {
}
: {}
);
ptr.free();
return result;
},
setup: (program, options) => {
return zokrates.setup(program, options);
return pkg.setup(program, options);
},
universalSetup: (curve, size) => {
return zokrates.universal_setup(curve, size);
return pkg.universal_setup(curve, size);
},
setupWithSrs: (srs, program, options) => {
return zokrates.setup_with_srs(srs, program, options);
return pkg.setup_with_srs(srs, program, options);
},
generateProof: (program, witness, provingKey, options) => {
return zokrates.generate_proof(program, witness, provingKey, options);
return pkg.generate_proof(program, witness, provingKey, options);
},
verify: (vk, proof) => {
return zokrates.verify(vk, proof);
verify: (vk, proof, options) => {
return pkg.verify(vk, proof, options);
},
exportSolidityVerifier: (vk) => {
return zokrates.export_solidity_verifier(vk);
return pkg.export_solidity_verifier(vk);
},
utils: {
formatProof: (proof) => {
return zokrates.format_proof(proof);
return pkg.format_proof(proof);
},
},
};
@ -125,7 +96,7 @@ module.exports = (dep) => {
defaultProvider.setupWithSrs(srs, program, options),
generateProof: (program, witness, provingKey) =>
defaultProvider.generateProof(program, witness, provingKey, options),
verify: (vk, proof) => defaultProvider.verify(vk, proof),
verify: (vk, proof) => defaultProvider.verify(vk, proof, options),
exportSolidityVerifier: (vk) =>
defaultProvider.exportSolidityVerifier(vk),
utils: {
@ -135,6 +106,6 @@ module.exports = (dep) => {
};
return {
...withOptions({ scheme: "g16", curve: "bn128" }),
...withOptions({ backend: "ark", scheme: "g16", curve: "bn128" }),
};
};

View file

@ -1,12 +1,8 @@
const wrapper = require("../wrapper.js");
const stdlib = require("../stdlib.js");
const lib = require("../lib.js");
const metadata = require("../metadata.js");
const initialize = async () => {
return wrapper({
zokrates: require("./pkg/index.js"),
stdlib,
});
return lib(require("./pkg/index.js"));
};
module.exports = { initialize, metadata };

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "zokrates-js",
"version": "1.1.0",
"version": "1.1.2",
"module": "index.js",
"main": "node/index.js",
"description": "JavaScript bindings for ZoKrates",
@ -19,44 +19,34 @@
"pkg",
"index.js",
"index.d.ts",
"wrapper.js",
"stdlib.js",
"lib.js",
"metadata.js"
],
"types": "index.d.ts",
"exports": {
"import": "./index.js",
"require": "./node/index.js"
"node": "./node/index.js",
"default": "./index.js"
},
"scripts": {
"wasm-pack": "wasm-pack build --out-name index",
"setup": "npm install && gulp setup",
"prebuild": "npm run setup",
"prebuild": "npm install",
"build": "npm run build:bundler && npm run build:node",
"prebuild:dev": "npm run setup",
"build:dev": "npm run build:bundler:dev && npm run build:node:dev",
"build:bundler": "rimraf pkg && npm run wasm-pack -- --target bundler --release && npm run clean-pkg",
"build:bundler:dev": "rimraf pkg && npm run wasm-pack -- --target bundler --dev && npm run clean-pkg",
"build:node": "rimraf node/pkg && npm run wasm-pack -- --target nodejs -d node/pkg --release && npm run clean-node-pkg",
"build:node:dev": "rimraf node/pkg && npm run wasm-pack -- --target nodejs -d node/pkg --dev && npm run clean-node-pkg",
"clean-pkg": "rimraf pkg/README.md pkg/.gitignore",
"clean-node-pkg": "rimraf node/pkg/README.md node/pkg/.gitignore",
"pretest": "npm run setup && npm run build:node:dev",
"clean-pkg": "rimraf pkg/README.md pkg/.gitignore pkg/package.json pkg/*.d.ts",
"clean-node-pkg": "rimraf node/pkg/README.md node/pkg/.gitignore node/pkg/package.json node/pkg/*.d.ts",
"pretest": "npm run build:node:dev",
"test": "npm run run-tests",
"run-tests": "mocha --timeout 100000 --require esm --recursive tests"
"run-tests": "mocha --timeout 100000 --recursive tests"
},
"devDependencies": {
"dree": "^2.6.1",
"esm": "^3.2.25",
"gulp": "^4.0.2",
"gulp-cli": "^2.3.0",
"mocha": "^9.2.0",
"rimraf": "^3.0.2",
"serve": "^11.3.2",
"snarkjs": "^0.4.19",
"text-encoding": "^0.7.0",
"toml": "^3.0.0",
"wasm-pack": "^0.10.2"
},
"dependencies": {}
}
}
}

View file

@ -1,8 +1,14 @@
mod util;
#[macro_use]
extern crate lazy_static;
use crate::util::normalize_path;
use serde::{Deserialize, Serialize};
use serde_json::to_string_pretty;
use std::convert::TryFrom;
use std::io::Cursor;
use std::path::PathBuf;
use std::io::{Cursor, Write};
use std::path::{Component, PathBuf};
use typed_arena::Arena;
use wasm_bindgen::prelude::*;
use zokrates_abi::{parse_strict, Decode, Encode, Inputs};
@ -11,8 +17,9 @@ use zokrates_ast::ir;
use zokrates_ast::ir::ProgEnum;
use zokrates_ast::typed::abi::Abi;
use zokrates_ast::typed::types::{ConcreteSignature, ConcreteType, GTupleType};
use zokrates_bellman::Bellman;
use zokrates_circom::{write_r1cs, write_witness};
use zokrates_common::helpers::{CurveParameter, SchemeParameter};
use zokrates_common::helpers::{BackendParameter, CurveParameter, SchemeParameter};
use zokrates_common::Resolver;
use zokrates_core::compile::{
compile as core_compile, CompilationArtifacts, CompileConfig, CompileError,
@ -26,6 +33,11 @@ use zokrates_proof_systems::{
UniversalBackend, UniversalScheme, GM17,
};
lazy_static! {
static ref STDLIB: serde_json::Value =
serde_json::from_str(include_str!(concat!(env!("OUT_DIR"), "/stdlib.json"))).unwrap();
}
#[wasm_bindgen]
pub struct CompilationResult {
program: Vec<u8>,
@ -99,29 +111,107 @@ impl<'a> Resolver<Error> for JsResolver<'a> {
current_location: PathBuf,
import_location: PathBuf,
) -> Result<(String, PathBuf), Error> {
let value = self
.callback
.call2(
let base: PathBuf = match import_location.components().next() {
Some(Component::CurDir) | Some(Component::ParentDir) => {
current_location.parent().unwrap().into()
}
_ => PathBuf::default(),
};
let path = base.join(import_location.clone()).with_extension("zok");
match path.components().next() {
Some(Component::Normal(_)) => {
let path_normalized = normalize_path(path);
let source = STDLIB
.get(&path_normalized.to_str().unwrap())
.ok_or_else(|| {
Error::new(format!(
"module `{}` not found in stdlib",
import_location.display()
))
})?
.as_str()
.unwrap();
Ok((source.to_owned(), path_normalized))
}
_ => {
let value = self
.callback
.call2(
&JsValue::UNDEFINED,
&current_location.to_str().unwrap().into(),
&import_location.to_str().unwrap().into(),
)
.map_err(|_| {
Error::new(format!(
"could not resolve module `{}`",
import_location.display()
))
})?;
if value.is_null() || value.is_undefined() {
return Err(Error::new(format!(
"could not resolve module `{}`",
import_location.display()
)));
}
let result: serde_json::Value = value.into_serde().unwrap();
let source = result
.get("source")
.ok_or_else(|| Error::new("missing field `source`"))?
.as_str()
.ok_or_else(|| {
Error::new("invalid type for field `source`, should be a string")
})?;
let location = result
.get("location")
.ok_or_else(|| Error::new("missing field `location`"))?
.as_str()
.ok_or_else(|| {
Error::new("invalid type for field `location`, should be a string")
})?;
Ok((source.to_owned(), PathBuf::from(location.to_owned())))
}
}
}
}
pub struct LogWriter<'a> {
buf: Vec<u8>,
callback: &'a js_sys::Function,
}
impl<'a> LogWriter<'a> {
pub fn new(callback: &'a js_sys::Function) -> Self {
Self {
buf: Vec::default(),
callback,
}
}
}
impl<'a> Write for LogWriter<'a> {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.callback
.call1(
&JsValue::UNDEFINED,
&current_location.to_str().unwrap().into(),
&import_location.to_str().unwrap().into(),
&JsValue::from_str(
std::str::from_utf8(&self.buf.as_slice()[..self.buf.len() - 1]).unwrap(),
),
)
.map_err(|_| {
Error::new(format!(
"Could not resolve `{}`: error thrown in resolve callback",
import_location.display()
))
std::io::Error::new(std::io::ErrorKind::Other, "unable to call log callback")
})?;
if value.is_null() || value.is_undefined() {
Err(Error::new(format!(
"Could not resolve `{}`",
import_location.display()
)))
} else {
let result: ResolverResult = value.into_serde().unwrap();
Ok((result.source, PathBuf::from(result.location)))
}
self.buf.clear();
Ok(())
}
}
@ -185,6 +275,7 @@ mod internal {
abi: JsValue,
args: JsValue,
config: JsValue,
log_callback: &js_sys::Function,
) -> Result<ComputationResult, JsValue> {
let input = args.as_string().unwrap();
@ -223,8 +314,9 @@ mod internal {
let public_inputs = program.public_inputs();
let mut writer = LogWriter::new(log_callback);
let witness = interpreter
.execute(program, &inputs.encode())
.execute_with_log_stream(program, &inputs.encode(), &mut writer)
.map_err(|err| JsValue::from_str(&format!("Execution failed: {}", err)))?;
let return_values: serde_json::Value =
@ -371,15 +463,16 @@ pub fn compute_witness(
abi: JsValue,
args: JsValue,
config: JsValue,
log_callback: &js_sys::Function,
) -> Result<ComputationResult, JsValue> {
let prog = ir::ProgEnum::deserialize(program)
.map_err(|err| JsValue::from_str(&err))?
.collect();
match prog {
ProgEnum::Bn128Program(p) => internal::compute::<_>(p, abi, args, config),
ProgEnum::Bls12_381Program(p) => internal::compute::<_>(p, abi, args, config),
ProgEnum::Bls12_377Program(p) => internal::compute::<_>(p, abi, args, config),
ProgEnum::Bw6_761Program(p) => internal::compute::<_>(p, abi, args, config),
ProgEnum::Bn128Program(p) => internal::compute::<_>(p, abi, args, config, log_callback),
ProgEnum::Bls12_381Program(p) => internal::compute::<_>(p, abi, args, config, log_callback),
ProgEnum::Bls12_377Program(p) => internal::compute::<_>(p, abi, args, config, log_callback),
ProgEnum::Bw6_761Program(p) => internal::compute::<_>(p, abi, args, config, log_callback),
}
}
@ -388,6 +481,7 @@ pub fn export_solidity_verifier(vk: JsValue) -> Result<JsValue, JsValue> {
let vk: serde_json::Value = vk
.into_serde()
.map_err(|e| JsValue::from_str(&e.to_string()))?;
let curve = CurveParameter::try_from(
vk["curve"]
.as_str()
@ -419,6 +513,13 @@ pub fn export_solidity_verifier(vk: JsValue) -> Result<JsValue, JsValue> {
pub fn setup(program: &[u8], options: JsValue) -> Result<JsValue, JsValue> {
let options: serde_json::Value = options.into_serde().unwrap();
let backend = BackendParameter::try_from(
options["backend"]
.as_str()
.ok_or_else(|| JsValue::from_str("Invalid options: missing field `backend`"))?,
)
.map_err(|e| JsValue::from_str(&e))?;
let scheme = SchemeParameter::try_from(
options["scheme"]
.as_str()
@ -430,20 +531,27 @@ pub fn setup(program: &[u8], options: JsValue) -> Result<JsValue, JsValue> {
.map_err(|err| JsValue::from_str(&err))?
.collect();
match scheme {
SchemeParameter::G16 => match prog {
match (backend, scheme) {
(BackendParameter::Bellman, SchemeParameter::G16) => match prog {
ProgEnum::Bn128Program(p) => Ok(internal::setup_non_universal::<_, G16, Bellman>(p)),
ProgEnum::Bls12_381Program(_) => Err(JsValue::from_str(
"Not supported: https://github.com/Zokrates/ZoKrates/issues/1200",
)),
_ => Err(JsValue::from_str("Not supported")),
},
(BackendParameter::Ark, SchemeParameter::G16) => match prog {
ProgEnum::Bn128Program(p) => Ok(internal::setup_non_universal::<_, G16, Ark>(p)),
ProgEnum::Bls12_381Program(p) => Ok(internal::setup_non_universal::<_, G16, Ark>(p)),
ProgEnum::Bls12_377Program(p) => Ok(internal::setup_non_universal::<_, G16, Ark>(p)),
ProgEnum::Bw6_761Program(p) => Ok(internal::setup_non_universal::<_, G16, Ark>(p)),
},
SchemeParameter::GM17 => match prog {
(BackendParameter::Ark, SchemeParameter::GM17) => match prog {
ProgEnum::Bn128Program(p) => Ok(internal::setup_non_universal::<_, GM17, Ark>(p)),
ProgEnum::Bls12_381Program(p) => Ok(internal::setup_non_universal::<_, GM17, Ark>(p)),
ProgEnum::Bls12_377Program(p) => Ok(internal::setup_non_universal::<_, GM17, Ark>(p)),
ProgEnum::Bw6_761Program(p) => Ok(internal::setup_non_universal::<_, GM17, Ark>(p)),
},
_ => Err(JsValue::from_str("Unsupported scheme")),
_ => Err(JsValue::from_str("Unsupported options")),
}
}
@ -507,6 +615,13 @@ pub fn generate_proof(
) -> Result<JsValue, JsValue> {
let options: serde_json::Value = options.into_serde().unwrap();
let backend = BackendParameter::try_from(
options["backend"]
.as_str()
.ok_or_else(|| JsValue::from_str("Invalid options: missing field `backend`"))?,
)
.map_err(|e| JsValue::from_str(&e))?;
let scheme = SchemeParameter::try_from(
options["scheme"]
.as_str()
@ -518,8 +633,17 @@ pub fn generate_proof(
.map_err(|err| JsValue::from_str(&err))?
.collect();
match scheme {
SchemeParameter::G16 => match prog {
match (backend, scheme) {
(BackendParameter::Bellman, SchemeParameter::G16) => match prog {
ProgEnum::Bn128Program(p) => {
internal::generate_proof::<_, G16, Bellman>(p, witness, pk)
}
ProgEnum::Bls12_381Program(_) => Err(JsValue::from_str(
"Not supported: https://github.com/Zokrates/ZoKrates/issues/1200",
)),
_ => Err(JsValue::from_str("Not supported")),
},
(BackendParameter::Ark, SchemeParameter::G16) => match prog {
ProgEnum::Bn128Program(p) => internal::generate_proof::<_, G16, Ark>(p, witness, pk),
ProgEnum::Bls12_381Program(p) => {
internal::generate_proof::<_, G16, Ark>(p, witness, pk)
@ -529,7 +653,7 @@ pub fn generate_proof(
}
ProgEnum::Bw6_761Program(p) => internal::generate_proof::<_, G16, Ark>(p, witness, pk),
},
SchemeParameter::GM17 => match prog {
(BackendParameter::Ark, SchemeParameter::GM17) => match prog {
ProgEnum::Bn128Program(p) => internal::generate_proof::<_, GM17, Ark>(p, witness, pk),
ProgEnum::Bls12_381Program(p) => {
internal::generate_proof::<_, GM17, Ark>(p, witness, pk)
@ -539,7 +663,7 @@ pub fn generate_proof(
}
ProgEnum::Bw6_761Program(p) => internal::generate_proof::<_, GM17, Ark>(p, witness, pk),
},
SchemeParameter::MARLIN => match prog {
(BackendParameter::Ark, SchemeParameter::MARLIN) => match prog {
ProgEnum::Bn128Program(p) => internal::generate_proof::<_, Marlin, Ark>(p, witness, pk),
ProgEnum::Bls12_381Program(p) => {
internal::generate_proof::<_, Marlin, Ark>(p, witness, pk)
@ -551,11 +675,20 @@ pub fn generate_proof(
internal::generate_proof::<_, Marlin, Ark>(p, witness, pk)
}
},
_ => Err(JsValue::from_str("Unsupported options")),
}
}
#[wasm_bindgen]
pub fn verify(vk: JsValue, proof: JsValue) -> Result<JsValue, JsValue> {
pub fn verify(vk: JsValue, proof: JsValue, options: JsValue) -> Result<JsValue, JsValue> {
let options: serde_json::Value = options.into_serde().unwrap();
let backend = BackendParameter::try_from(
options["backend"]
.as_str()
.ok_or_else(|| JsValue::from_str("Invalid options: missing field `backend`"))?,
)
.map_err(|e| JsValue::from_str(&e))?;
let vk: serde_json::Value = vk.into_serde().unwrap();
let proof: serde_json::Value = proof.into_serde().unwrap();
let vk_curve = CurveParameter::try_from(
@ -600,25 +733,33 @@ pub fn verify(vk: JsValue, proof: JsValue) -> Result<JsValue, JsValue> {
let scheme = vk_scheme;
let curve = vk_curve;
match scheme {
SchemeParameter::G16 => match curve {
match (backend, scheme) {
(BackendParameter::Bellman, SchemeParameter::G16) => match curve {
CurveParameter::Bn128 => internal::verify::<Bn128Field, G16, Bellman>(vk, proof),
CurveParameter::Bls12_381 => Err(JsValue::from_str(
"Not supported: https://github.com/Zokrates/ZoKrates/issues/1200",
)),
_ => Err(JsValue::from_str("Not supported")),
},
(BackendParameter::Ark, SchemeParameter::G16) => match curve {
CurveParameter::Bn128 => internal::verify::<Bn128Field, G16, Ark>(vk, proof),
CurveParameter::Bls12_381 => internal::verify::<Bls12_381Field, G16, Ark>(vk, proof),
CurveParameter::Bls12_377 => internal::verify::<Bls12_377Field, G16, Ark>(vk, proof),
CurveParameter::Bw6_761 => internal::verify::<Bw6_761Field, G16, Ark>(vk, proof),
},
SchemeParameter::GM17 => match curve {
(BackendParameter::Ark, SchemeParameter::GM17) => match curve {
CurveParameter::Bn128 => internal::verify::<Bn128Field, GM17, Ark>(vk, proof),
CurveParameter::Bls12_381 => internal::verify::<Bls12_381Field, GM17, Ark>(vk, proof),
CurveParameter::Bls12_377 => internal::verify::<Bls12_377Field, GM17, Ark>(vk, proof),
CurveParameter::Bw6_761 => internal::verify::<Bw6_761Field, GM17, Ark>(vk, proof),
},
SchemeParameter::MARLIN => match curve {
(BackendParameter::Ark, SchemeParameter::MARLIN) => match curve {
CurveParameter::Bn128 => internal::verify::<Bn128Field, Marlin, Ark>(vk, proof),
CurveParameter::Bls12_381 => internal::verify::<Bls12_381Field, Marlin, Ark>(vk, proof),
CurveParameter::Bls12_377 => internal::verify::<Bls12_377Field, Marlin, Ark>(vk, proof),
CurveParameter::Bw6_761 => internal::verify::<Bw6_761Field, Marlin, Ark>(vk, proof),
},
_ => Err(JsValue::from_str("Unsupported options")),
}
}

28
zokrates_js/src/util.rs Normal file
View file

@ -0,0 +1,28 @@
use std::path::{Component, PathBuf};
pub fn normalize_path(path: PathBuf) -> PathBuf {
let mut components = path.components().peekable();
let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
components.next();
PathBuf::from(c.as_os_str())
} else {
PathBuf::new()
};
for component in components {
match component {
Component::Prefix(..) => unreachable!(),
Component::RootDir => {
ret.push(component.as_os_str());
}
Component::CurDir => {}
Component::ParentDir => {
ret.pop();
}
Component::Normal(c) => {
ret.push(c);
}
}
}
ret
}

View file

@ -4,7 +4,7 @@ const fs = require("fs");
const os = require("os");
const dree = require("dree");
const snarkjs = require("snarkjs");
const { initialize } = require("../node/index.js");
const { initialize, metadata } = require("../node/index.js");
let zokratesProvider;
let tmpFolder;
@ -14,9 +14,11 @@ describe("tests", () => {
before(() => {
return initialize().then((defaultProvider) => {
zokratesProvider = defaultProvider;
return fs.promises.mkdtemp(path.join(os.tmpdir(), path.sep)).then((folder) => {
tmpFolder = folder;
});
return fs.promises
.mkdtemp(path.join(os.tmpdir(), path.sep))
.then((folder) => {
tmpFolder = folder;
});
});
});
@ -24,14 +26,20 @@ describe("tests", () => {
if (globalThis.curve_bn128) globalThis.curve_bn128.terminate();
});
describe("metadata", () => {
it("is present", () => {
assert.ok(metadata);
assert.ok(metadata.version !== undefined);
});
});
describe("compilation", () => {
it("should compile", () => {
assert.doesNotThrow(() => {
const artifacts = zokratesProvider.compile(
"def main() -> field { return 42; }"
);
assert.ok(artifacts !== undefined);
assert.ok(artifacts);
assert.ok(artifacts.snarkjs === undefined);
});
});
@ -42,7 +50,7 @@ describe("tests", () => {
"def main() -> field { return 42; }",
{ snarkjs: true }
);
assert.ok(artifacts !== undefined);
assert.ok(artifacts);
assert.ok(artifacts.snarkjs.program !== undefined);
});
});
@ -52,11 +60,8 @@ describe("tests", () => {
});
it("should resolve stdlib module", () => {
const stdlib = require("../stdlib.js");
assert.doesNotThrow(() => {
const code = `import "${
Object.keys(stdlib)[0]
}" as func;\ndef main() { return; }`;
const code = `import "utils/pack/bool/unpack" as unpack;\ndef main() { return; }`;
zokratesProvider.compile(code);
});
});
@ -64,7 +69,7 @@ describe("tests", () => {
it("should resolve user module", () => {
assert.doesNotThrow(() => {
const code =
'import "test" as test;\ndef main() -> field { return test(); }';
'import "./test" as test;\ndef main() -> field { return test(); }';
const options = {
resolveCallback: (_, path) => {
return {
@ -80,7 +85,7 @@ describe("tests", () => {
it("should throw on unresolved module", () => {
assert.throws(() => {
const code =
'import "test" as test;\ndef main() -> field { return test(); }';
'import "./test" as test;\ndef main() -> field { return test(); }';
zokratesProvider.compile(code);
});
});
@ -128,6 +133,22 @@ describe("tests", () => {
zokratesProvider.computeWitness(artifacts, [true]);
});
});
it("should log in debug", () => {
assert.doesNotThrow(() => {
const code = 'def main() { log("{}", 1f); log("{}", 2f); return; }';
const artifacts = zokratesProvider.compile(code, {
config: { debug: true },
});
let logs = [];
zokratesProvider.computeWitness(artifacts, [], {
logCallback: (l) => {
logs.push(l);
},
});
assert.deepEqual(logs, ['"1"', '"2"']);
});
});
});
const runWithOptions = (options) => {
@ -224,10 +245,25 @@ describe("tests", () => {
});
};
for (const scheme of ["g16", "gm17", "marlin"]) {
describe(scheme, () => {
for (const curve of ["bn128", "bls12_381", "bls12_377", "bw6_761"]) {
describe(curve, () => runWithOptions({ scheme, curve }));
let combinations = {
ark: {
schemes: ["g16", "gm17", "marlin"],
curves: ["bn128", "bls12_381", "bls12_377", "bw6_761"],
},
bellman: {
schemes: ["g16"],
curves: ["bn128"],
},
};
for (const backend of Object.keys(combinations)) {
describe(backend, () => {
for (const scheme of combinations[backend].schemes) {
describe(scheme, () => {
for (const curve of combinations[backend].curves) {
describe(curve, () => runWithOptions({ backend, scheme, curve }));
}
});
}
});
}

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_parser"
version = "0.3.0"
version = "0.3.1"
authors = ["JacobEberhardt <jacob.eberhardt@tu-berlin.de>"]
edition = "2018"

View file

@ -1,4 +0,0 @@
### ZoKrates Ace Mode (Syntax Highlighting for Ace/Brace)
[Ace](https://ace.c9.io/) Edit Mode for [ZoKrates DSL](https://github.com/Zokrates/ZoKrates).
Compatible with browserify version of the ace editor, [brace](https://www.npmjs.com/package/brace).

View file

@ -1,121 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2019, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
ace.define("ace/mode/zokrates_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"], function(acequire, exports, module) {
"use strict";
var oop = acequire("../lib/oop");
var TextHighlightRules = acequire("./text_highlight_rules").TextHighlightRules;
var ZoKratesHighlightRules = function () {
var keywords = (
"assert|as|bool|byte|const|def|do|else|endfor|export|false|field|for|if|then|fi|import|from|in|private|public|return|struct|true|type|u8|u16|u32|u64"
);
var keywordMapper = this.createKeywordMapper({
"keyword": keywords
}, "identifier");
var decimalInteger = "(?:(?:[1-9]\\d*)|(?:0))";
var decimalSuffix = "(?:_?(?:f|u(?:8|16|32|64)))?";
var hexInteger = "(?:0[xX][\\dA-Fa-f]+)";
var integer = "(?:" + decimalInteger + decimalSuffix + "|" + hexInteger + ")\\b";
this.$rules = {
"start": [
{
token: "comment", // single line comment
regex: "\\/\\/.*$"
}, {
token: "comment", // multi line comment
regex: "\\/\\*",
next: "comment"
}, {
token: "string", // single line
regex: '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]'
}, {
token: "constant.numeric", // integer
regex: integer
}, {
token: keywordMapper,
regex: "[a-zA-Z_$][a-zA-Z0-9_$]*\\b"
}, {
token: "keyword.operator",
regex: "\\+|\\-|\\*\\*?|\\/|\\|\\|?|&&?|\\^|!|<<?|>>?|<=|=>|==|!=|="
}, {
token: "punctuation",
regex: ",|:|;"
}, {
token: "lparen",
regex: "[[({]"
}, {
token: "rparen",
regex: "[\\])}]"
}, {
token: "text",
regex: "\\s+"
}
],
"comment": [
{
token: "comment", // closing comment
regex: "\\*\\/",
next: "start"
}, {
defaultToken: "comment"
}
]
};
};
oop.inherits(ZoKratesHighlightRules, TextHighlightRules);
exports.ZoKratesHighlightRules = ZoKratesHighlightRules;
});
ace.define("ace/mode/zokrates",["require","exports","module","ace/lib/oop","ace/mode/text","ace/mode/zokrates_highlight_rules"], function(acequire, exports, module) {
"use strict";
var oop = acequire("../lib/oop");
var TextMode = acequire("./text").Mode;
var ZoKratesHighlightRules = acequire("./zokrates_highlight_rules").ZoKratesHighlightRules;
var Mode = function () {
this.HighlightRules = ZoKratesHighlightRules;
};
oop.inherits(Mode, TextMode);
(function () {
this.$id = "ace/mode/zokrates";
}).call(Mode.prototype);
exports.Mode = Mode;
});

View file

@ -1,17 +0,0 @@
{
"name": "ace-mode-zokrates",
"version": "1.0.4",
"description": "Ace Mode for ZoKrates DSL",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"zokrates",
"ace",
"mode",
"brace"
],
"author": "Darko Macesic",
"license": "LGPL"
}

View file

@ -0,0 +1 @@
*.tmLanguage.json

View file

@ -1,36 +1,36 @@
{
"name": "zokrates",
"displayName": "zokrates",
"description": "Syntax highlighting for the ZoKrates language",
"publisher": "zokrates",
"repository": "https://github.com/ZoKrates/ZoKrates",
"version": "0.0.2",
"engines": {
"vscode": "^1.53.0"
},
"categories": [
"Programming Languages"
],
"contributes": {
"languages": [
{
"id": "zokrates",
"aliases": [
"ZoKrates",
"zokrates"
],
"extensions": [
".zok"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "zokrates",
"scopeName": "source.zok",
"path": "./syntaxes/zokrates.tmLanguage.json"
}
]
}
}
"name": "zokrates",
"displayName": "zokrates",
"description": "Syntax highlighting for the ZoKrates language",
"publisher": "zokrates",
"repository": "https://github.com/ZoKrates/ZoKrates",
"version": "0.1.0",
"engines": {
"vscode": "^1.53.0"
},
"categories": [
"Programming Languages"
],
"contributes": {
"languages": [
{
"id": "zokrates",
"aliases": [
"ZoKrates",
"zokrates"
],
"extensions": [
".zok"
],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "zokrates",
"scopeName": "source.zok",
"path": "./syntaxes/zokrates.tmLanguage.json"
}
]
}
}

View file

@ -1,637 +0,0 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "ZoKrates",
"fileTypes": [
"zok"
],
"scopeName": "source.zok",
"patterns": [
{
"comment": "attributes",
"name": "meta.attribute.zokrates",
"begin": "(#)(\\!?)(\\[)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.attribute.zokrates"
},
"2": {
"name": "keyword.operator.attribute.inner.zokrates"
},
"3": {
"name": "punctuation.brackets.attribute.zokrates"
}
},
"end": "\\]",
"endCaptures": {
"0": {
"name": "punctuation.brackets.attribute.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#punctuation"
},
{
"include": "#strings"
},
{
"include": "#types"
}
]
},
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#constants"
},
{
"include": "#functions"
},
{
"include": "#types"
},
{
"include": "#keywords"
},
{
"include": "#punctuation"
},
{
"include": "#strings"
},
{
"include": "#variables"
}
],
"repository": {
"comments": {
"patterns": [
{
"comment": "line comments",
"name": "comment.line.double-slash.zokrates",
"match": "\\s*//.*"
}
]
},
"block-comments": {
"patterns": [
{
"comment": "empty block comments",
"name": "comment.block.zokrates",
"match": "/\\*\\*/"
},
{
"comment": "block comments",
"name": "comment.block.zokrates",
"begin": "/\\*(?!\\*)",
"end": "\\*/",
"patterns": [
{
"include": "#block-comments"
}
]
}
]
},
"constants": {
"patterns": [
{
"comment": "ALL CAPS constants",
"name": "constant.other.caps.zokrates",
"match": "\\b[A-Z]{2}[A-Z0-9_]*\\b"
},
{
"comment": "decimal integers and floats",
"name": "constant.numeric.decimal.zokrates",
"match": "\\b\\d[\\d_]*(?:u128|u16|u32|u64|u8|f)?\\b"
},
{
"comment": "hexadecimal integers",
"name": "constant.numeric.hex.zokrates",
"match": "\\b0x[\\da-fA-F_]+\\b"
},
{
"comment": "booleans",
"name": "constant.language.bool.zokrates",
"match": "\\b(true|false)\\b"
}
]
},
"imports": {
"patterns": [
{
"comment": "explicit import statement",
"name": "meta.import.explicit.zokrates",
"match": "\\b(from)\\s+(\\\".*\\\")(import)\\s+([A-Za-z0-9_]+)\\s+((as)\\s+[A-Za-z0-9_]+)?\\b",
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#punctuation"
},
{
"include": "#types"
},
{
"include": "#strings"
}
]
},
{
"comment": "main import statement",
"name": "meta.import.explicit.zokrates",
"match": "\\b(import)\\s+(\\\".*\\\")\\s+((as)\\s+[A-Za-z0-9_]+)?\\b",
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#punctuation"
},
{
"include": "#types"
},
{
"include": "#strings"
}
]
}
]
},
"constant-definitions": {
"patterns": [
{
"comment": "constant definition",
"name": "constant.definition.zokrates",
"match": "\\b(const)\\s+([A-Za-z0-9_]+)\\s+([A-Za-z0-9_]+)\\s+=\\s+(?:.+)\\b",
"captures": {
"1": {
"name": "keyword.other.const.zokrates"
},
"2": {
"name": "entity.name.type.zokrates"
},
"3": {
"name": "entity.name.constant.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#constants"
},
{
"include": "#punctuation"
},
{
"include": "#types"
},
{
"include": "#variables"
}
]
}
]
},
"functions": {
"patterns": [
{
"comment": "function definition",
"name": "meta.function.definition.zokrates",
"begin": "\\b(def)\\s+([A-Za-z0-9_]+)((\\()|(<))",
"beginCaptures": {
"1": {
"name": "keyword.other.def.zokrates"
},
"2": {
"name": "entity.name.function.zokrates"
},
"4": {
"name": "punctuation.brackets.round.zokrates"
},
"5": {
"name": "punctuation.brackets.angle.zokrates"
}
},
"end": "\\:|;",
"endCaptures": {
"0": {
"name": "keyword.punctuation.colon.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#constants"
},
{
"include": "#functions"
},
{
"include": "#punctuation"
},
{
"include": "#strings"
},
{
"include": "#types"
},
{
"include": "#variables"
}
]
},
{
"comment": "function/method calls, chaining",
"name": "meta.function.call.zokrates",
"begin": "([A-Za-z0-9_]+)(\\()",
"beginCaptures": {
"1": {
"name": "entity.name.function.zokrates"
},
"2": {
"name": "punctuation.brackets.round.zokrates"
}
},
"end": "\\)",
"endCaptures": {
"0": {
"name": "punctuation.brackets.round.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#constants"
},
{
"include": "#functions"
},
{
"include": "#punctuation"
},
{
"include": "#strings"
},
{
"include": "#types"
},
{
"include": "#variables"
}
]
},
{
"comment": "function/method calls with turbofish",
"name": "meta.function.call.zokrates",
"begin": "([A-Za-z0-9_]+)(?=::<.*>\\()",
"beginCaptures": {
"1": {
"name": "entity.name.function.zokrates"
}
},
"end": "\\)",
"endCaptures": {
"0": {
"name": "punctuation.brackets.round.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#constants"
},
{
"include": "#functions"
},
{
"include": "#punctuation"
},
{
"include": "#strings"
},
{
"include": "#types"
},
{
"include": "#variables"
}
]
}
]
},
"keywords": {
"patterns": [
{
"comment": "argument visibility",
"name": "keyword.visibility.zokrates",
"match": "\\b(public|private)\\b"
},
{
"comment": "control flow keywords",
"name": "keyword.control.zokrates",
"match": "\\b(do|else|for|do|endfor|if|then|fi|return|assert)\\b"
},
{
"comment": "storage keywords",
"name": "storage.type.zokrates",
"match": "\\b(struct)\\b"
},
{
"comment": "const",
"name": "keyword.other.const.zokrates",
"match": "\\bconst\\b"
},
{
"comment": "def",
"name": "keyword.other.def.zokrates",
"match": "\\bdef\\b"
},
{
"comment": "import keywords",
"name": "keyword.other.import.zokrates",
"match": "\\b(import|from|as)\\b"
},
{
"comment": "logical operators",
"name": "keyword.operator.logical.zokrates",
"match": "(\\^|\\||\\|\\||&|&&|<<|>>|!)(?!=)"
},
{
"comment": "single equal",
"name": "keyword.operator.assignment.equal.zokrates",
"match": "(?<![<>])=(?!=|>)"
},
{
"comment": "comparison operators",
"name": "keyword.operator.comparison.zokrates",
"match": "(=(=)?(?!>)|!=|<=|(?<!=)>=)"
},
{
"comment": "math operators",
"name": "keyword.operator.math.zokrates",
"match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))"
},
{
"comment": "less than, greater than (special case)",
"match": "(?:\\b|(?:(\\))|(\\])|(\\})))[ \\t]+([<>])[ \\t]+(?:\\b|(?:(\\()|(\\[)|(\\{)))",
"captures": {
"1": {
"name": "punctuation.brackets.round.zokrates"
},
"2": {
"name": "punctuation.brackets.square.zokrates"
},
"3": {
"name": "punctuation.brackets.curly.zokrates"
},
"4": {
"name": "keyword.operator.comparison.zokrates"
},
"5": {
"name": "punctuation.brackets.round.zokrates"
},
"6": {
"name": "punctuation.brackets.square.zokrates"
},
"7": {
"name": "punctuation.brackets.curly.zokrates"
}
}
},
{
"comment": "dot access",
"name": "keyword.operator.access.dot.zokrates",
"match": "\\.(?!\\.)"
},
{
"comment": "ranges, range patterns",
"name": "keyword.operator.range.zokrates",
"match": "\\.{2}(=|\\.)?"
},
{
"comment": "colon",
"name": "keyword.operator.colon.zokrates",
"match": ":(?!:)"
},
{
"comment": "dashrocket, skinny arrow",
"name": "keyword.operator.arrow.skinny.zokrates",
"match": "->"
}
]
},
"types": {
"patterns": [
{
"comment": "numeric types",
"match": "(?<![A-Za-z])(u128|u16|u32|u64|u8|field)\\b",
"captures": {
"1": {
"name": "entity.name.type.numeric.zokrates"
}
}
},
{
"comment": "parameterized types",
"begin": "\\b([A-Z][A-Za-z0-9]*)(<)",
"beginCaptures": {
"1": {
"name": "entity.name.type.zokrates"
},
"2": {
"name": "punctuation.brackets.angle.zokrates"
}
},
"end": ">",
"endCaptures": {
"0": {
"name": "punctuation.brackets.angle.zokrates"
}
},
"patterns": [
{
"include": "#block-comments"
},
{
"include": "#comments"
},
{
"include": "#keywords"
},
{
"include": "#punctuation"
},
{
"include": "#types"
},
{
"include": "#variables"
}
]
},
{
"comment": "primitive types",
"name": "entity.name.type.primitive.zokrates",
"match": "\\b(bool)\\b"
},
{
"comment": "struct declarations",
"match": "\\b(struct)\\s+([A-Z][A-Za-z0-9]*)\\b",
"captures": {
"1": {
"name": "storage.type.zokrates"
},
"2": {
"name": "entity.name.type.struct.zokrates"
}
}
},
{
"comment": "types",
"name": "entity.name.type.zokrates",
"match": "\\b[A-Z][A-Za-z0-9]*\\b(?!!)"
}
]
},
"punctuation": {
"patterns": [
{
"comment": "comma",
"name": "punctuation.comma.zokrates",
"match": ","
},
{
"comment": "parentheses, round brackets",
"name": "punctuation.brackets.round.zokrates",
"match": "[()]"
},
{
"comment": "square brackets",
"name": "punctuation.brackets.square.zokrates",
"match": "[\\[\\]]"
},
{
"comment": "angle brackets",
"name": "punctuation.brackets.angle.zokrates",
"match": "(?<!=)[<>]"
}
]
},
"strings": {
"patterns": [
{
"comment": "double-quoted strings and byte strings",
"name": "string.quoted.double.zokrates",
"begin": "(b?)(\")",
"beginCaptures": {
"1": {
"name": "string.quoted.byte.raw.zokrates"
},
"2": {
"name": "punctuation.definition.string.zokrates"
}
},
"end": "\"",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.zokrates"
}
}
},
{
"comment": "double-quoted raw strings and raw byte strings",
"name": "string.quoted.double.zokrates",
"begin": "(b?r)(#*)(\")",
"beginCaptures": {
"1": {
"name": "string.quoted.byte.raw.zokrates"
},
"2": {
"name": "punctuation.definition.string.raw.zokrates"
},
"3": {
"name": "punctuation.definition.string.zokrates"
}
},
"end": "(\")(\\2)",
"endCaptures": {
"1": {
"name": "punctuation.definition.string.zokrates"
},
"2": {
"name": "punctuation.definition.string.raw.zokrates"
}
}
}
]
},
"variables": {
"patterns": [
{
"comment": "variables",
"name": "variable.other.zokrates",
"match": "\\b(?<!(?<!\\.)\\.)[a-z0-9_]+\\b"
}
]
}
}
}

View file

@ -79,7 +79,7 @@ repository:
-
comment: 'decimal integers and floats'
name: constant.numeric.decimal.zokrates
match: '\b\d[\d_]*(?:u128|u16|u32|u64|u8|f)?\b'
match: '\b\d[\d_]*(?:u16|u32|u64|u8|f)?\b'
-
comment: 'hexadecimal integers'
name: constant.numeric.hex.zokrates
@ -202,7 +202,7 @@ repository:
-
comment: 'control flow keywords'
name: keyword.control.zokrates
match: \b(for|in|do|endfor|if|then|else|fi|return|assert)\b
match: \b(for|in|if|else|return|assert|log)\b
-
comment: 'storage keywords'
name: storage.type.zokrates
@ -227,6 +227,10 @@ repository:
comment: 'logical operators'
name: keyword.operator.logical.zokrates
match: '(\^|\||\|\||&|&&|<<|>>|!)(?!=)'
-
comment: 'mut'
name: "storage.modifier.mut.zokrates"
match: \b(mut)\b
-
comment: 'single equal'
name: keyword.operator.assignment.equal.zokrates
@ -270,7 +274,7 @@ repository:
patterns:
-
comment: 'numeric types'
match: '(?<![A-Za-z])(u128|u16|u32|u64|u8|field)\b'
match: '(?<![A-Za-z])(u16|u32|u64|u8|field)\b'
captures:
'1': {name: entity.name.type.numeric.zokrates}
-
@ -309,10 +313,18 @@ repository:
comment: comma
name: punctuation.comma.zokrates
match: ','
-
comment: 'curly braces'
name: punctuation.brackets.curly.zokrates
match: '[{}]'
-
comment: 'parentheses, round brackets'
name: punctuation.brackets.round.zokrates
match: '[()]'
-
comment: 'semicolon'
name: punctuation.semi.zokrates
match: ';'
-
comment: 'square brackets'
name: punctuation.brackets.square.zokrates

View file

@ -180,6 +180,6 @@ COMMENT = _{ ("/*" ~ (!"*/" ~ ANY)* ~ "*/") | ("//" ~ (!NEWLINE ~ ANY)*) }
// the ordering of reserved keywords matters: if "as" is before "assert", then "assert" gets parsed as (as)(sert) and incorrectly
// accepted
keyword = @{
"log"|"assert"|"as"|"bool"|"const"|"def"|"else"|"false"|"field"|"for"|"if"|"then"|"fi"|"import"|"from"|
"in"|"mut"|"private"|"public"|"return"|"struct"|"true"|"u8"|"u16"|"u32"|"u64"
"log"|"assert"|"as"|"bool"|"const"|"def"|"else"|"false"|"field"|"for"|"if"|"import"|"from"|
"in"|"mut"|"private"|"public"|"return"|"struct"|"true"|"type"|"u8"|"u16"|"u32"|"u64"
}

View file

@ -1,6 +1,6 @@
[package]
name = "zokrates_stdlib"
version = "0.3.0"
version = "0.3.1"
authors = ["Stefan Deml <stefandeml@gmail.com>", "schaeff <thibaut@schaeff.fr>"]
edition = "2018"

View file

@ -0,0 +1,5 @@
from "hashes/keccak/keccak" import main as keccak;
def main<N>(u8[N] input) -> u8[28] {
return keccak::<_, 28>(input, 0x01);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def keccak256<N>(u8[N] input) -> u64[4] {
return keccak_u8::<_, 256>(input, 0x0000000000000001)[..4];
}
def main<N>(u64[N] input) -> u64[4] {
return keccak::<_, 256>(input, 0x0000000000000001)[..4];
def main<N>(u8[N] input) -> u8[32] {
return keccak::<_, 32>(input, 0x01);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def keccak384<N>(u8[N] input) -> u64[6] {
return keccak_u8::<_, 384>(input, 0x0000000000000001)[..6];
}
def main<N>(u64[N] input) -> u64[6] {
return keccak::<_, 384>(input, 0x0000000000000001)[..6];
def main<N>(u8[N] input) -> u8[48] {
return keccak::<_, 48>(input, 0x01);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def keccak512<N>(u8[N] input) -> u64[8] {
return keccak_u8::<_, 512>(input, 0x0000000000000001)[..8];
}
def main<N>(u64[N] input) -> u64[8] {
return keccak::<_, 512>(input, 0x0000000000000001)[..8];
def main<N>(u8[N] input) -> u8[64] {
return keccak::<_, 64>(input, 0x01);
}

View file

@ -1,8 +1,10 @@
// https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
// based on keccak-f[1600] permutation
import "utils/casts/u64_from_bits";
import "utils/casts/u8_to_bits";
import "utils/casts/u8_from_bits";
import "utils/casts/u64_to_bits";
import "utils/casts/u64_from_bits";
const u32[24] RHO = [
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14,
@ -10,19 +12,19 @@ const u32[24] RHO = [
];
const u32[24] PI = [
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4,
15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1
];
const u64[24] RC = [
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
0x0000000000000001, 0x0000000000008082, 0x800000000000808a,
0x8000000080008000, 0x000000000000808b, 0x0000000080000001,
0x8000000080008081, 0x8000000000008009, 0x000000000000008a,
0x0000000000000088, 0x0000000080008009, 0x000000008000000a,
0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
0x8000000000008003, 0x8000000000008002, 0x8000000000000080,
0x000000000000800a, 0x800000008000000a, 0x8000000080008081,
0x8000000000008080, 0x0000000080000001, 0x8000000080008008
];
// left rotation
@ -42,6 +44,10 @@ def keccakf(u64[25] mut st) -> u64[25] {
u64[5] mut bc = [0; 5];
u64 mut t = 0;
for u32 i in 0..25 {
st[i] = swap_u64(st[i]);
}
for u32 r in 0..24 {
// theta
for u32 i in 0..5 {
@ -79,42 +85,15 @@ def keccakf(u64[25] mut st) -> u64[25] {
// iota
st[0] = st[0] ^ RC[r];
}
for u32 i in 0..25 {
st[i] = swap_u64(st[i]);
}
return st;
}
def keccak<N, W>(u64[N] mut input, u64 pad) -> u64[25] {
u64[25] mut q = [0; 25];
u32 rate = (200 - (W / 4)) / 8;
u32 mut pt = 0;
// change endianness of inputs from big endian to little endian
for u32 i in 0..N {
input[i] = swap_u64(input[i]);
}
// update
for u32 i in 0..N {
q[pt] = q[pt] ^ input[i];
pt = (pt + 1) % rate;
q = pt == 0 ? keccakf(q) : q;
}
pt = (pad & 0x00000000000000ff) != 0 ? pt : pt - 1;
// finalize
q[pt] = q[pt] ^ pad;
q[rate - 1] = q[rate - 1] ^ 0x8000000000000000;
q = keccakf(q);
// change endianness of output from little endian to big endian
for u32 i in 0..W/64 {
q[i] = swap_u64(q[i]);
}
return q;
}
def u8_array_to_u64(u8[8] input) -> u64 {
def u64_from_u8_array(u8[8] input) -> u64 {
bool[64] bits = [
...u8_to_bits(input[0]),
...u8_to_bits(input[1]),
@ -128,18 +107,55 @@ def u8_array_to_u64(u8[8] input) -> u64 {
return u64_from_bits(bits);
}
def main<N, W>(u8[N] input, u64 pad) -> u64[25] {
u32 L = N / 8;
u32 R = L * 8 == N ? 0 : 1;
u32 len = L + R;
def u64_to_u8_array(u64 input) -> u8[8] {
bool[64] bits = u64_to_bits(input);
return [
u8_from_bits(bits[0..8]),
u8_from_bits(bits[8..16]),
u8_from_bits(bits[16..24]),
u8_from_bits(bits[24..32]),
u8_from_bits(bits[32..40]),
u8_from_bits(bits[40..48]),
u8_from_bits(bits[48..56]),
u8_from_bits(bits[56..64])
];
}
u8[len * 8] padded = [...input, ...[0; len * 8 - N]];
u64[len] mut input_u64 = [0; len];
def to_bytes(u64[25] input) -> u8[200] {
u8[200] mut output = [0; 200];
for u32 i in 0..25 {
u8[8] t = u64_to_u8_array(input[i]);
for u32 j in 0..8 {
output[i * 8 + j] = t[j];
}
}
return output;
}
for u32 i in 0..len {
u32 j = i * 8;
input_u64[i] = u8_array_to_u64(padded[j..j+8]);
def from_bytes(u8[200] input) -> u64[25] {
u64[25] mut output = [0; 25];
for u32 i in 0..25 {
output[i] = u64_from_u8_array(input[i*8..i*8+8]);
}
return output;
}
def main<N, W>(u8[N] mut input, u8 delim) -> u8[W] {
u8[200] mut b = [0; 200];
u32 rate = 200 - (2 * W);
u32 mut pt = 0;
// update
for u32 i in 0..N {
b[pt] = b[pt] ^ input[i];
pt = (pt + 1) % rate;
b = pt == 0 ? to_bytes(keccakf(from_bytes(b))) : b;
}
return keccak::<_, W>(input_u64, pad << ((N % 8) * 8));
// finalize
b[pt] = b[pt] ^ delim;
b[rate - 1] = b[rate - 1] ^ 0x80;
b = to_bytes(keccakf(from_bytes(b)));
return b[..W];
}

View file

@ -7,7 +7,7 @@ const u32[8] IV = [
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
];
// A function that takes N u32[8] arrays as inputs, concatenates them,
// A function that takes N u32[16] arrays as inputs, concatenates them,
// and returns their sha256 compression as a u32[8].
// Note: no padding is applied
def main<N>(u32[N][16] a) -> u32[8] {

View file

@ -0,0 +1,5 @@
from "hashes/keccak/keccak" import main as keccak;
def main<N>(u8[N] input) -> u8[28] {
return keccak::<_, 28>(input, 0x06);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def sha3_256<N>(u8[N] input) -> u64[4] {
return keccak_u8::<_, 256>(input, 0x0000000000000006)[..4];
}
def main<N>(u64[N] input) -> u64[4] {
return keccak::<_, 256>(input, 0x0000000000000006)[..4];
def main<N>(u8[N] input) -> u8[32] {
return keccak::<_, 32>(input, 0x06);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def sha3_384<N>(u8[N] input) -> u64[6] {
return keccak_u8::<_, 384>(input, 0x0000000000000006)[..6];
}
def main<N>(u64[N] input) -> u64[6] {
return keccak::<_, 384>(input, 0x0000000000000006)[..6];
def main<N>(u8[N] input) -> u8[48] {
return keccak::<_, 48>(input, 0x06);
}

View file

@ -1,9 +1,5 @@
from "hashes/keccak/keccak" import keccak, main as keccak_u8;
from "hashes/keccak/keccak" import main as keccak;
def sha3_512<N>(u8[N] input) -> u64[8] {
return keccak_u8::<_, 512>(input, 0x0000000000000006)[..8];
}
def main<N>(u64[N] input) -> u64[8] {
return keccak::<_, 512>(input, 0x0000000000000006)[..8];
def main<N>(u8[N] input) -> u8[64] {
return keccak::<_, 64>(input, 0x06);
}

View file

@ -0,0 +1,15 @@
{
"entry_point": "./tests/tests/hashes/keccak/224bit.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": []
}
}
}
]
}

View file

@ -0,0 +1,47 @@
import "hashes/keccak/224bit" as keccak224;
def main() {
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=224)
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// '69d40b3f7b3118a1fb193b518a70f279348e4f0835553f37d85f436a'
u8[28] h1 = keccak224::<1>([0x2a]);
assert(h1 == [
0x69, 0xd4, 0x0b, 0x3f, 0x7b, 0x31, 0x18, 0xa1, 0xfb, 0x19, 0x3b, 0x51, 0x8a, 0x70,
0xf2, 0x79, 0x34, 0x8e, 0x4f, 0x08, 0x35, 0x55, 0x3f, 0x37, 0xd8, 0x5f, 0x43, 0x6a
]);
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=224)
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// '463b45a39816aeba7c62a75aed7acaaf11f7646217512a2f992ddce0'
u8[28] h2 = keccak224::<8>([0x2a; 8]);
assert(h2 == [
0x46, 0x3b, 0x45, 0xa3, 0x98, 0x16, 0xae, 0xba, 0x7c, 0x62, 0xa7, 0x5a, 0xed, 0x7a,
0xca, 0xaf, 0x11, 0xf7, 0x64, 0x62, 0x17, 0x51, 0x2a, 0x2f, 0x99, 0x2d, 0xdc, 0xe0
]);
// Python:
// >>> from Crypto.Hash import keccak
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = keccak.new(digest_bits=224)
// >>> digest.update(input)
// >>> digest.hexdigest()
// '25f3ecfebabe99686282f57f5c9e1f18244cfee2813d33f955aae568'
u8[28] h3 = keccak224::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x25, 0xf3, 0xec, 0xfe, 0xba, 0xbe, 0x99, 0x68, 0x62, 0x82, 0xf5, 0x7f, 0x5c, 0x9e,
0x1f, 0x18, 0x24, 0x4c, 0xfe, 0xe2, 0x81, 0x3d, 0x33, 0xf9, 0x55, 0xaa, 0xe5, 0x68
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/keccak/256bit" import keccak256;
import "hashes/keccak/256bit" as keccak256;
def main() {
// Python:
@ -8,8 +8,11 @@ def main() {
// >>> digest.hexdigest()
// '04994f67dc55b09e814ab7ffc8df3686b4afb2bb53e60eae97ef043fe03fb829'
u64[4] h1 = keccak256::<1>([0x2a]);
assert(h1 == [0x04994f67dc55b09e, 0x814ab7ffc8df3686, 0xb4afb2bb53e60eae, 0x97ef043fe03fb829]);
u8[32] h1 = keccak256::<1>([0x2a]);
assert(h1 == [
0x04, 0x99, 0x4f, 0x67, 0xdc, 0x55, 0xb0, 0x9e, 0x81, 0x4a, 0xb7, 0xff, 0xc8, 0xdf, 0x36, 0x86,
0xb4, 0xaf, 0xb2, 0xbb, 0x53, 0xe6, 0x0e, 0xae, 0x97, 0xef, 0x04, 0x3f, 0xe0, 0x3f, 0xb8, 0x29
]);
// Python:
// >>> from Crypto.Hash import keccak
@ -18,8 +21,11 @@ def main() {
// >>> digest.hexdigest()
// '4d57ecea94f7735c23ae7c02845a500a815c21fc6d6046d2d7d518fad6bebf89'
u64[4] h2 = keccak256::<8>([0x2a; 8]);
assert(h2 == [0x4d57ecea94f7735c, 0x23ae7c02845a500a, 0x815c21fc6d6046d2, 0xd7d518fad6bebf89]);
u8[32] h2 = keccak256::<8>([0x2a; 8]);
assert(h2 == [
0x4d, 0x57, 0xec, 0xea, 0x94, 0xf7, 0x73, 0x5c, 0x23, 0xae, 0x7c, 0x02, 0x84, 0x5a, 0x50, 0x0a,
0x81, 0x5c, 0x21, 0xfc, 0x6d, 0x60, 0x46, 0xd2, 0xd7, 0xd5, 0x18, 0xfa, 0xd6, 0xbe, 0xbf, 0x89
]);
// Python:
// >>> from Crypto.Hash import keccak
@ -31,8 +37,11 @@ def main() {
// >>> digest.hexdigest()
// '47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad'
u64[4] h3 = keccak256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [0x47173285a8d7341e, 0x5e972fc677286384, 0xf802f8ef42a5ec5f, 0x03bbfa254cb01fad]);
u8[32] h3 = keccak256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x47, 0x17, 0x32, 0x85, 0xa8, 0xd7, 0x34, 0x1e, 0x5e, 0x97, 0x2f, 0xc6, 0x77, 0x28, 0x63, 0x84,
0xf8, 0x02, 0xf8, 0xef, 0x42, 0xa5, 0xec, 0x5f, 0x03, 0xbb, 0xfa, 0x25, 0x4c, 0xb0, 0x1f, 0xad
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/keccak/384bit" import keccak384;
import "hashes/keccak/384bit" as keccak384;
def main() {
// Python:
@ -8,10 +8,11 @@ def main() {
// >>> digest.hexdigest()
// '53403c11270822eebdccc9aca81e0582996de74333909598a4e4c409967fb9da14a1506264996c855eb5d9a42fd21a08'
u64[6] h1 = keccak384::<1>([0x2a]);
u8[48] h1 = keccak384::<1>([0x2a]);
assert(h1 == [
0x53403c11270822ee, 0xbdccc9aca81e0582, 0x996de74333909598,
0xa4e4c409967fb9da, 0x14a1506264996c85, 0x5eb5d9a42fd21a08
0x53, 0x40, 0x3c, 0x11, 0x27, 0x08, 0x22, 0xee, 0xbd, 0xcc, 0xc9, 0xac, 0xa8, 0x1e, 0x05, 0x82,
0x99, 0x6d, 0xe7, 0x43, 0x33, 0x90, 0x95, 0x98, 0xa4, 0xe4, 0xc4, 0x09, 0x96, 0x7f, 0xb9, 0xda,
0x14, 0xa1, 0x50, 0x62, 0x64, 0x99, 0x6c, 0x85, 0x5e, 0xb5, 0xd9, 0xa4, 0x2f, 0xd2, 0x1a, 0x08
]);
// Python:
@ -21,10 +22,11 @@ def main() {
// >>> digest.hexdigest()
// 'ec7216058c28201daeb6fd1599b81fdbd40e229b31bea3b6b3190f21db81b01baf3d000e40801ab59551133efbac6cce'
u64[6] h2 = keccak384::<8>([0x2a; 8]);
u8[48] h2 = keccak384::<8>([0x2a; 8]);
assert(h2 == [
0xec7216058c28201d, 0xaeb6fd1599b81fdb, 0xd40e229b31bea3b6,
0xb3190f21db81b01b, 0xaf3d000e40801ab5, 0x9551133efbac6cce
0xec, 0x72, 0x16, 0x05, 0x8c, 0x28, 0x20, 0x1d, 0xae, 0xb6, 0xfd, 0x15, 0x99, 0xb8, 0x1f, 0xdb,
0xd4, 0x0e, 0x22, 0x9b, 0x31, 0xbe, 0xa3, 0xb6, 0xb3, 0x19, 0x0f, 0x21, 0xdb, 0x81, 0xb0, 0x1b,
0xaf, 0x3d, 0x00, 0x0e, 0x40, 0x80, 0x1a, 0xb5, 0x95, 0x51, 0x13, 0x3e, 0xfb, 0xac, 0x6c, 0xce
]);
// Python:
@ -37,10 +39,11 @@ def main() {
// >>> digest.hexdigest()
// '65fc99339a2a40e99d3c40d695b22f278853ca0f925cde4254bcae5e22ece47e6441f91b6568425adc9d95b0072eb49f'
u64[6] h3 = keccak384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
u8[48] h3 = keccak384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x65fc99339a2a40e9, 0x9d3c40d695b22f27, 0x8853ca0f925cde42,
0x54bcae5e22ece47e, 0x6441f91b6568425a, 0xdc9d95b0072eb49f
0x65, 0xfc, 0x99, 0x33, 0x9a, 0x2a, 0x40, 0xe9, 0x9d, 0x3c, 0x40, 0xd6, 0x95, 0xb2, 0x2f, 0x27,
0x88, 0x53, 0xca, 0x0f, 0x92, 0x5c, 0xde, 0x42, 0x54, 0xbc, 0xae, 0x5e, 0x22, 0xec, 0xe4, 0x7e,
0x64, 0x41, 0xf9, 0x1b, 0x65, 0x68, 0x42, 0x5a, 0xdc, 0x9d, 0x95, 0xb0, 0x07, 0x2e, 0xb4, 0x9f
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/keccak/512bit" import keccak512;
import "hashes/keccak/512bit" as keccak512;
def main() {
// Python:
@ -8,10 +8,12 @@ def main() {
// >>> digest.hexdigest()
// 'a470459552991801eca017c8bfeedb376469c9b642a2cca455a3271c5751ad3be53d9f4ddce99613515e954bd3d80d218a2f43f953141ec6bdcaf7ba4a4bad67'
u64[8] h1 = keccak512::<1>([0x2a]);
u8[64] h1 = keccak512::<1>([0x2a]);
assert(h1 == [
0xa470459552991801, 0xeca017c8bfeedb37, 0x6469c9b642a2cca4, 0x55a3271c5751ad3b,
0xe53d9f4ddce99613, 0x515e954bd3d80d21, 0x8a2f43f953141ec6, 0xbdcaf7ba4a4bad67
0xa4, 0x70, 0x45, 0x95, 0x52, 0x99, 0x18, 0x01, 0xec, 0xa0, 0x17, 0xc8, 0xbf, 0xee, 0xdb, 0x37,
0x64, 0x69, 0xc9, 0xb6, 0x42, 0xa2, 0xcc, 0xa4, 0x55, 0xa3, 0x27, 0x1c, 0x57, 0x51, 0xad, 0x3b,
0xe5, 0x3d, 0x9f, 0x4d, 0xdc, 0xe9, 0x96, 0x13, 0x51, 0x5e, 0x95, 0x4b, 0xd3, 0xd8, 0x0d, 0x21,
0x8a, 0x2f, 0x43, 0xf9, 0x53, 0x14, 0x1e, 0xc6, 0xbd, 0xca, 0xf7, 0xba, 0x4a, 0x4b, 0xad, 0x67
]);
// Python:
@ -21,10 +23,12 @@ def main() {
// >>> digest.hexdigest()
// '91e7b4ca7569fb43a180354878bcd807578e207c0dec866d7bc7569d86996a86bce7bd05ab32138797693e76882475a819352919cd81585110e5dfb1c8710337'
u64[8] h2 = keccak512::<8>([0x2a; 8]);
u8[64] h2 = keccak512::<8>([0x2a; 8]);
assert(h2 == [
0x91e7b4ca7569fb43, 0xa180354878bcd807, 0x578e207c0dec866d, 0x7bc7569d86996a86,
0xbce7bd05ab321387, 0x97693e76882475a8, 0x19352919cd815851, 0x10e5dfb1c8710337
0x91, 0xe7, 0xb4, 0xca, 0x75, 0x69, 0xfb, 0x43, 0xa1, 0x80, 0x35, 0x48, 0x78, 0xbc, 0xd8, 0x07,
0x57, 0x8e, 0x20, 0x7c, 0x0d, 0xec, 0x86, 0x6d, 0x7b, 0xc7, 0x56, 0x9d, 0x86, 0x99, 0x6a, 0x86,
0xbc, 0xe7, 0xbd, 0x05, 0xab, 0x32, 0x13, 0x87, 0x97, 0x69, 0x3e, 0x76, 0x88, 0x24, 0x75, 0xa8,
0x19, 0x35, 0x29, 0x19, 0xcd, 0x81, 0x58, 0x51, 0x10, 0xe5, 0xdf, 0xb1, 0xc8, 0x71, 0x03, 0x37
]);
// Python:
@ -37,10 +41,12 @@ def main() {
// >>> digest.hexdigest()
// '3ee2b40047b8060f68c67242175660f4174d0af5c01d47168ec20ed619b0b7c42181f40aa1046f39e2ef9efc6910782a998e0013d172458957957fac9405b67d'
u64[8] h3 = keccak512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
u8[64] h3 = keccak512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x3ee2b40047b8060f, 0x68c67242175660f4, 0x174d0af5c01d4716, 0x8ec20ed619b0b7c4,
0x2181f40aa1046f39, 0xe2ef9efc6910782a, 0x998e0013d1724589, 0x57957fac9405b67d
0x3e, 0xe2, 0xb4, 0x00, 0x47, 0xb8, 0x06, 0x0f, 0x68, 0xc6, 0x72, 0x42, 0x17, 0x56, 0x60, 0xf4,
0x17, 0x4d, 0x0a, 0xf5, 0xc0, 0x1d, 0x47, 0x16, 0x8e, 0xc2, 0x0e, 0xd6, 0x19, 0xb0, 0xb7, 0xc4,
0x21, 0x81, 0xf4, 0x0a, 0xa1, 0x04, 0x6f, 0x39, 0xe2, 0xef, 0x9e, 0xfc, 0x69, 0x10, 0x78, 0x2a,
0x99, 0x8e, 0x00, 0x13, 0xd1, 0x72, 0x45, 0x89, 0x57, 0x95, 0x7f, 0xac, 0x94, 0x05, 0xb6, 0x7d
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/keccak/keccak" import keccak;
import "hashes/keccak/keccak";
def main() {
// Python:
@ -8,8 +8,37 @@ def main() {
// >>> digest.hexdigest()
// 'ca85d1976d40dcb6ca3becc8c6596e83c0774f4185cf016a05834f5856a37f39'
u64[4] h = keccak::<1, 256>([0x7a6f6b7261746573], 0x0000000000000001)[..4];
assert(h == [0xca85d1976d40dcb6, 0xca3becc8c6596e83, 0xc0774f4185cf016a, 0x05834f5856a37f39]);
u8[32] h1 = keccak::<_, 32>([0x7a, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0x65, 0x73], 0x01);
assert(h1 == [
0xca, 0x85, 0xd1, 0x97, 0x6d, 0x40, 0xdc, 0xb6, 0xca, 0x3b, 0xec, 0xc8, 0xc6, 0x59, 0x6e, 0x83,
0xc0, 0x77, 0x4f, 0x41, 0x85, 0xcf, 0x01, 0x6a, 0x05, 0x83, 0x4f, 0x58, 0x56, 0xa3, 0x7f, 0x39
]);
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x2a' * 135)
// >>> digest.hexdigest()
// '723e2ae02ca8d8fb45dca21e5f6369c4f124da72f217dca5e657a4bbc69b917d'
u8[32] h2 = keccak::<_, 32>([0x2a; 135], 0x01);
assert(h2 == [
0x72, 0x3e, 0x2a, 0xe0, 0x2c, 0xa8, 0xd8, 0xfb, 0x45, 0xdc, 0xa2, 0x1e, 0x5f, 0x63, 0x69, 0xc4,
0xf1, 0x24, 0xda, 0x72, 0xf2, 0x17, 0xdc, 0xa5, 0xe6, 0x57, 0xa4, 0xbb, 0xc6, 0x9b, 0x91, 0x7d
]);
// Python:
// >>> from Crypto.Hash import keccak
// >>> digest = keccak.new(digest_bits=256)
// >>> digest.update(b'\x2a' * 136)
// >>> digest.hexdigest()
// 'e60d5160227cb1b8dc8547deb9c6a2c5e6c3306a1ca155611a73ed2c2324bfc0'
u8[32] h3 = keccak::<_, 32>([0x2a; 136], 0x01);
assert(h3 == [
0xe6, 0x0d, 0x51, 0x60, 0x22, 0x7c, 0xb1, 0xb8, 0xdc, 0x85, 0x47, 0xde, 0xb9, 0xc6, 0xa2, 0xc5,
0xe6, 0xc3, 0x30, 0x6a, 0x1c, 0xa1, 0x55, 0x61, 0x1a, 0x73, 0xed, 0x2c, 0x23, 0x24, 0xbf, 0xc0
]);
return;
}

View file

@ -0,0 +1,15 @@
{
"entry_point": "./tests/tests/hashes/sha3/224bit.zok",
"tests": [
{
"input": {
"values": []
},
"output": {
"Ok": {
"value": []
}
}
}
]
}

View file

@ -0,0 +1,47 @@
import "hashes/sha3/224bit" as sha3_224;
def main() {
// Python:
// >>> from Crypto.Hash import SHA3_224
// >>> digest = SHA3_224.new()
// >>> digest.update(b'\x2a')
// >>> digest.hexdigest()
// 'b588579919b3947381b5d6260797296695f30ef82b5a204ec00840e5'
u8[28] h1 = sha3_224::<1>([0x2a]);
assert(h1 == [
0xb5, 0x88, 0x57, 0x99, 0x19, 0xb3, 0x94, 0x73, 0x81, 0xb5, 0xd6, 0x26, 0x07, 0x97,
0x29, 0x66, 0x95, 0xf3, 0x0e, 0xf8, 0x2b, 0x5a, 0x20, 0x4e, 0xc0, 0x08, 0x40, 0xe5
]);
// Python:
// >>> from Crypto.Hash import SHA3_224
// >>> digest = SHA3_224.new()
// >>> digest.update(b'\x2a' * 8)
// >>> digest.hexdigest()
// 'e6005b22af6b0f068cf6b158a607ad5ca1b21ca85f2470e6af4b4ca0'
u8[28] h2 = sha3_224::<8>([0x2a; 8]);
assert(h2 == [
0xe6, 0x00, 0x5b, 0x22, 0xaf, 0x6b, 0x0f, 0x06, 0x8c, 0xf6, 0xb1, 0x58, 0xa6, 0x07,
0xad, 0x5c, 0xa1, 0xb2, 0x1c, 0xa8, 0x5f, 0x24, 0x70, 0xe6, 0xaf, 0x4b, 0x4c, 0xa0
]);
// Python:
// >>> from Crypto.Hash import SHA3_224
// >>> input = "hello world".encode()
// >>> input.hex()
// '68656c6c6f20776f726c64'
// >>> digest = SHA3_224.new()
// >>> digest.update(input)
// >>> digest.hexdigest()
// 'dfb7f18c77e928bb56faeb2da27291bd790bc1045cde45f3210bb6c5'
u8[28] h3 = sha3_224::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0xdf, 0xb7, 0xf1, 0x8c, 0x77, 0xe9, 0x28, 0xbb, 0x56, 0xfa, 0xeb, 0x2d, 0xa2, 0x72,
0x91, 0xbd, 0x79, 0x0b, 0xc1, 0x04, 0x5c, 0xde, 0x45, 0xf3, 0x21, 0x0b, 0xb6, 0xc5
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/sha3/256bit" import sha3_256;
import "hashes/sha3/256bit" as sha3_256;
def main() {
// Python:
@ -8,8 +8,11 @@ def main() {
// >>> digest.hexdigest()
// '82283b4b030589a7aa0ca28b8e933ac0bd89738a0df509806c864366deec31d7'
u64[4] h1 = sha3_256::<1>([0x2a]);
assert(h1 == [0x82283b4b030589a7, 0xaa0ca28b8e933ac0, 0xbd89738a0df50980, 0x6c864366deec31d7]);
u8[32] h1 = sha3_256::<1>([0x2a]);
assert(h1 == [
0x82, 0x28, 0x3b, 0x4b, 0x03, 0x05, 0x89, 0xa7, 0xaa, 0x0c, 0xa2, 0x8b, 0x8e, 0x93, 0x3a, 0xc0,
0xbd, 0x89, 0x73, 0x8a, 0x0d, 0xf5, 0x09, 0x80, 0x6c, 0x86, 0x43, 0x66, 0xde, 0xec, 0x31, 0xd7
]);
// Python:
// >>> from Crypto.Hash import SHA3_256
@ -18,8 +21,11 @@ def main() {
// >>> digest.hexdigest()
// '02794645c5d54624a86e237cda0cbe980075f3908ccb00fd67befd2a0bbe0b35'
u64[4] h2 = sha3_256::<8>([0x2a; 8]);
assert(h2 == [0x02794645c5d54624, 0xa86e237cda0cbe98, 0x0075f3908ccb00fd, 0x67befd2a0bbe0b35]);
u8[32] h2 = sha3_256::<8>([0x2a; 8]);
assert(h2 == [
0x02, 0x79, 0x46, 0x45, 0xc5, 0xd5, 0x46, 0x24, 0xa8, 0x6e, 0x23, 0x7c, 0xda, 0x0c, 0xbe, 0x98,
0x00, 0x75, 0xf3, 0x90, 0x8c, 0xcb, 0x00, 0xfd, 0x67, 0xbe, 0xfd, 0x2a, 0x0b, 0xbe, 0x0b, 0x35
]);
// Python:
// >>> from Crypto.Hash import SHA3_256
@ -31,8 +37,11 @@ def main() {
// >>> digest.hexdigest()
// '644bcc7e564373040999aac89e7622f3ca71fba1d972fd94a31c3bfbf24e3938'
u64[4] h3 = sha3_256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [0x644bcc7e56437304, 0x0999aac89e7622f3, 0xca71fba1d972fd94, 0xa31c3bfbf24e3938]);
u8[32] h3 = sha3_256::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x64, 0x4b, 0xcc, 0x7e, 0x56, 0x43, 0x73, 0x04, 0x09, 0x99, 0xaa, 0xc8, 0x9e, 0x76, 0x22, 0xf3,
0xca, 0x71, 0xfb, 0xa1, 0xd9, 0x72, 0xfd, 0x94, 0xa3, 0x1c, 0x3b, 0xfb, 0xf2, 0x4e, 0x39, 0x38
]);
return;
}

View file

@ -1,4 +1,4 @@
from "hashes/sha3/384bit" import sha3_384;
import "hashes/sha3/384bit" as sha3_384;
def main() {
// Python:
@ -8,10 +8,11 @@ def main() {
// >>> digest.hexdigest()
// '386f0e977e65e7609217714a7cd450e145efbc645ad7c7c78d6c9f12b52cb4df22729b2330b7f5267bac9a5750d9130e'
u64[6] h1 = sha3_384::<1>([0x2a]);
u8[48] h1 = sha3_384::<1>([0x2a]);
assert(h1 == [
0x386f0e977e65e760, 0x9217714a7cd450e1, 0x45efbc645ad7c7c7,
0x8d6c9f12b52cb4df, 0x22729b2330b7f526, 0x7bac9a5750d9130e
0x38, 0x6f, 0x0e, 0x97, 0x7e, 0x65, 0xe7, 0x60, 0x92, 0x17, 0x71, 0x4a, 0x7c, 0xd4, 0x50, 0xe1,
0x45, 0xef, 0xbc, 0x64, 0x5a, 0xd7, 0xc7, 0xc7, 0x8d, 0x6c, 0x9f, 0x12, 0xb5, 0x2c, 0xb4, 0xdf,
0x22, 0x72, 0x9b, 0x23, 0x30, 0xb7, 0xf5, 0x26, 0x7b, 0xac, 0x9a, 0x57, 0x50, 0xd9, 0x13, 0x0e
]);
// Python:
@ -21,10 +22,11 @@ def main() {
// >>> digest.hexdigest()
// 'b5e5109aa62d1633ca3b4c8fcf90b71192b7ebbca1159a65546be6bea5a53f748c513f97556e86d3516b3f9384ff4380'
u64[6] h2 = sha3_384::<8>([0x2a; 8]);
u8[48] h2 = sha3_384::<8>([0x2a; 8]);
assert(h2 == [
0xb5e5109aa62d1633, 0xca3b4c8fcf90b711, 0x92b7ebbca1159a65,
0x546be6bea5a53f74, 0x8c513f97556e86d3, 0x516b3f9384ff4380
0xb5, 0xe5, 0x10, 0x9a, 0xa6, 0x2d, 0x16, 0x33, 0xca, 0x3b, 0x4c, 0x8f, 0xcf, 0x90, 0xb7, 0x11,
0x92, 0xb7, 0xeb, 0xbc, 0xa1, 0x15, 0x9a, 0x65, 0x54, 0x6b, 0xe6, 0xbe, 0xa5, 0xa5, 0x3f, 0x74,
0x8c, 0x51, 0x3f, 0x97, 0x55, 0x6e, 0x86, 0xd3, 0x51, 0x6b, 0x3f, 0x93, 0x84, 0xff, 0x43, 0x80
]);
// Python:
@ -37,10 +39,11 @@ def main() {
// >>> digest.hexdigest()
// '83bff28dde1b1bf5810071c6643c08e5b05bdb836effd70b403ea8ea0a634dc4997eb1053aa3593f590f9c63630dd90b'
u64[6] h3 = sha3_384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
u8[48] h3 = sha3_384::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x83bff28dde1b1bf5, 0x810071c6643c08e5, 0xb05bdb836effd70b,
0x403ea8ea0a634dc4, 0x997eb1053aa3593f, 0x590f9c63630dd90b
0x83, 0xbf, 0xf2, 0x8d, 0xde, 0x1b, 0x1b, 0xf5, 0x81, 0x00, 0x71, 0xc6, 0x64, 0x3c, 0x08, 0xe5,
0xb0, 0x5b, 0xdb, 0x83, 0x6e, 0xff, 0xd7, 0x0b, 0x40, 0x3e, 0xa8, 0xea, 0x0a, 0x63, 0x4d, 0xc4,
0x99, 0x7e, 0xb1, 0x05, 0x3a, 0xa3, 0x59, 0x3f, 0x59, 0x0f, 0x9c, 0x63, 0x63, 0x0d, 0xd9, 0x0b
]);
return;

View file

@ -1,4 +1,4 @@
from "hashes/sha3/512bit" import sha3_512;
import "hashes/sha3/512bit" as sha3_512;
def main() {
// Python:
@ -8,10 +8,12 @@ def main() {
// >>> digest.hexdigest()
// '0f8e235b563113abb8a914eb6efc4a31280f1d2341920dfb88bdd20a00d7e47d601a353e5821142acf0dd9ec53bfe4bfe9a2a16f98933142e1c6938c8939b3a0'
u64[8] h1 = sha3_512::<1>([0x2a]);
u8[64] h1 = sha3_512::<1>([0x2a]);
assert(h1 == [
0x0f8e235b563113ab, 0xb8a914eb6efc4a31, 0x280f1d2341920dfb, 0x88bdd20a00d7e47d,
0x601a353e5821142a, 0xcf0dd9ec53bfe4bf, 0xe9a2a16f98933142, 0xe1c6938c8939b3a0
0x0f, 0x8e, 0x23, 0x5b, 0x56, 0x31, 0x13, 0xab, 0xb8, 0xa9, 0x14, 0xeb, 0x6e, 0xfc, 0x4a, 0x31,
0x28, 0x0f, 0x1d, 0x23, 0x41, 0x92, 0x0d, 0xfb, 0x88, 0xbd, 0xd2, 0x0a, 0x00, 0xd7, 0xe4, 0x7d,
0x60, 0x1a, 0x35, 0x3e, 0x58, 0x21, 0x14, 0x2a, 0xcf, 0x0d, 0xd9, 0xec, 0x53, 0xbf, 0xe4, 0xbf,
0xe9, 0xa2, 0xa1, 0x6f, 0x98, 0x93, 0x31, 0x42, 0xe1, 0xc6, 0x93, 0x8c, 0x89, 0x39, 0xb3, 0xa0
]);
// Python:
@ -21,10 +23,12 @@ def main() {
// >>> digest.hexdigest()
// '5e908c2962bcd38fddd1ae4ed4c44eb3396cad53eb36564881979435e18a8e71eda1cbea2fe0fc6ded0672756312b12f8dad38e7528af173ea10095a28cd5555'
u64[8] h2 = sha3_512::<8>([0x2a; 8]);
u8[64] h2 = sha3_512::<8>([0x2a; 8]);
assert(h2 == [
0x5e908c2962bcd38f, 0xddd1ae4ed4c44eb3, 0x396cad53eb365648, 0x81979435e18a8e71,
0xeda1cbea2fe0fc6d, 0xed0672756312b12f, 0x8dad38e7528af173, 0xea10095a28cd5555
0x5e, 0x90, 0x8c, 0x29, 0x62, 0xbc, 0xd3, 0x8f, 0xdd, 0xd1, 0xae, 0x4e, 0xd4, 0xc4, 0x4e, 0xb3,
0x39, 0x6c, 0xad, 0x53, 0xeb, 0x36, 0x56, 0x48, 0x81, 0x97, 0x94, 0x35, 0xe1, 0x8a, 0x8e, 0x71,
0xed, 0xa1, 0xcb, 0xea, 0x2f, 0xe0, 0xfc, 0x6d, 0xed, 0x06, 0x72, 0x75, 0x63, 0x12, 0xb1, 0x2f,
0x8d, 0xad, 0x38, 0xe7, 0x52, 0x8a, 0xf1, 0x73, 0xea, 0x10, 0x09, 0x5a, 0x28, 0xcd, 0x55, 0x55
]);
// Python:
@ -37,10 +41,12 @@ def main() {
// >>> digest.hexdigest()
// '840006653e9ac9e95117a15c915caab81662918e925de9e004f774ff82d7079a40d4d27b1b372657c61d46d470304c88c788b3a4527ad074d1dccbee5dbaa99a'
u64[8] h3 = sha3_512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
u8[64] h3 = sha3_512::<11>([0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64]);
assert(h3 == [
0x840006653e9ac9e9, 0x5117a15c915caab8, 0x1662918e925de9e0, 0x04f774ff82d7079a,
0x40d4d27b1b372657, 0xc61d46d470304c88, 0xc788b3a4527ad074, 0xd1dccbee5dbaa99a
0x84, 0x00, 0x06, 0x65, 0x3e, 0x9a, 0xc9, 0xe9, 0x51, 0x17, 0xa1, 0x5c, 0x91, 0x5c, 0xaa, 0xb8,
0x16, 0x62, 0x91, 0x8e, 0x92, 0x5d, 0xe9, 0xe0, 0x04, 0xf7, 0x74, 0xff, 0x82, 0xd7, 0x07, 0x9a,
0x40, 0xd4, 0xd2, 0x7b, 0x1b, 0x37, 0x26, 0x57, 0xc6, 0x1d, 0x46, 0xd4, 0x70, 0x30, 0x4c, 0x88,
0xc7, 0x88, 0xb3, 0xa4, 0x52, 0x7a, 0xd0, 0x74, 0xd1, 0xdc, 0xcb, 0xee, 0x5d, 0xba, 0xa9, 0x9a
]);
return;