diff --git a/Cargo.lock b/Cargo.lock index 59a707f5..f032ccdb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,15 @@ version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "arrayvec" version = "0.5.2" @@ -327,6 +336,17 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "blake2-rfc_bellman_edition" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc60350286c7c3db13b98e91dbe5c8b6830a6821bc20af5b0c310ce94d74915" +dependencies = [ + "arrayvec 0.4.12", + "byteorder", + "constant_time_eq", +] + [[package]] name = "blake2b_simd" version = "0.5.11" @@ -334,7 +354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.5.2", "constant_time_eq", ] @@ -562,6 +582,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-mac" version = "0.7.0" @@ -1080,6 +1106,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "num" version = "0.1.42" @@ -1566,6 +1598,23 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "sapling-crypto_ce" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c4ff5309ec3e4bd800ad4ab3f71e9b76e9ea81c9f0eda6efa16008afbe440b3" +dependencies = [ + "bellman_ce", + "blake2-rfc_bellman_edition", + "byteorder", + "digest", + "rand 0.4.6", + "serde", + "serde_derive", + "sha2", + "tiny-keccak", +] + [[package]] name = "scoped-tls" version = "1.0.0" @@ -1785,6 +1834,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinyvec" version = "1.1.0" @@ -2159,6 +2217,7 @@ dependencies = [ "typed-arena", "wasm-bindgen-test", "zokrates_common", + "zokrates_embed", "zokrates_field", "zokrates_pest_ast", ] @@ -2171,6 +2230,14 @@ dependencies = [ "zokrates_test_derive", ] +[[package]] +name = "zokrates_embed" +version = "0.1.1" +dependencies = [ + "bellman_ce", + "sapling-crypto_ce", +] + [[package]] name = "zokrates_field" version = "0.3.7" diff --git a/Cargo.toml b/Cargo.toml index 889f4c86..50d4c4ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "zokrates_cli", "zokrates_fs_resolver", "zokrates_stdlib", + "zokrates_embed", "zokrates_abi", "zokrates_test", "zokrates_core_test", diff --git a/zokrates_core/Cargo.toml b/zokrates_core/Cargo.toml index 6a145846..3b9485f3 100644 --- a/zokrates_core/Cargo.toml +++ b/zokrates_core/Cargo.toml @@ -31,6 +31,7 @@ regex = "0.2" zokrates_field = { version = "0.3.0", path = "../zokrates_field", default-features = false } zokrates_pest_ast = { version = "0.1.0", path = "../zokrates_pest_ast" } zokrates_common = { path = "../zokrates_common" } +zokrates_embed = { path = "../zokrates_embed" } rand_0_4 = { version = "0.4", package = "rand" } rand_0_7 = { version = "0.7", package = "rand" } csv = "1" diff --git a/zokrates_core/src/embed.rs b/zokrates_core/src/embed.rs index 8f3f044d..9a53f611 100644 --- a/zokrates_core/src/embed.rs +++ b/zokrates_core/src/embed.rs @@ -6,13 +6,24 @@ use crate::solvers::Solver; use crate::typed_absy::types::{ConcreteFunctionKey, ConcreteSignature, ConcreteType}; use crate::typed_absy::TypedModuleId; use std::collections::HashMap; -use zokrates_field::Field; +use zokrates_field::{Bn128Field, Field}; + +cfg_if::cfg_if! { + if #[cfg(feature = "bellman")] { + use pairing_ce::bn256::Bn256; + use pairing_ce::ff::{PrimeField, PrimeFieldRepr}; + use pairing_ce::Engine; + use zokrates_embed::{generate_sha256_round_constraints, BellmanConstraint}; + } +} /// A low level function that contains non-deterministic introduction of variables. It is carried out as is until /// the flattening step when it can be inlined. #[derive(Debug, Clone, PartialEq, Hash)] pub enum FlatEmbed { U32ToField, + #[cfg(feature = "bellman")] + Sha256Round, Unpack(usize), U8ToBits, U16ToBits, @@ -52,6 +63,13 @@ impl FlatEmbed { FlatEmbed::U32FromBits => ConcreteSignature::new() .outputs(vec![ConcreteType::uint(32)]) .inputs(vec![ConcreteType::array((ConcreteType::Boolean, 32usize))]), + #[cfg(feature = "bellman")] + FlatEmbed::Sha256Round => ConcreteSignature::new() + .inputs(vec![ + ConcreteType::array((ConcreteType::Boolean, 512usize)), + ConcreteType::array((ConcreteType::Boolean, 256usize)), + ]) + .outputs(vec![ConcreteType::array((ConcreteType::Boolean, 256usize))]), } } @@ -65,6 +83,8 @@ impl FlatEmbed { pub fn id(&self) -> &'static str { match self { FlatEmbed::U32ToField => "_U32_TO_FIELD", + #[cfg(feature = "bellman")] + FlatEmbed::Sha256Round => "_SHA256_ROUND", FlatEmbed::Unpack(_) => "_UNPACK", FlatEmbed::U8ToBits => "_U8_TO_BITS", FlatEmbed::U16ToBits => "_U16_TO_BITS", @@ -78,12 +98,137 @@ impl FlatEmbed { /// Actually get the `FlatFunction` that this `FlatEmbed` represents pub fn synthetize(&self) -> FlatFunction { match self { + #[cfg(feature = "bellman")] + FlatEmbed::Sha256Round => sha256_round(), FlatEmbed::Unpack(bitwidth) => unpack_to_bitwidth(*bitwidth), _ => unreachable!(), } } } +// util to convert a vector of `(variable_id, coefficient)` to a flat_expression +// we build a binary tree of additions by splitting the vector recursively +#[cfg(feature = "bellman")] +fn flat_expression_from_vec(v: &[(usize, E::Fr)]) -> FlatExpression { + match v.len() { + 0 => FlatExpression::Number(T::zero()), + 1 => { + let (key, val) = v[0]; + let mut res: Vec = vec![]; + val.into_repr().write_le(&mut res).unwrap(); + FlatExpression::Mult( + box FlatExpression::Number(T::from_byte_vector(res)), + box FlatExpression::Identifier(FlatVariable::new(key)), + ) + } + n => { + let (u, v) = v.split_at(n / 2); + FlatExpression::Add( + box flat_expression_from_vec::(u), + box flat_expression_from_vec::(v), + ) + } + } +} + +#[cfg(feature = "bellman")] +impl From> for FlatStatement { + fn from(c: BellmanConstraint) -> FlatStatement { + let rhs_a = flat_expression_from_vec::(&c.a); + let rhs_b = flat_expression_from_vec::(&c.b); + let lhs = flat_expression_from_vec::(&c.c); + + FlatStatement::Condition(lhs, FlatExpression::Mult(box rhs_a, box rhs_b)) + } +} + +/// Returns a flat function which computes a sha256 round +/// +/// # Remarks +/// +/// The variables inside the function are set in this order: +/// - constraint system variables +/// - arguments +#[cfg(feature = "bellman")] +pub fn sha256_round() -> FlatFunction { + assert_eq!(T::id(), Bn128Field::id()); + + // Define iterators for all indices at hand + let (r1cs, input_indices, current_hash_indices, output_indices) = + generate_sha256_round_constraints::(); + // indices of the input + let input_indices = input_indices.into_iter(); + // indices of the current hash + let current_hash_indices = current_hash_indices.into_iter(); + // indices of the output + let output_indices = output_indices.into_iter(); + let variable_count = r1cs.aux_count + 1; // auxiliary and ONE + // indices of the sha256round constraint system variables + let cs_indices = 0..variable_count; + // indices of the arguments to the function + // apply an offset of `variable_count` to get the indice of our dummy `input` argument + let input_argument_indices = input_indices + .clone() + .into_iter() + .map(|i| i + variable_count); + // apply an offset of `variable_count` to get the indice of our dummy `current_hash` argument + let current_hash_argument_indices = current_hash_indices + .clone() + .into_iter() + .map(|i| i + variable_count); + // define parameters to the function based on the variables + let arguments = input_argument_indices + .clone() + .chain(current_hash_argument_indices.clone()) + .map(|i| FlatParameter { + id: FlatVariable::new(i), + private: true, + }) + .collect(); + // define a binding of the first variable in the constraint system to one + let one_binding_statement = FlatStatement::Condition( + FlatVariable::new(0).into(), + FlatExpression::Number(T::from(1)), + ); + let input_binding_statements = + // bind input and current_hash to inputs + input_indices.chain(current_hash_indices).zip(input_argument_indices.clone().chain(current_hash_argument_indices.clone())).map(|(cs_index, argument_index)| { + FlatStatement::Condition( + FlatVariable::new(cs_index).into(), + FlatVariable::new(argument_index).into(), + ) + }); + // insert flattened statements to represent constraints + let constraint_statements = r1cs.constraints.into_iter().map(|c| c.into()); + // define which subset of the witness is returned + let outputs: Vec> = output_indices + .map(|o| FlatExpression::Identifier(FlatVariable::new(o))) + .collect(); + // insert a directive to set the witness based on the bellman gadget and inputs + let directive_statement = FlatStatement::Directive(FlatDirective { + outputs: cs_indices.map(FlatVariable::new).collect(), + inputs: input_argument_indices + .chain(current_hash_argument_indices) + .map(|i| FlatVariable::new(i).into()) + .collect(), + solver: Solver::Sha256Round, + }); + // insert a statement to return the subset of the witness + let return_statement = FlatStatement::Return(FlatExpressionList { + expressions: outputs, + }); + let statements = std::iter::once(directive_statement) + .chain(std::iter::once(one_binding_statement)) + .chain(input_binding_statements) + .chain(constraint_statements) + .chain(std::iter::once(return_statement)) + .collect(); + FlatFunction { + arguments, + statements, + } +} + fn use_variable( layout: &mut HashMap, name: String, @@ -231,4 +376,86 @@ mod tests { ); } } + + #[cfg(feature = "bellman")] + #[cfg(test)] + mod sha256 { + use super::*; + use crate::ir::Interpreter; + + #[test] + fn generate_sha256_constraints() { + let compiled = sha256_round::(); + + // function should have 768 inputs + assert_eq!(compiled.arguments.len(), 768); + + // function should return 256 values + assert_eq!( + compiled + .statements + .iter() + .filter_map(|s| match s { + FlatStatement::Return(v) => Some(v), + _ => None, + }) + .next() + .unwrap() + .expressions + .len(), + 256, + ); + + // directive should take 768 inputs and return n_var outputs + let directive = compiled + .statements + .iter() + .filter_map(|s| match s { + FlatStatement::Directive(d) => Some(d.clone()), + _ => None, + }) + .next() + .unwrap(); + assert_eq!(directive.inputs.len(), 768); + assert_eq!(directive.outputs.len(), 26935); + // function input should be offset by variable_count + assert_eq!( + compiled.arguments[0].id, + FlatVariable::new(directive.outputs.len() + 1) + ); + + // bellman variable #0: index 0 should equal 1 + assert_eq!( + compiled.statements[1], + FlatStatement::Condition( + FlatVariable::new(0).into(), + FlatExpression::Number(Bn128Field::from(1)) + ) + ); + + // bellman input #0: index 1 should equal zokrates input #0: index v_count + assert_eq!( + compiled.statements[2], + FlatStatement::Condition( + FlatVariable::new(1).into(), + FlatVariable::new(26936).into() + ) + ); + + let f = crate::ir::Function::from(compiled); + let prog = crate::ir::Prog { + main: f, + private: vec![true; 768], + }; + + let input: Vec<_> = (0..512) + .map(|_| 0) + .chain((0..256).map(|_| 1)) + .map(|i| Bn128Field::from(i)) + .collect(); + + let interpreter = Interpreter::default(); + interpreter.execute(&prog, &input).unwrap(); + } + } } diff --git a/zokrates_core/src/flatten/mod.rs b/zokrates_core/src/flatten/mod.rs index 3a361b84..6bbb82de 100644 --- a/zokrates_core/src/flatten/mod.rs +++ b/zokrates_core/src/flatten/mod.rs @@ -10,9 +10,9 @@ mod utils; use self::utils::flat_expression_from_bits; +use crate::ir::Interpreter; use crate::flat_absy::*; -use crate::ir; use crate::solvers::Solver; use crate::zir::types::{FunctionIdentifier, FunctionKey, Signature, Type, UBitwidth}; use crate::zir::*; @@ -1744,7 +1744,7 @@ impl<'ast, T: Field> Flattener<'ast, T> { // constants do not require directives if let Some(FlatExpression::Number(ref x)) = e.field { - let bits: Vec<_> = ir::Interpreter::default() + let bits: Vec<_> = Interpreter::default() .execute_solver(&Solver::bits(to), &[x.clone()]) .unwrap() .into_iter() diff --git a/zokrates_core/src/imports.rs b/zokrates_core/src/imports.rs index 1ac8ba2f..842c25e4 100644 --- a/zokrates_core/src/imports.rs +++ b/zokrates_core/src/imports.rs @@ -16,7 +16,7 @@ use std::path::{Path, PathBuf}; use typed_arena::Arena; use zokrates_common::Resolver; -use zokrates_field::Field; +use zokrates_field::{Bn128Field, Field}; #[derive(PartialEq, Debug)] pub struct Error { @@ -144,6 +144,30 @@ impl Importer { // handle the case of special bellman and packing imports if import.source.starts_with("EMBED") { match import.source.to_str().unwrap() { + #[cfg(feature = "bellman")] + "EMBED/sha256round" => { + if T::id() != Bn128Field::id() { + return Err(CompileErrorInner::ImportError( + Error::new(format!( + "Embed sha256round cannot be used with curve {}", + T::name() + )) + .with_pos(Some(pos)), + ) + .in_file(&location) + .into()); + } else { + let alias = alias.unwrap_or("sha256round"); + + symbols.push( + SymbolDeclaration { + id: &alias, + symbol: Symbol::Flat(FlatEmbed::Sha256Round), + } + .start_end(pos.0, pos.1), + ); + } + } "EMBED/unpack" => { let alias = alias.unwrap_or("unpack"); diff --git a/zokrates_core/src/ir/interpreter.rs b/zokrates_core/src/ir/interpreter.rs index 11e8de67..69ffacf1 100644 --- a/zokrates_core/src/ir/interpreter.rs +++ b/zokrates_core/src/ir/interpreter.rs @@ -2,9 +2,12 @@ use crate::flat_absy::flat_variable::FlatVariable; use crate::ir::Directive; use crate::ir::{LinComb, Prog, QuadComb, Statement, Witness}; use crate::solvers::Solver; +use pairing_ce::bn256::Bn256; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; use std::fmt; +#[cfg(feature = "bellman")] +use zokrates_embed::generate_sha256_round_witness; use zokrates_field::Field; pub type ExecutionResult = Result, Error>; @@ -191,6 +194,7 @@ impl Interpreter { let c = inputs[2].clone(); vec![a * (b - c.clone()) + c] } + Solver::Div => vec![inputs[0] .clone() .checked_div(&inputs[1]) @@ -205,6 +209,30 @@ impl Interpreter { let r = n - d * &q; vec![T::try_from(q).unwrap(), T::try_from(r).unwrap()] } + #[cfg(feature = "bellman")] + Solver::Sha256Round => { + use zokrates_field::Bn128Field; + assert_eq!(T::id(), Bn128Field::id()); + let i = &inputs[0..512]; + let h = &inputs[512..]; + let to_fr = |x: &T| { + use pairing_ce::ff::{PrimeField, ScalarEngine}; + let s = x.to_dec_string(); + ::Fr::from_str(&s).unwrap() + }; + let i: Vec<_> = i.iter().map(|x| to_fr(x)).collect(); + let h: Vec<_> = h.iter().map(|x| to_fr(x)).collect(); + assert_eq!(h.len(), 256); + generate_sha256_round_witness::(&i, &h) + .into_iter() + .map(|x| { + use bellman_ce::pairing::ff::{PrimeField, PrimeFieldRepr}; + let mut res: Vec = vec![]; + x.into_repr().write_le(&mut res).unwrap(); + T::from_byte_vector(res) + }) + .collect() + } }; assert_eq!(res.len(), expected_output_count); diff --git a/zokrates_core/src/solvers/mod.rs b/zokrates_core/src/solvers/mod.rs index f9c6e1c4..d6bc0c0c 100644 --- a/zokrates_core/src/solvers/mod.rs +++ b/zokrates_core/src/solvers/mod.rs @@ -1,6 +1,5 @@ use serde::{Deserialize, Serialize}; use std::fmt; -use zokrates_field::Field; #[derive(Clone, PartialEq, Debug, Serialize, Deserialize, Hash, Eq)] pub enum Solver { @@ -12,6 +11,8 @@ pub enum Solver { ShaAndXorAndXorAnd, ShaCh, EuclideanDiv, + #[cfg(feature = "bellman")] + Sha256Round, } impl fmt::Display for Solver { @@ -31,6 +32,8 @@ impl Solver { Solver::ShaAndXorAndXorAnd => (3, 1), Solver::ShaCh => (3, 1), Solver::EuclideanDiv => (2, 2), + #[cfg(feature = "bellman")] + Solver::Sha256Round => (768, 26935), } } } @@ -40,11 +43,3 @@ impl Solver { Solver::Bits(width) } } - -pub trait Executable: Signed { - fn execute(&self, inputs: &[T]) -> Result, String>; -} - -pub trait Signed { - fn get_signature(&self) -> (usize, usize); -} diff --git a/zokrates_core_test/tests/tests/generics/cache.json b/zokrates_core_test/tests/tests/generics/cache.json new file mode 100644 index 00000000..749eefef --- /dev/null +++ b/zokrates_core_test/tests/tests/generics/cache.json @@ -0,0 +1,17 @@ +{ + "curves": ["Bn128", "Bls12_381"], + "tests": [ + { + "input": { + "values": [ + ] + }, + "output": { + "Ok": { + "values": [ + ] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_core_test/tests/tests/generics/cache.zok b/zokrates_core_test/tests/tests/generics/cache.zok new file mode 100644 index 00000000..2a2f1751 --- /dev/null +++ b/zokrates_core_test/tests/tests/generics/cache.zok @@ -0,0 +1,7 @@ +def id() -> u32: + return N + +def main(): + assert(id::<5>() == 5) + assert(id::<6>() == 6) + return \ No newline at end of file diff --git a/zokrates_embed/Cargo.toml b/zokrates_embed/Cargo.toml new file mode 100644 index 00000000..90e9cccb --- /dev/null +++ b/zokrates_embed/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "zokrates_embed" +version = "0.1.1" +authors = ["schaeff "] +edition = "2018" + +[features] +default = [] +wasm = ["bellman_ce/wasm", "sapling-crypto_ce/wasm"] +multicore = ["bellman_ce/multicore", "sapling-crypto_ce/multicore"] + +[dependencies] +bellman_ce = { version = "^0.3", default-features = false } +sapling-crypto_ce = { version = "^0.1", default-features = false } \ No newline at end of file diff --git a/zokrates_embed/src/lib.rs b/zokrates_embed/src/lib.rs new file mode 100644 index 00000000..8d689055 --- /dev/null +++ b/zokrates_embed/src/lib.rs @@ -0,0 +1,319 @@ +extern crate sapling_crypto_ce as sapling_crypto; +use sapling_crypto::bellman; + +use bellman::{ + pairing::{ff::Field, Engine}, + ConstraintSystem, Index, LinearCombination, SynthesisError, Variable, +}; +use sapling_crypto::circuit::{ + boolean::{AllocatedBit, Boolean}, + sha256::sha256_compression_function, + uint32::UInt32, +}; + +#[derive(Debug)] +pub struct BellmanR1CS { + pub aux_count: usize, + pub constraints: Vec>, +} + +impl BellmanR1CS { + pub fn new() -> Self { + BellmanR1CS { + aux_count: 0, + constraints: vec![], + } + } +} + +#[derive(Debug)] +pub struct BellmanWitness { + pub values: Vec, +} + +#[derive(Debug, PartialEq)] +pub struct BellmanConstraint { + pub a: Vec<(usize, E::Fr)>, + pub b: Vec<(usize, E::Fr)>, + pub c: Vec<(usize, E::Fr)>, +} + +fn sha256_round>( + mut cs: CS, + input: &Vec>, + current_hash: &Vec>, +) -> Result<(Vec, Vec, Vec), SynthesisError> { + // Allocate bits for `input` + let input_bits = input + .iter() + .enumerate() + .map(|(index, i)| { + AllocatedBit::alloc::( + &mut cs.namespace(|| format!("input_{}", index)), + Some(*i == Some(::one())), + ) + .unwrap() + }) + .collect::>(); + + // Define Booleans whose values are the defined bits + let input = input_bits + .iter() + .map(|i| Boolean::Is(i.clone())) + .collect::>(); + + // Allocate bits for `current_hash` + let current_hash_bits = current_hash + .iter() + .enumerate() + .map(|(index, i)| { + AllocatedBit::alloc::( + &mut cs.namespace(|| format!("current_hash_{}", index)), + Some(*i == Some(::one())), + ) + .unwrap() + }) + .collect::>(); + + // Define Booleans whose values are the defined bits + let current_hash = current_hash_bits + .chunks(32) + .map(|chunk| { + UInt32::from_bits_be( + &chunk + .into_iter() + .map(|i| Boolean::Is(i.clone())) + .collect::>(), + ) + }) + .collect::>(); + + // Apply the compression function, returning the 8 bytes of outputs + let res = sha256_compression_function::(&mut cs, &input, ¤t_hash).unwrap(); + + // Extract the 256 bits of output out of the 8 bytes + let output_bits = res + .into_iter() + .flat_map(|u| u.into_bits_be()) + .map(|b| b.get_variable().unwrap().clone()) + .collect::>(); + + // Return indices of `input`, `current_hash` and `output` in the CS + Ok(( + input_bits + .into_iter() + .map(|b| var_to_index(b.get_variable())) + .collect(), + current_hash_bits + .into_iter() + .map(|b| var_to_index(b.get_variable())) + .collect(), + output_bits + .into_iter() + .map(|b| var_to_index(b.get_variable())) + .collect(), + )) +} + +impl ConstraintSystem for BellmanWitness { + type Root = Self; + + fn alloc(&mut self, _: A, f: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + let index = self.values.len(); + let var = Variable::new_unchecked(Index::Aux(index)); + self.values.push(f().unwrap()); + Ok(var) + } + + fn alloc_input(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + unreachable!("Bellman helpers are not allowed to allocate public variables") + } + + fn enforce(&mut self, _: A, _: LA, _: LB, _: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, + { + // do nothing + } + + fn push_namespace(&mut self, _: N) + where + NR: Into, + N: FnOnce() -> NR, + { + // do nothing + } + + fn pop_namespace(&mut self) { + // do nothing + } + + fn get_root(&mut self) -> &mut Self::Root { + self + } +} + +impl ConstraintSystem for BellmanR1CS { + type Root = Self; + + fn alloc(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + // we don't care about the value as we're only generating the CS + let index = self.aux_count; + let var = Variable::new_unchecked(Index::Aux(index)); + self.aux_count += 1; + Ok(var) + } + + fn alloc_input(&mut self, _: A, _: F) -> Result + where + F: FnOnce() -> Result, + A: FnOnce() -> AR, + AR: Into, + { + unreachable!("Bellman helpers are not allowed to allocate public variables") + } + + fn enforce(&mut self, _: A, a: LA, b: LB, c: LC) + where + A: FnOnce() -> AR, + AR: Into, + LA: FnOnce(LinearCombination) -> LinearCombination, + LB: FnOnce(LinearCombination) -> LinearCombination, + LC: FnOnce(LinearCombination) -> LinearCombination, + { + let a = a(LinearCombination::zero()); + let b = b(LinearCombination::zero()); + let c = c(LinearCombination::zero()); + + let a = a + .as_ref() + .into_iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + let b = b + .as_ref() + .into_iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + let c = c + .as_ref() + .into_iter() + .map(|(variable, coefficient)| (var_to_index(*variable), *coefficient)) + .collect(); + + self.constraints.push(BellmanConstraint { a, b, c }); + } + + fn push_namespace(&mut self, _: N) + where + NR: Into, + N: FnOnce() -> NR, + { + // do nothing + } + + fn pop_namespace(&mut self) { + // do nothing + } + + fn get_root(&mut self) -> &mut Self::Root { + self + } +} + +pub fn generate_sha256_round_constraints( +) -> (BellmanR1CS, Vec, Vec, Vec) { + let mut cs = BellmanR1CS::new(); + + let (input_bits, current_hash_bits, output_bits) = + sha256_round(&mut cs, &vec![None; 512], &vec![None; 256]).unwrap(); + + // res is now the allocated bits for `input`, `current_hash` and `sha256_output` + + (cs, input_bits, current_hash_bits, output_bits) +} + +pub fn generate_sha256_round_witness( + input: &[E::Fr], + current_hash: &[E::Fr], +) -> Vec { + assert_eq!(input.len(), 512); + assert_eq!(current_hash.len(), 256); + + let mut cs: BellmanWitness = BellmanWitness { + values: vec![::one()], + }; + + sha256_round( + &mut cs, + &input.iter().map(|x| Some(x.clone())).collect(), + ¤t_hash.iter().map(|x| Some(x.clone())).collect(), + ) + .unwrap(); + + cs.values +} + +fn var_to_index(v: Variable) -> usize { + match v.get_unchecked() { + Index::Aux(i) => i + 1, + Index::Input(0) => 0, + _ => unreachable!("No public variables should have been allocated"), + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bellman::pairing::bn256::{Bn256, Fr}; + + #[test] + fn generate_constraints() { + let (_c, input, current_hash, output) = generate_sha256_round_constraints::(); + assert_eq!(input.len(), 512); + assert_eq!(current_hash.len(), 256); + assert_eq!(output.len(), 256); + } + + #[test] + fn generate_witness() { + let witness = + generate_sha256_round_witness::(&vec![Fr::one(); 512], &vec![Fr::zero(); 256]); + assert_eq!(witness.len(), 26935); + } + + #[test] + fn test_cs() { + use sapling_crypto::circuit::test::TestConstraintSystem; + + let mut cs: TestConstraintSystem = TestConstraintSystem::new(); + + let _ = sha256_round( + &mut cs, + &vec![Some(Fr::zero()); 512], + &vec![Some(Fr::one()); 256], + ) + .unwrap(); + + assert!(cs.is_satisfied()); + } +} diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok new file mode 100644 index 00000000..b332c9c2 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bit.zok @@ -0,0 +1,13 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 4 bool[256] arrays as inputs +// and applies 2 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): + + bool[256] IV = IVconstants() + bool[256] digest1 = sha256(a, b, IV) + bool[256] digest2 = sha256(c, d, digest1) + + return digest2 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok new file mode 100644 index 00000000..65592589 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1024bitPadded.zok @@ -0,0 +1,16 @@ +import "./1536bit" as sha256 + +// Take two bool[256] arrays as input +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d) -> (bool[256]): + + // Hash is computed on the full 1024bit block size + // padding does not fit in the first two blocks + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + // total length of message is 1024 bits: 0b10000000000 + bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false] + + bool[256] digest = sha256(a, b, c, d, dummyblock1, dummyblock2) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok new file mode 100644 index 00000000..c7ce4a9c --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/1536bit.zok @@ -0,0 +1,14 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 6 bool[256] arrays as inputs +// and applies 3 rounds of sha256 compression. +// It returns an array of 256 bool. +def main(bool[256] a, bool[256] b, bool[256] c, bool[256] d, bool[256] e, bool[256] f) -> (bool[256]): + + bool[256] IV = IVconstants() + bool[256] digest1 = sha256(a, b, IV) + bool[256] digest2 = sha256(c, d, digest1) + bool[256] digest3 = sha256(e, f, digest2) + + return digest3 \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok new file mode 100644 index 00000000..c12adb42 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/256bitPadded.zok @@ -0,0 +1,30 @@ +import "./512bit" as sha256 + +// A function that takes 1 bool[256] array as input +// and returns the sha256 full round output as an array of 256 bool. +def main(bool[256] a) -> (bool[256]): + + // Hash is computed on 256 bits of input + // padding fits in the remaining 256 bits of the first block + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [ \ + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0] + + bool[256] digest = sha256(a, dummyblock1) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok new file mode 100644 index 00000000..a05d4a70 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bit.zok @@ -0,0 +1,15 @@ +import "./IVconstants" as IVconstants +import "./shaRoundNoBoolCheck" as sha256 + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 compression function as an array of 256 bool. +// In contrast to full_round.zok no padding is being applied +def main(bool[256] a, bool[256] b) -> (bool[256]): + + // a and b is NOT checked to be of type bool + + bool[256] IV = IVconstants() + bool[256] digest = sha256(a, b, IV) + //digest is constraint to be of type bool + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok new file mode 100644 index 00000000..d518d3d5 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPacked.zok @@ -0,0 +1,23 @@ +import "../../../utils/pack/bool/pack128" as pack128 +import "../../../utils/pack/bool/unpack128" as unpack128 +import "./512bitPadded" as sha256 + +// A function that takes an array of 4 field elements as inputs, unpacks each of them to 128 +// bits (big endian), concatenates them and applies sha256. +// It then returns an array of two field elements, each representing 128 bits of the result. +def main(field[4] preimage) -> (field[2]): + + bool[128] a = unpack128(preimage[0]) + bool[128] b = unpack128(preimage[1]) + bool[128] c = unpack128(preimage[2]) + bool[128] d = unpack128(preimage[3]) + + bool[256] lhs = [...a, ...b] + bool[256] rhs = [...c, ...d] + + bool[256] r = sha256(lhs, rhs) + + field res0 = pack128(r[..128]) + field res1 = pack128(r[128..]) + + return [res0, res1] \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok new file mode 100644 index 00000000..7c195915 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/512bitPadded.zok @@ -0,0 +1,17 @@ +import "./1024bit" as sha256 + +// A function that takes 2 bool[256] arrays as inputs +// and returns their sha256 full round output as an array of 256 bool. +def main(bool[256] a, bool[256] b) -> (bool[256]): + + // Hash is computed on the full 512bit block size + // padding does not fit in the primary block + // add dummy block (single "1" followed by "0" + total length) + bool[256] dummyblock1 = [true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + + // total length of message is 512 bits: 0b1000000000 + bool[256] dummyblock2 = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false] + + bool[256] digest = sha256(a, b, dummyblock1, dummyblock2) + + return digest \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok new file mode 100644 index 00000000..56554cff --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/IVconstants.zok @@ -0,0 +1,15 @@ +// SHA-256 is specified in FIPS 180-3 and initial values are listed in section 5.3.3 +// https://csrc.nist.gov/csrc/media/publications/fips/180/3/archive/2008-10-31/documents/fips180-3_final.pdf +def main() -> (bool[256]): + bool[32] h0 = [false, true, true, false, true, false, true, false, false, false, false, false, true, false, false, true, true, true, true, false, false, true, true, false, false, true, true, false, false, true, true, true] + bool[32] h1 = [true, false, true, true, true, false, true, true, false, true, true, false, false, true, true, true, true, false, true, false, true, true, true, false, true, false, false, false, false, true, false, true] + bool[32] h2 = [false, false, true, true, true, true, false, false, false, true, true, false, true, true, true, false, true, true, true, true, false, false, true, true, false, true, true, true, false, false, true, false] + bool[32] h3 = [true, false, true, false, false, true, false, true, false, true, false, false, true, true, true, true, true, true, true, true, false, true, false, true, false, false, true, true, true, false, true, false] + bool[32] h4 = [false, true, false, true, false, false, false, true, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, false, true, true, true, true, true, true, true] + bool[32] h5 = [true, false, false, true, true, false, true, true, false, false, false, false, false, true, false, true, false, true, true, false, true, false, false, false, true, false, false, false, true, true, false, false] + bool[32] h6 = [false, false, false, true, true, true, true, true, true, false, false, false, false, false, true, true, true, true, false, true, true, false, false, true, true, false, true, false, true, false, true, true] + bool[32] h7 = [false, true, false, true, true, false, true, true, true, true, true, false, false, false, false, false, true, true, false, false, true, true, false, true, false, false, false, true, true, false, false, true] + + bool[256] IV = [...h0, ...h1, ...h2, ...h3, ...h4, ...h5, ...h6, ...h7] + + return IV \ No newline at end of file diff --git a/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok new file mode 100644 index 00000000..1f971ae0 --- /dev/null +++ b/zokrates_stdlib/stdlib/hashes/sha256/embed/shaRoundNoBoolCheck.zok @@ -0,0 +1,8 @@ +#pragma curve bn128 +import "EMBED/sha256round" as sha256round + +// a and b is NOT checked to be 0 or 1 +// the return value is checked to be 0 or 1 +// IV vector is checked to be of type bool +def main(bool[256] a, bool[256] b, bool[256] IV) -> (bool[256]): + return sha256round([...a, ...b], IV) \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json new file mode 100644 index 00000000..fe3a97b7 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.json @@ -0,0 +1,15 @@ +{ + "entry_point": "./tests/tests/hashes/sha256/embed/1024bitPadded.zok", + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.zok b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.zok new file mode 100644 index 00000000..93140849 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/1024bitPadded.zok @@ -0,0 +1,13 @@ +import "hashes/sha256/embed/1024bitPadded" as sha256 +def main() -> (field): + + bool[256] a = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] b = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] c = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] d = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true] + + bool[256] digest = sha256(a, b, c, d) + + assert(digest == [true, true, true, false, true, true, true, true, true, false, true, false, false, true, false, false, false, false, false, true, true, true, false, false, true, false, true, false, false, true, false, false, true, false, true, false, false, true, false, true, true, true, false, false, false, true, true, true, false, true, true, false, true, false, true, true, false, true, false, false, true, false, false, true, false, true, false, true, true, true, false, true, false, true, false, true, false, true, false, true, true, true, false, true, true, true, true, true, true, true, false, true, true, false, true, true, true, true, true, true, true, false, false, true, false, false, false, true, false, true, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, true, false, true, true, false, false, true, true, true, true, false, false, true, false, false, false, false, false, false, false, false, true, false, false, true, false, false, false, true, false, true, true, false, false, true, true, true, false, false, false, true, true, true, false, true, false, true, true, false, false, false, true, true, false, false, false, false, true, true, true, false, false, true, true, true, false, true, false, true, false, true, false, false, true, true, false, false, true, true, false, false, false, true, true, false, false, true, true, true, false, true, false, false, false, true, true, false, true, true, false, false, false, true, true, true, false, false, false, true, false, false, false, false, false, true, true]) + + return 1 \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json new file mode 100644 index 00000000..c342bcb3 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/hashes/sha256/embed/512bit.zok", + "curves": ["Bn128"], + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.zok b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.zok new file mode 100644 index 00000000..e9d54af4 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bit.zok @@ -0,0 +1,11 @@ +import "hashes/sha256/embed/512bit" as sha256 +def main() -> (field): + + bool[256] a = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] b = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true] + + bool[256] digest = sha256(a, b) + + assert(digest == [false, false, false, true, true, true, true, true, false, false, true, true, true, false, true, true, true, false, false, false, true, false, true, true, true, false, false, true, true, false, false, false, true, true, false, false, false, false, true, false, false, false, false, true, true, true, true, false, true, false, true, true, true, false, false, false, true, false, false, true, false, true, false, false, false, false, true, true, true, true, false, false, true, false, false, false, true, true, true, false, true, true, true, false, false, false, true, true, false, false, true, true, false, false, true, false, false, false, true, false, true, true, false, false, false, false, false, true, false, true, false, false, false, false, false, true, false, true, false, false, true, false, true, true, false, true, true, false, false, false, false, true, false, false, false, false, false, true, false, true, false, true, false, true, false, true, true, false, false, false, true, false, false, true, true, false, false, false, false, true, false, true, false, false, true, true, true, false, false, true, true, true, false, false, true, true, true, false, false, false, true, true, true, true, false, false, true, true, false, true, false, true, true, true, true, false, true, true, true, true, false, false, false, true, false, false, true, true, true, false, true, false, false, false, false, false, false, true, true, true, true, false, true, true, true, true, true, false, true, false, true, false, true, true, false, false, true, true, false, false, false, false, true, true, true, true, false, true, false, false, true, false, true, true, false, true]) + + return 1 \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json new file mode 100644 index 00000000..9c61e9e7 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/hashes/sha256/embed/512bitPacked.zok", + "curves": ["Bn128"], + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.zok b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.zok new file mode 100644 index 00000000..b87bf9d1 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPacked.zok @@ -0,0 +1,14 @@ +import "hashes/sha256/embed/512bitPacked" as sha256packed +def main() -> (field): + + field a = 0 + field b = 0 + field c = 0 + field d = 5 + + field[2] h = sha256packed([a, b, c, d]) + + assert(h[0] == 263561599766550617289250058199814760685) + assert(h[1] == 65303172752238645975888084098459749904) + + return 1 \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json new file mode 100644 index 00000000..a0e762be --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.json @@ -0,0 +1,16 @@ +{ + "entry_point": "./tests/tests/hashes/sha256/embed/512bitPadded.zok", + "curves": ["Bn128"], + "tests": [ + { + "input": { + "values": [] + }, + "output": { + "Ok": { + "values": ["1"] + } + } + } + ] +} \ No newline at end of file diff --git a/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.zok b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.zok new file mode 100644 index 00000000..a042da12 --- /dev/null +++ b/zokrates_stdlib/tests/tests/hashes/sha256/embed/512bitPadded.zok @@ -0,0 +1,11 @@ +import "hashes/sha256/embed/512bitPadded" as sha256 +def main() -> (field): + + bool[256] a = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + bool[256] b = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true] + + bool[256] digest = sha256(a, b) + + assert(digest == [true, true, false, false, false, true, true, false, false, true, false, false, true, false, false, false, false, false, false, true, true, true, true, false, false, false, true, false, false, false, true, false, true, true, false, false, false, true, false, true, true, true, true, true, true, true, true, true, false, true, false, false, false, false, false, true, false, true, true, false, false, true, false, false, true, false, true, false, true, true, true, true, false, true, true, false, true, false, false, false, false, false, false, false, true, false, true, true, true, false, false, false, true, true, false, false, true, true, true, true, true, false, true, false, true, false, true, false, false, true, false, true, true, true, true, false, true, false, false, false, true, true, true, false, true, true, false, true, false, false, true, true, false, false, false, true, false, false, true, false, false, false, false, false, true, true, true, false, true, true, true, false, true, true, true, true, true, true, true, true, true, false, false, false, true, false, false, true, true, true, false, false, false, true, false, false, true, true, true, true, false, false, true, true, false, false, false, false, false, true, true, true, true, true, false, false, false, true, false, false, true, false, true, false, false, true, true, false, true, true, true, true, true, false, true, false, true, false, true, false, true, false, true, false, true, true, true, false, false, false, false, false, false, true, false, true, true, false, false, true, true, true, false, false, true, true, true, false, false, false, false, true, false, false, false, false]) + + return 1 \ No newline at end of file