Merge branch 'develop' into field-size-in-bits
This commit is contained in:
commit
c3cc316591
29 changed files with 598 additions and 261 deletions
1
changelogs/unreleased/906-dark64
Normal file
1
changelogs/unreleased/906-dark64
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Change endianness in keccak, sha3 and blake2s hash algorithms to big endian
|
1
changelogs/unreleased/913-schaeff
Normal file
1
changelogs/unreleased/913-schaeff
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix crash on import of functions containing constants
|
|
@ -4,7 +4,8 @@ use crate::flat_absy::{
|
||||||
};
|
};
|
||||||
use crate::solvers::Solver;
|
use crate::solvers::Solver;
|
||||||
use crate::typed_absy::types::{
|
use crate::typed_absy::types::{
|
||||||
ConcreteGenericsAssignment, Constant, DeclarationSignature, DeclarationType, GenericIdentifier,
|
ConcreteGenericsAssignment, DeclarationConstant, DeclarationSignature, DeclarationType,
|
||||||
|
GenericIdentifier,
|
||||||
};
|
};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use zokrates_field::{Bn128Field, Field};
|
use zokrates_field::{Bn128Field, Field};
|
||||||
|
@ -43,10 +44,12 @@ impl FlatEmbed {
|
||||||
.inputs(vec![DeclarationType::uint(32)])
|
.inputs(vec![DeclarationType::uint(32)])
|
||||||
.outputs(vec![DeclarationType::FieldElement]),
|
.outputs(vec![DeclarationType::FieldElement]),
|
||||||
FlatEmbed::Unpack => DeclarationSignature::new()
|
FlatEmbed::Unpack => DeclarationSignature::new()
|
||||||
.generics(vec![Some(Constant::Generic(GenericIdentifier {
|
.generics(vec![Some(DeclarationConstant::Generic(
|
||||||
name: "N",
|
GenericIdentifier {
|
||||||
index: 0,
|
name: "N",
|
||||||
}))])
|
index: 0,
|
||||||
|
},
|
||||||
|
))])
|
||||||
.inputs(vec![DeclarationType::FieldElement])
|
.inputs(vec![DeclarationType::FieldElement])
|
||||||
.outputs(vec![DeclarationType::array((
|
.outputs(vec![DeclarationType::array((
|
||||||
DeclarationType::Boolean,
|
DeclarationType::Boolean,
|
||||||
|
@ -122,7 +125,7 @@ impl FlatEmbed {
|
||||||
.generics
|
.generics
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|c| match c.unwrap() {
|
.map(|c| match c.unwrap() {
|
||||||
Constant::Generic(g) => g,
|
DeclarationConstant::Generic(g) => g,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ use crate::parser::Position;
|
||||||
use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId};
|
use crate::absy::types::{UnresolvedSignature, UnresolvedType, UserTypeId};
|
||||||
|
|
||||||
use crate::typed_absy::types::{
|
use crate::typed_absy::types::{
|
||||||
ArrayType, Constant, DeclarationArrayType, DeclarationFunctionKey, DeclarationSignature,
|
ArrayType, DeclarationArrayType, DeclarationConstant, DeclarationFunctionKey,
|
||||||
DeclarationStructMember, DeclarationStructType, DeclarationType, GenericIdentifier,
|
DeclarationSignature, DeclarationStructMember, DeclarationStructType, DeclarationType,
|
||||||
StructLocation,
|
GenericIdentifier, StructLocation,
|
||||||
};
|
};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
@ -350,7 +350,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
|
|
||||||
fn check_constant_definition(
|
fn check_constant_definition(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: &'ast str,
|
id: ConstantIdentifier<'ast>,
|
||||||
c: ConstantDefinitionNode<'ast>,
|
c: ConstantDefinitionNode<'ast>,
|
||||||
module_id: &ModuleId,
|
module_id: &ModuleId,
|
||||||
state: &State<'ast, T>,
|
state: &State<'ast, T>,
|
||||||
|
@ -445,8 +445,8 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
declaration: SymbolDeclarationNode<'ast>,
|
declaration: SymbolDeclarationNode<'ast>,
|
||||||
module_id: &ModuleId,
|
module_id: &ModuleId,
|
||||||
state: &mut State<'ast, T>,
|
state: &mut State<'ast, T>,
|
||||||
functions: &mut HashMap<DeclarationFunctionKey<'ast>, TypedFunctionSymbol<'ast, T>>,
|
functions: &mut TypedFunctionSymbols<'ast, T>,
|
||||||
constants: &mut HashMap<ConstantIdentifier<'ast>, TypedConstantSymbol<'ast, T>>,
|
constants: &mut TypedConstantSymbols<'ast, T>,
|
||||||
symbol_unifier: &mut SymbolUnifier<'ast>,
|
symbol_unifier: &mut SymbolUnifier<'ast>,
|
||||||
) -> Result<(), Vec<Error>> {
|
) -> Result<(), Vec<Error>> {
|
||||||
let mut errors: Vec<Error> = vec![];
|
let mut errors: Vec<Error> = vec![];
|
||||||
|
@ -506,8 +506,13 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
.in_file(module_id),
|
.in_file(module_id),
|
||||||
),
|
),
|
||||||
true => {
|
true => {
|
||||||
constants
|
constants.push((
|
||||||
.insert(declaration.id, TypedConstantSymbol::Here(c.clone()));
|
CanonicalConstantIdentifier::new(
|
||||||
|
declaration.id,
|
||||||
|
module_id.into(),
|
||||||
|
),
|
||||||
|
TypedConstantSymbol::Here(c.clone()),
|
||||||
|
));
|
||||||
self.insert_into_scope(Variable::with_id_and_type(
|
self.insert_into_scope(Variable::with_id_and_type(
|
||||||
declaration.id,
|
declaration.id,
|
||||||
c.get_type(),
|
c.get_type(),
|
||||||
|
@ -600,7 +605,9 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
.constants
|
.constants
|
||||||
.entry(import.module_id.to_path_buf())
|
.entry(import.module_id.to_path_buf())
|
||||||
.or_default()
|
.or_default()
|
||||||
.get(import.symbol_id)
|
.iter()
|
||||||
|
.find(|(i, _)| *i == &import.symbol_id)
|
||||||
|
.map(|(_, c)| c)
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
match (function_candidates.len(), type_candidate, const_candidate) {
|
match (function_candidates.len(), type_candidate, const_candidate) {
|
||||||
|
@ -653,7 +660,10 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
true => {
|
true => {
|
||||||
constants.insert(declaration.id, TypedConstantSymbol::There(import.module_id.to_path_buf(), import.symbol_id));
|
let imported_id = CanonicalConstantIdentifier::new(import.symbol_id, import.module_id);
|
||||||
|
let id = CanonicalConstantIdentifier::new(declaration.id, module_id.into());
|
||||||
|
|
||||||
|
constants.push((id.clone(), TypedConstantSymbol::There(imported_id)));
|
||||||
self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone()));
|
self.insert_into_scope(Variable::with_id_and_type(declaration.id, ty.clone()));
|
||||||
|
|
||||||
state
|
state
|
||||||
|
@ -750,8 +760,8 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
module_id: &ModuleId,
|
module_id: &ModuleId,
|
||||||
state: &mut State<'ast, T>,
|
state: &mut State<'ast, T>,
|
||||||
) -> Result<(), Vec<Error>> {
|
) -> Result<(), Vec<Error>> {
|
||||||
let mut checked_functions = HashMap::new();
|
let mut checked_functions = TypedFunctionSymbols::new();
|
||||||
let mut checked_constants = HashMap::new();
|
let mut checked_constants = TypedConstantSymbols::new();
|
||||||
|
|
||||||
// check if the module was already removed from the untyped ones
|
// check if the module was already removed from the untyped ones
|
||||||
let to_insert = match state.modules.remove(module_id) {
|
let to_insert = match state.modules.remove(module_id) {
|
||||||
|
@ -856,7 +866,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
|
|
||||||
let v = Variable::with_id_and_type(
|
let v = Variable::with_id_and_type(
|
||||||
match generic {
|
match generic {
|
||||||
Constant::Generic(g) => g.name,
|
DeclarationConstant::Generic(g) => g.name,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
Type::Uint(UBitwidth::B32),
|
Type::Uint(UBitwidth::B32),
|
||||||
|
@ -996,7 +1006,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
} else {
|
} else {
|
||||||
match generics_map.insert(g.value, index).is_none() {
|
match generics_map.insert(g.value, index).is_none() {
|
||||||
true => {
|
true => {
|
||||||
generics.push(Some(Constant::Generic(GenericIdentifier {
|
generics.push(Some(DeclarationConstant::Generic(GenericIdentifier {
|
||||||
name: g.value,
|
name: g.value,
|
||||||
index,
|
index,
|
||||||
})));
|
})));
|
||||||
|
@ -1112,16 +1122,17 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
fn check_generic_expression(
|
fn check_generic_expression(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: ExpressionNode<'ast>,
|
expr: ExpressionNode<'ast>,
|
||||||
|
module_id: &ModuleId,
|
||||||
constants_map: &HashMap<ConstantIdentifier<'ast>, Type<'ast, T>>,
|
constants_map: &HashMap<ConstantIdentifier<'ast>, Type<'ast, T>>,
|
||||||
generics_map: &HashMap<Identifier<'ast>, usize>,
|
generics_map: &HashMap<Identifier<'ast>, usize>,
|
||||||
) -> Result<Constant<'ast>, ErrorInner> {
|
) -> Result<DeclarationConstant<'ast>, ErrorInner> {
|
||||||
let pos = expr.pos();
|
let pos = expr.pos();
|
||||||
|
|
||||||
match expr.value {
|
match expr.value {
|
||||||
Expression::U32Constant(c) => Ok(Constant::Concrete(c)),
|
Expression::U32Constant(c) => Ok(DeclarationConstant::Concrete(c)),
|
||||||
Expression::IntConstant(c) => {
|
Expression::IntConstant(c) => {
|
||||||
if c <= BigUint::from(2u128.pow(32) - 1) {
|
if c <= BigUint::from(2u128.pow(32) - 1) {
|
||||||
Ok(Constant::Concrete(
|
Ok(DeclarationConstant::Concrete(
|
||||||
u32::from_str_radix(&c.to_str_radix(16), 16).unwrap(),
|
u32::from_str_radix(&c.to_str_radix(16), 16).unwrap(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1138,7 +1149,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
match (constants_map.get(name), generics_map.get(&name)) {
|
match (constants_map.get(name), generics_map.get(&name)) {
|
||||||
(Some(ty), None) => {
|
(Some(ty), None) => {
|
||||||
match ty {
|
match ty {
|
||||||
Type::Uint(UBitwidth::B32) => Ok(Constant::Identifier(name, 32usize)),
|
Type::Uint(UBitwidth::B32) => Ok(DeclarationConstant::Constant(CanonicalConstantIdentifier::new(name, module_id.into()))),
|
||||||
_ => Err(ErrorInner {
|
_ => Err(ErrorInner {
|
||||||
pos: Some(pos),
|
pos: Some(pos),
|
||||||
message: format!(
|
message: format!(
|
||||||
|
@ -1148,7 +1159,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(None, Some(index)) => Ok(Constant::Generic(GenericIdentifier { name, index: *index })),
|
(None, Some(index)) => Ok(DeclarationConstant::Generic(GenericIdentifier { name, index: *index })),
|
||||||
_ => Err(ErrorInner {
|
_ => Err(ErrorInner {
|
||||||
pos: Some(pos),
|
pos: Some(pos),
|
||||||
message: format!("Undeclared symbol `{}` in function definition", name)
|
message: format!("Undeclared symbol `{}` in function definition", name)
|
||||||
|
@ -1182,6 +1193,7 @@ impl<'ast, T: Field> Checker<'ast, T> {
|
||||||
UnresolvedType::Array(t, size) => {
|
UnresolvedType::Array(t, size) => {
|
||||||
let checked_size = self.check_generic_expression(
|
let checked_size = self.check_generic_expression(
|
||||||
size.clone(),
|
size.clone(),
|
||||||
|
module_id,
|
||||||
state.constants.get(module_id).unwrap_or(&HashMap::new()),
|
state.constants.get(module_id).unwrap_or(&HashMap::new()),
|
||||||
generics_map,
|
generics_map,
|
||||||
)?;
|
)?;
|
||||||
|
|
|
@ -1,161 +1,153 @@
|
||||||
use crate::static_analysis::propagation::Propagator;
|
use crate::static_analysis::Propagator;
|
||||||
use crate::typed_absy::folder::*;
|
use crate::typed_absy::folder::*;
|
||||||
use crate::typed_absy::result_folder::ResultFolder;
|
use crate::typed_absy::result_folder::ResultFolder;
|
||||||
use crate::typed_absy::types::{Constant, DeclarationStructType, GStructMember};
|
use crate::typed_absy::types::DeclarationConstant;
|
||||||
use crate::typed_absy::*;
|
use crate::typed_absy::*;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use zokrates_field::Field;
|
use zokrates_field::Field;
|
||||||
|
|
||||||
pub struct ConstantInliner<'ast, 'a, T: Field> {
|
type ProgramConstants<'ast, T> =
|
||||||
|
HashMap<OwnedTypedModuleId, HashMap<Identifier<'ast>, TypedExpression<'ast, T>>>;
|
||||||
|
|
||||||
|
pub struct ConstantInliner<'ast, T> {
|
||||||
modules: TypedModules<'ast, T>,
|
modules: TypedModules<'ast, T>,
|
||||||
location: OwnedTypedModuleId,
|
location: OwnedTypedModuleId,
|
||||||
propagator: Propagator<'ast, 'a, T>,
|
constants: ProgramConstants<'ast, T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast, 'a, T: Field> ConstantInliner<'ast, 'a, T> {
|
impl<'ast, 'a, T: Field> ConstantInliner<'ast, T> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
modules: TypedModules<'ast, T>,
|
modules: TypedModules<'ast, T>,
|
||||||
location: OwnedTypedModuleId,
|
location: OwnedTypedModuleId,
|
||||||
propagator: Propagator<'ast, 'a, T>,
|
constants: ProgramConstants<'ast, T>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ConstantInliner {
|
ConstantInliner {
|
||||||
modules,
|
modules,
|
||||||
location,
|
location,
|
||||||
propagator,
|
constants,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn inline(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
|
pub fn inline(p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
|
||||||
let mut constants = HashMap::new();
|
let constants = ProgramConstants::new();
|
||||||
let mut inliner = ConstantInliner::new(
|
let mut inliner = ConstantInliner::new(p.modules.clone(), p.main.clone(), constants);
|
||||||
p.modules.clone(),
|
|
||||||
p.main.clone(),
|
|
||||||
Propagator::with_constants(&mut constants),
|
|
||||||
);
|
|
||||||
inliner.fold_program(p)
|
inliner.fold_program(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn module(&self) -> &TypedModule<'ast, T> {
|
|
||||||
self.modules.get(&self.location).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn change_location(&mut self, location: OwnedTypedModuleId) -> OwnedTypedModuleId {
|
fn change_location(&mut self, location: OwnedTypedModuleId) -> OwnedTypedModuleId {
|
||||||
let prev = self.location.clone();
|
let prev = self.location.clone();
|
||||||
self.location = location;
|
self.location = location;
|
||||||
|
self.constants.entry(self.location.clone()).or_default();
|
||||||
prev
|
prev
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_constant(&mut self, id: &Identifier) -> Option<TypedConstant<'ast, T>> {
|
fn treated(&self, id: &TypedModuleId) -> bool {
|
||||||
self.modules
|
self.constants.contains_key(id)
|
||||||
.get(&self.location)
|
|
||||||
.unwrap()
|
|
||||||
.constants
|
|
||||||
.get(id.clone().try_into().unwrap())
|
|
||||||
.cloned()
|
|
||||||
.map(|symbol| self.get_canonical_constant(symbol))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_canonical_constant(
|
fn get_constant(
|
||||||
&mut self,
|
&self,
|
||||||
symbol: TypedConstantSymbol<'ast, T>,
|
id: &CanonicalConstantIdentifier<'ast>,
|
||||||
) -> TypedConstant<'ast, T> {
|
) -> Option<TypedExpression<'ast, T>> {
|
||||||
match symbol {
|
self.constants
|
||||||
TypedConstantSymbol::There(module_id, id) => {
|
.get(&id.module)
|
||||||
let location = self.change_location(module_id);
|
.and_then(|constants| constants.get(&id.id.into()))
|
||||||
let symbol = self.module().constants.get(id).cloned().unwrap();
|
.cloned()
|
||||||
|
}
|
||||||
|
|
||||||
let symbol = self.get_canonical_constant(symbol);
|
fn get_constant_for_identifier(
|
||||||
let _ = self.change_location(location);
|
&self,
|
||||||
symbol
|
id: &Identifier<'ast>,
|
||||||
}
|
) -> Option<TypedExpression<'ast, T>> {
|
||||||
TypedConstantSymbol::Here(tc) => {
|
self.constants
|
||||||
let tc: TypedConstant<T> = self.fold_constant(tc);
|
.get(&self.location)
|
||||||
TypedConstant {
|
.and_then(|constants| constants.get(&id))
|
||||||
expression: self.propagator.fold_expression(tc.expression).unwrap(),
|
.cloned()
|
||||||
..tc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
impl<'ast, T: Field> Folder<'ast, T> for ConstantInliner<'ast, T> {
|
||||||
fn fold_program(&mut self, p: TypedProgram<'ast, T>) -> TypedProgram<'ast, T> {
|
fn fold_module_id(&mut self, id: OwnedTypedModuleId) -> OwnedTypedModuleId {
|
||||||
TypedProgram {
|
// anytime we encounter a module id, visit the corresponding module if it hasn't been done yet
|
||||||
modules: p
|
if !self.treated(&id) {
|
||||||
.modules
|
let current_m_id = self.change_location(id.clone());
|
||||||
|
let m = self.modules.remove(&id).unwrap();
|
||||||
|
let m = self.fold_module(m);
|
||||||
|
self.modules.insert(id.clone(), m);
|
||||||
|
self.change_location(current_m_id);
|
||||||
|
}
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_module(&mut self, m: TypedModule<'ast, T>) -> TypedModule<'ast, T> {
|
||||||
|
TypedModule {
|
||||||
|
constants: m
|
||||||
|
.constants
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(module_id, module)| {
|
.map(|(id, tc)| {
|
||||||
self.change_location(module_id.clone());
|
let constant = match tc {
|
||||||
(module_id, self.fold_module(module))
|
TypedConstantSymbol::There(imported_id) => {
|
||||||
|
// visit the imported symbol. This triggers visiting the corresponding module if needed
|
||||||
|
let imported_id = self.fold_canonical_constant_identifier(imported_id);
|
||||||
|
// after that, the constant must have been defined defined in the global map. It is already reduced
|
||||||
|
// to a literal, so running propagation isn't required
|
||||||
|
self.get_constant(&imported_id).unwrap()
|
||||||
|
}
|
||||||
|
TypedConstantSymbol::Here(c) => {
|
||||||
|
let non_propagated_constant = fold_constant(self, c).expression;
|
||||||
|
// folding the constant above only reduces it to an expression containing only literals, not to a single literal.
|
||||||
|
// propagating with an empty map of constants reduces it to a single literal
|
||||||
|
Propagator::with_constants(&mut HashMap::default())
|
||||||
|
.fold_expression(non_propagated_constant)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// add to the constant map. The value added is always a single litteral
|
||||||
|
self.constants
|
||||||
|
.get_mut(&self.location)
|
||||||
|
.unwrap()
|
||||||
|
.insert(id.id.into(), constant.clone());
|
||||||
|
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
TypedConstantSymbol::Here(TypedConstant {
|
||||||
|
ty: constant.get_type().clone(),
|
||||||
|
expression: constant,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
functions: m
|
||||||
|
.functions
|
||||||
|
.into_iter()
|
||||||
|
.map(|(key, fun)| {
|
||||||
|
(
|
||||||
|
self.fold_declaration_function_key(key),
|
||||||
|
self.fold_function_symbol(fun),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
main: p.main,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_declaration_type(&mut self, t: DeclarationType<'ast>) -> DeclarationType<'ast> {
|
fn fold_declaration_constant(
|
||||||
match t {
|
|
||||||
DeclarationType::Array(ref array_ty) => match array_ty.size {
|
|
||||||
Constant::Identifier(name, _) => {
|
|
||||||
let tc = self.get_constant(&name.into()).unwrap();
|
|
||||||
let expression: UExpression<'ast, T> = tc.expression.try_into().unwrap();
|
|
||||||
match expression.inner {
|
|
||||||
UExpressionInner::Value(v) => DeclarationType::array((
|
|
||||||
self.fold_declaration_type(*array_ty.ty.clone()),
|
|
||||||
Constant::Concrete(v as u32),
|
|
||||||
)),
|
|
||||||
_ => unreachable!("expected u32 value"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => t,
|
|
||||||
},
|
|
||||||
DeclarationType::Struct(struct_ty) => DeclarationType::struc(DeclarationStructType {
|
|
||||||
members: struct_ty
|
|
||||||
.members
|
|
||||||
.into_iter()
|
|
||||||
.map(|m| GStructMember::new(m.id, self.fold_declaration_type(*m.ty)))
|
|
||||||
.collect(),
|
|
||||||
..struct_ty
|
|
||||||
}),
|
|
||||||
_ => t,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold_type(&mut self, t: Type<'ast, T>) -> Type<'ast, T> {
|
|
||||||
use self::GType::*;
|
|
||||||
match t {
|
|
||||||
Array(ref array_type) => match &array_type.size.inner {
|
|
||||||
UExpressionInner::Identifier(v) => match self.get_constant(v) {
|
|
||||||
Some(tc) => {
|
|
||||||
let expression: UExpression<'ast, T> = tc.expression.try_into().unwrap();
|
|
||||||
Type::array(GArrayType::new(
|
|
||||||
self.fold_type(*array_type.ty.clone()),
|
|
||||||
expression,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
None => t,
|
|
||||||
},
|
|
||||||
_ => t,
|
|
||||||
},
|
|
||||||
Struct(struct_type) => Type::struc(GStructType {
|
|
||||||
members: struct_type
|
|
||||||
.members
|
|
||||||
.into_iter()
|
|
||||||
.map(|m| GStructMember::new(m.id, self.fold_type(*m.ty)))
|
|
||||||
.collect(),
|
|
||||||
..struct_type
|
|
||||||
}),
|
|
||||||
_ => t,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fold_constant_symbol(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
s: TypedConstantSymbol<'ast, T>,
|
c: DeclarationConstant<'ast>,
|
||||||
) -> TypedConstantSymbol<'ast, T> {
|
) -> DeclarationConstant<'ast> {
|
||||||
let tc = self.get_canonical_constant(s);
|
match c {
|
||||||
TypedConstantSymbol::Here(tc)
|
// replace constants by their concrete value in declaration types
|
||||||
|
DeclarationConstant::Constant(id) => {
|
||||||
|
DeclarationConstant::Concrete(match self.get_constant(&id).unwrap() {
|
||||||
|
TypedExpression::Uint(UExpression {
|
||||||
|
inner: UExpressionInner::Value(v),
|
||||||
|
..
|
||||||
|
}) => v as u32,
|
||||||
|
_ => unreachable!("all constants found in declaration types should be reduceable to u32 literals"),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
c => c,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_field_expression(
|
fn fold_field_expression(
|
||||||
|
@ -163,10 +155,12 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
||||||
e: FieldElementExpression<'ast, T>,
|
e: FieldElementExpression<'ast, T>,
|
||||||
) -> FieldElementExpression<'ast, T> {
|
) -> FieldElementExpression<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
FieldElementExpression::Identifier(ref id) => match self.get_constant(id) {
|
FieldElementExpression::Identifier(ref id) => {
|
||||||
Some(c) => self.fold_constant(c).try_into().unwrap(),
|
match self.get_constant_for_identifier(id) {
|
||||||
None => fold_field_expression(self, e),
|
Some(c) => c.try_into().unwrap(),
|
||||||
},
|
None => fold_field_expression(self, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
e => fold_field_expression(self, e),
|
e => fold_field_expression(self, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,8 +170,8 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
||||||
e: BooleanExpression<'ast, T>,
|
e: BooleanExpression<'ast, T>,
|
||||||
) -> BooleanExpression<'ast, T> {
|
) -> BooleanExpression<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
BooleanExpression::Identifier(ref id) => match self.get_constant(id) {
|
BooleanExpression::Identifier(ref id) => match self.get_constant_for_identifier(id) {
|
||||||
Some(c) => self.fold_constant(c).try_into().unwrap(),
|
Some(c) => c.try_into().unwrap(),
|
||||||
None => fold_boolean_expression(self, e),
|
None => fold_boolean_expression(self, e),
|
||||||
},
|
},
|
||||||
e => fold_boolean_expression(self, e),
|
e => fold_boolean_expression(self, e),
|
||||||
|
@ -190,9 +184,9 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
||||||
e: UExpressionInner<'ast, T>,
|
e: UExpressionInner<'ast, T>,
|
||||||
) -> UExpressionInner<'ast, T> {
|
) -> UExpressionInner<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
UExpressionInner::Identifier(ref id) => match self.get_constant(id) {
|
UExpressionInner::Identifier(ref id) => match self.get_constant_for_identifier(id) {
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
let e: UExpression<'ast, T> = self.fold_constant(c).try_into().unwrap();
|
let e: UExpression<'ast, T> = c.try_into().unwrap();
|
||||||
e.into_inner()
|
e.into_inner()
|
||||||
}
|
}
|
||||||
None => fold_uint_expression_inner(self, size, e),
|
None => fold_uint_expression_inner(self, size, e),
|
||||||
|
@ -207,13 +201,15 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
||||||
e: ArrayExpressionInner<'ast, T>,
|
e: ArrayExpressionInner<'ast, T>,
|
||||||
) -> ArrayExpressionInner<'ast, T> {
|
) -> ArrayExpressionInner<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
ArrayExpressionInner::Identifier(ref id) => match self.get_constant(id) {
|
ArrayExpressionInner::Identifier(ref id) => {
|
||||||
Some(c) => {
|
match self.get_constant_for_identifier(id) {
|
||||||
let e: ArrayExpression<'ast, T> = self.fold_constant(c).try_into().unwrap();
|
Some(c) => {
|
||||||
e.into_inner()
|
let e: ArrayExpression<'ast, T> = c.try_into().unwrap();
|
||||||
|
e.into_inner()
|
||||||
|
}
|
||||||
|
None => fold_array_expression_inner(self, ty, e),
|
||||||
}
|
}
|
||||||
None => fold_array_expression_inner(self, ty, e),
|
}
|
||||||
},
|
|
||||||
e => fold_array_expression_inner(self, ty, e),
|
e => fold_array_expression_inner(self, ty, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,9 +220,10 @@ impl<'ast, 'a, T: Field> Folder<'ast, T> for ConstantInliner<'ast, 'a, T> {
|
||||||
e: StructExpressionInner<'ast, T>,
|
e: StructExpressionInner<'ast, T>,
|
||||||
) -> StructExpressionInner<'ast, T> {
|
) -> StructExpressionInner<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
StructExpressionInner::Identifier(ref id) => match self.get_constant(id) {
|
StructExpressionInner::Identifier(ref id) => match self.get_constant_for_identifier(id)
|
||||||
|
{
|
||||||
Some(c) => {
|
Some(c) => {
|
||||||
let e: StructExpression<'ast, T> = self.fold_constant(c).try_into().unwrap();
|
let e: StructExpression<'ast, T> = c.try_into().unwrap();
|
||||||
e.into_inner()
|
e.into_inner()
|
||||||
}
|
}
|
||||||
None => fold_struct_expression_inner(self, ty, e),
|
None => fold_struct_expression_inner(self, ty, e),
|
||||||
|
@ -265,7 +262,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let constants: TypedConstantSymbols<_> = vec![(
|
let constants: TypedConstantSymbols<_> = vec![(
|
||||||
const_id,
|
CanonicalConstantIdentifier::new(const_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(Bn128Field::from(1))),
|
TypedExpression::FieldElement(FieldElementExpression::Number(Bn128Field::from(1))),
|
||||||
|
@ -353,7 +350,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let constants: TypedConstantSymbols<_> = vec![(
|
let constants: TypedConstantSymbols<_> = vec![(
|
||||||
const_id,
|
CanonicalConstantIdentifier::new(const_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::Boolean,
|
GType::Boolean,
|
||||||
TypedExpression::Boolean(BooleanExpression::Value(true)),
|
TypedExpression::Boolean(BooleanExpression::Value(true)),
|
||||||
|
@ -442,7 +439,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let constants: TypedConstantSymbols<_> = vec![(
|
let constants: TypedConstantSymbols<_> = vec![(
|
||||||
const_id,
|
CanonicalConstantIdentifier::new(const_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::Uint(UBitwidth::B32),
|
GType::Uint(UBitwidth::B32),
|
||||||
UExpressionInner::Value(1u128)
|
UExpressionInner::Value(1u128)
|
||||||
|
@ -543,7 +540,7 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let constants: TypedConstantSymbols<_> = vec![(
|
let constants: TypedConstantSymbols<_> = vec![(
|
||||||
const_id,
|
CanonicalConstantIdentifier::new(const_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::Array(
|
TypedExpression::Array(
|
||||||
|
@ -682,7 +679,7 @@ mod tests {
|
||||||
.collect(),
|
.collect(),
|
||||||
constants: vec![
|
constants: vec![
|
||||||
(
|
(
|
||||||
const_a_id,
|
CanonicalConstantIdentifier::new(const_a_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(
|
TypedExpression::FieldElement(FieldElementExpression::Number(
|
||||||
|
@ -691,7 +688,7 @@ mod tests {
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
const_b_id,
|
CanonicalConstantIdentifier::new(const_b_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Add(
|
TypedExpression::FieldElement(FieldElementExpression::Add(
|
||||||
|
@ -740,7 +737,7 @@ mod tests {
|
||||||
.collect(),
|
.collect(),
|
||||||
constants: vec![
|
constants: vec![
|
||||||
(
|
(
|
||||||
const_a_id,
|
CanonicalConstantIdentifier::new(const_a_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(
|
TypedExpression::FieldElement(FieldElementExpression::Number(
|
||||||
|
@ -749,7 +746,7 @@ mod tests {
|
||||||
)),
|
)),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
const_b_id,
|
CanonicalConstantIdentifier::new(const_b_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(
|
TypedExpression::FieldElement(FieldElementExpression::Number(
|
||||||
|
@ -801,7 +798,7 @@ mod tests {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
constants: vec![(
|
constants: vec![(
|
||||||
foo_const_id,
|
CanonicalConstantIdentifier::new(foo_const_id, "foo".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(
|
TypedExpression::FieldElement(FieldElementExpression::Number(
|
||||||
|
@ -833,8 +830,11 @@ mod tests {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
constants: vec![(
|
constants: vec![(
|
||||||
foo_const_id,
|
CanonicalConstantIdentifier::new(foo_const_id, "main".into()),
|
||||||
TypedConstantSymbol::There(OwnedTypedModuleId::from("foo"), foo_const_id),
|
TypedConstantSymbol::There(CanonicalConstantIdentifier::new(
|
||||||
|
foo_const_id,
|
||||||
|
"foo".into(),
|
||||||
|
)),
|
||||||
)]
|
)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -871,7 +871,7 @@ mod tests {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.collect(),
|
.collect(),
|
||||||
constants: vec![(
|
constants: vec![(
|
||||||
foo_const_id,
|
CanonicalConstantIdentifier::new(foo_const_id, "main".into()),
|
||||||
TypedConstantSymbol::Here(TypedConstant::new(
|
TypedConstantSymbol::Here(TypedConstant::new(
|
||||||
GType::FieldElement,
|
GType::FieldElement,
|
||||||
TypedExpression::FieldElement(FieldElementExpression::Number(
|
TypedExpression::FieldElement(FieldElementExpression::Number(
|
||||||
|
|
|
@ -84,6 +84,7 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
|
||||||
} else {
|
} else {
|
||||||
r
|
r
|
||||||
};
|
};
|
||||||
|
|
||||||
// reduce the program to a single function
|
// reduce the program to a single function
|
||||||
let r = reduce_program(r).map_err(Error::from)?;
|
let r = reduce_program(r).map_err(Error::from)?;
|
||||||
// generate abi
|
// generate abi
|
||||||
|
|
|
@ -614,7 +614,7 @@ fn compute_hash<T: Field>(f: &TypedFunction<T>) -> u64 {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::typed_absy::types::Constant;
|
use crate::typed_absy::types::DeclarationConstant;
|
||||||
use crate::typed_absy::types::DeclarationSignature;
|
use crate::typed_absy::types::DeclarationSignature;
|
||||||
use crate::typed_absy::{
|
use crate::typed_absy::{
|
||||||
ArrayExpression, ArrayExpressionInner, DeclarationFunctionKey, DeclarationType,
|
ArrayExpression, ArrayExpressionInner, DeclarationFunctionKey, DeclarationType,
|
||||||
|
@ -834,11 +834,11 @@ mod tests {
|
||||||
)])
|
)])
|
||||||
.inputs(vec![DeclarationType::array((
|
.inputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))])
|
))])
|
||||||
.outputs(vec![DeclarationType::array((
|
.outputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))]);
|
))]);
|
||||||
|
|
||||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||||
|
@ -1053,11 +1053,11 @@ mod tests {
|
||||||
)])
|
)])
|
||||||
.inputs(vec![DeclarationType::array((
|
.inputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))])
|
))])
|
||||||
.outputs(vec![DeclarationType::array((
|
.outputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))]);
|
))]);
|
||||||
|
|
||||||
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
let foo: TypedFunction<Bn128Field> = TypedFunction {
|
||||||
|
@ -1285,11 +1285,11 @@ mod tests {
|
||||||
let foo_signature = DeclarationSignature::new()
|
let foo_signature = DeclarationSignature::new()
|
||||||
.inputs(vec![DeclarationType::array((
|
.inputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))])
|
))])
|
||||||
.outputs(vec![DeclarationType::array((
|
.outputs(vec![DeclarationType::array((
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
))])
|
))])
|
||||||
.generics(vec![Some(
|
.generics(vec![Some(
|
||||||
GenericIdentifier::with_name("K").index(0).into(),
|
GenericIdentifier::with_name("K").index(0).into(),
|
||||||
|
@ -1299,7 +1299,7 @@ mod tests {
|
||||||
arguments: vec![DeclarationVariable::array(
|
arguments: vec![DeclarationVariable::array(
|
||||||
"a",
|
"a",
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
)
|
)
|
||||||
.into()],
|
.into()],
|
||||||
statements: vec![
|
statements: vec![
|
||||||
|
@ -1363,7 +1363,7 @@ mod tests {
|
||||||
arguments: vec![DeclarationVariable::array(
|
arguments: vec![DeclarationVariable::array(
|
||||||
"a",
|
"a",
|
||||||
DeclarationType::FieldElement,
|
DeclarationType::FieldElement,
|
||||||
Constant::Generic(GenericIdentifier::with_name("K").index(0)),
|
DeclarationConstant::Generic(GenericIdentifier::with_name("K").index(0)),
|
||||||
)
|
)
|
||||||
.into()],
|
.into()],
|
||||||
statements: vec![TypedStatement::Return(vec![
|
statements: vec![TypedStatement::Return(vec![
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Generic walk through a typed AST. Not mutating in place
|
// Generic walk through a typed AST. Not mutating in place
|
||||||
|
|
||||||
use crate::typed_absy::types::{ArrayType, StructMember, StructType};
|
use crate::typed_absy::types::*;
|
||||||
use crate::typed_absy::*;
|
use crate::typed_absy::*;
|
||||||
use zokrates_field::Field;
|
use zokrates_field::Field;
|
||||||
|
|
||||||
|
@ -80,6 +80,13 @@ pub trait Folder<'ast, T: Field>: Sized {
|
||||||
fold_signature(self, s)
|
fold_signature(self, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_constant(
|
||||||
|
&mut self,
|
||||||
|
c: DeclarationConstant<'ast>,
|
||||||
|
) -> DeclarationConstant<'ast> {
|
||||||
|
fold_declaration_constant(self, c)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_parameter(&mut self, p: DeclarationParameter<'ast>) -> DeclarationParameter<'ast> {
|
fn fold_parameter(&mut self, p: DeclarationParameter<'ast>) -> DeclarationParameter<'ast> {
|
||||||
DeclarationParameter {
|
DeclarationParameter {
|
||||||
id: self.fold_declaration_variable(p.id),
|
id: self.fold_declaration_variable(p.id),
|
||||||
|
@ -144,7 +151,40 @@ pub trait Folder<'ast, T: Field>: Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_declaration_type(&mut self, t: DeclarationType<'ast>) -> DeclarationType<'ast> {
|
fn fold_declaration_type(&mut self, t: DeclarationType<'ast>) -> DeclarationType<'ast> {
|
||||||
t
|
use self::GType::*;
|
||||||
|
|
||||||
|
match t {
|
||||||
|
Array(array_type) => Array(self.fold_declaration_array_type(array_type)),
|
||||||
|
Struct(struct_type) => Struct(self.fold_declaration_struct_type(struct_type)),
|
||||||
|
t => t,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_array_type(
|
||||||
|
&mut self,
|
||||||
|
t: DeclarationArrayType<'ast>,
|
||||||
|
) -> DeclarationArrayType<'ast> {
|
||||||
|
DeclarationArrayType {
|
||||||
|
ty: box self.fold_declaration_type(*t.ty),
|
||||||
|
size: self.fold_declaration_constant(t.size),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_struct_type(
|
||||||
|
&mut self,
|
||||||
|
t: DeclarationStructType<'ast>,
|
||||||
|
) -> DeclarationStructType<'ast> {
|
||||||
|
DeclarationStructType {
|
||||||
|
members: t
|
||||||
|
.members
|
||||||
|
.into_iter()
|
||||||
|
.map(|m| DeclarationStructMember {
|
||||||
|
ty: box self.fold_declaration_type(*m.ty),
|
||||||
|
..m
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_assignee(&mut self, a: TypedAssignee<'ast, T>) -> TypedAssignee<'ast, T> {
|
fn fold_assignee(&mut self, a: TypedAssignee<'ast, T>) -> TypedAssignee<'ast, T> {
|
||||||
|
@ -175,6 +215,20 @@ pub trait Folder<'ast, T: Field>: Sized {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_canonical_constant_identifier(
|
||||||
|
&mut self,
|
||||||
|
i: CanonicalConstantIdentifier<'ast>,
|
||||||
|
) -> CanonicalConstantIdentifier<'ast> {
|
||||||
|
CanonicalConstantIdentifier {
|
||||||
|
module: self.fold_module_id(i.module),
|
||||||
|
id: i.id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_module_id(&mut self, i: OwnedTypedModuleId) -> OwnedTypedModuleId {
|
||||||
|
i
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> {
|
fn fold_expression(&mut self, e: TypedExpression<'ast, T>) -> TypedExpression<'ast, T> {
|
||||||
match e {
|
match e {
|
||||||
TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(),
|
TypedExpression::FieldElement(e) => self.fold_field_expression(e).into(),
|
||||||
|
@ -316,7 +370,12 @@ pub fn fold_module<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
constants: m
|
constants: m
|
||||||
.constants
|
.constants
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(key, tc)| (key, f.fold_constant_symbol(tc)))
|
.map(|(id, tc)| {
|
||||||
|
(
|
||||||
|
f.fold_canonical_constant_identifier(id),
|
||||||
|
f.fold_constant_symbol(tc),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
functions: m
|
functions: m
|
||||||
.functions
|
.functions
|
||||||
|
@ -901,6 +960,13 @@ fn fold_signature<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_constant<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
|
_: &mut F,
|
||||||
|
c: DeclarationConstant<'ast>,
|
||||||
|
) -> DeclarationConstant<'ast> {
|
||||||
|
c
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
pub fn fold_array_expression<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
f: &mut F,
|
f: &mut F,
|
||||||
e: ArrayExpression<'ast, T>,
|
e: ArrayExpression<'ast, T>,
|
||||||
|
@ -988,7 +1054,9 @@ pub fn fold_constant_symbol<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
) -> TypedConstantSymbol<'ast, T> {
|
) -> TypedConstantSymbol<'ast, T> {
|
||||||
match s {
|
match s {
|
||||||
TypedConstantSymbol::Here(tc) => TypedConstantSymbol::Here(f.fold_constant(tc)),
|
TypedConstantSymbol::Here(tc) => TypedConstantSymbol::Here(f.fold_constant(tc)),
|
||||||
there => there,
|
TypedConstantSymbol::There(id) => {
|
||||||
|
TypedConstantSymbol::There(f.fold_canonical_constant_identifier(id))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,7 +1066,10 @@ pub fn fold_function_symbol<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
) -> TypedFunctionSymbol<'ast, T> {
|
) -> TypedFunctionSymbol<'ast, T> {
|
||||||
match s {
|
match s {
|
||||||
TypedFunctionSymbol::Here(fun) => TypedFunctionSymbol::Here(f.fold_function(fun)),
|
TypedFunctionSymbol::Here(fun) => TypedFunctionSymbol::Here(f.fold_function(fun)),
|
||||||
there => there, // by default, do not fold modules recursively
|
TypedFunctionSymbol::There(key) => {
|
||||||
|
TypedFunctionSymbol::There(f.fold_declaration_function_key(key))
|
||||||
|
}
|
||||||
|
s => s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1023,8 +1094,8 @@ pub fn fold_program<'ast, T: Field, F: Folder<'ast, T>>(
|
||||||
modules: p
|
modules: p
|
||||||
.modules
|
.modules
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(module_id, module)| (module_id, f.fold_module(module)))
|
.map(|(module_id, module)| (f.fold_module_id(module_id), f.fold_module(module)))
|
||||||
.collect(),
|
.collect(),
|
||||||
main: p.main,
|
main: f.fold_module_id(p.main),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,10 @@ mod variable;
|
||||||
pub use self::identifier::CoreIdentifier;
|
pub use self::identifier::CoreIdentifier;
|
||||||
pub use self::parameter::{DeclarationParameter, GParameter};
|
pub use self::parameter::{DeclarationParameter, GParameter};
|
||||||
pub use self::types::{
|
pub use self::types::{
|
||||||
ConcreteFunctionKey, ConcreteSignature, ConcreteType, DeclarationFunctionKey,
|
CanonicalConstantIdentifier, ConcreteFunctionKey, ConcreteSignature, ConcreteType,
|
||||||
DeclarationSignature, DeclarationType, GArrayType, GStructType, GType, GenericIdentifier,
|
ConstantIdentifier, DeclarationFunctionKey, DeclarationSignature, DeclarationType, GArrayType,
|
||||||
IntoTypes, Signature, StructType, Type, Types, UBitwidth,
|
GStructType, GType, GenericIdentifier, IntoTypes, Signature, StructType, Type, Types,
|
||||||
|
UBitwidth,
|
||||||
};
|
};
|
||||||
use crate::typed_absy::types::ConcreteGenericsAssignment;
|
use crate::typed_absy::types::ConcreteGenericsAssignment;
|
||||||
|
|
||||||
|
@ -62,17 +63,18 @@ pub type TypedModules<'ast, T> = HashMap<OwnedTypedModuleId, TypedModule<'ast, T
|
||||||
pub type TypedFunctionSymbols<'ast, T> =
|
pub type TypedFunctionSymbols<'ast, T> =
|
||||||
HashMap<DeclarationFunctionKey<'ast>, TypedFunctionSymbol<'ast, T>>;
|
HashMap<DeclarationFunctionKey<'ast>, TypedFunctionSymbol<'ast, T>>;
|
||||||
|
|
||||||
pub type ConstantIdentifier<'ast> = &'ast str;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum TypedConstantSymbol<'ast, T> {
|
pub enum TypedConstantSymbol<'ast, T> {
|
||||||
Here(TypedConstant<'ast, T>),
|
Here(TypedConstant<'ast, T>),
|
||||||
There(OwnedTypedModuleId, ConstantIdentifier<'ast>),
|
There(CanonicalConstantIdentifier<'ast>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A collection of `TypedConstantSymbol`s
|
/// A collection of `TypedConstantSymbol`s
|
||||||
pub type TypedConstantSymbols<'ast, T> =
|
/// It is still ordered, as we inline the constants in the order they are declared
|
||||||
HashMap<ConstantIdentifier<'ast>, TypedConstantSymbol<'ast, T>>;
|
pub type TypedConstantSymbols<'ast, T> = Vec<(
|
||||||
|
CanonicalConstantIdentifier<'ast>,
|
||||||
|
TypedConstantSymbol<'ast, T>,
|
||||||
|
)>;
|
||||||
|
|
||||||
/// A typed program as a collection of modules, one of them being the main
|
/// A typed program as a collection of modules, one of them being the main
|
||||||
#[derive(PartialEq, Debug, Clone)]
|
#[derive(PartialEq, Debug, Clone)]
|
||||||
|
@ -188,12 +190,17 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedModule<'ast, T> {
|
||||||
let res = self
|
let res = self
|
||||||
.constants
|
.constants
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, symbol)| match symbol {
|
.map(|(id, symbol)| match symbol {
|
||||||
TypedConstantSymbol::Here(ref tc) => {
|
TypedConstantSymbol::Here(ref tc) => {
|
||||||
format!("const {} {} = {}", tc.ty, key, tc.expression)
|
format!("const {} {} = {}", tc.ty, id.id, tc.expression)
|
||||||
}
|
}
|
||||||
TypedConstantSymbol::There(ref module_id, ref id) => {
|
TypedConstantSymbol::There(ref imported_id) => {
|
||||||
format!("from \"{}\" import {} as {}", module_id.display(), id, key)
|
format!(
|
||||||
|
"from \"{}\" import {} as {}",
|
||||||
|
imported_id.module.display(),
|
||||||
|
imported_id.id,
|
||||||
|
id.id
|
||||||
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.chain(self.functions.iter().map(|(key, symbol)| match symbol {
|
.chain(self.functions.iter().map(|(key, symbol)| match symbol {
|
||||||
|
@ -291,6 +298,7 @@ impl<'ast, T: fmt::Display> fmt::Display for TypedFunction<'ast, T> {
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub struct TypedConstant<'ast, T> {
|
pub struct TypedConstant<'ast, T> {
|
||||||
|
// the type is already stored in the TypedExpression, but we want to avoid awkward trait bounds in `fmt::Display`
|
||||||
pub ty: Type<'ast, T>,
|
pub ty: Type<'ast, T>,
|
||||||
pub expression: TypedExpression<'ast, T>,
|
pub expression: TypedExpression<'ast, T>,
|
||||||
}
|
}
|
||||||
|
@ -303,6 +311,7 @@ impl<'ast, T> TypedConstant<'ast, T> {
|
||||||
|
|
||||||
impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> {
|
impl<'ast, T: fmt::Display> fmt::Display for TypedConstant<'ast, T> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
// using `self.expression.get_type()` would be better here but ends up requiring stronger trait bounds
|
||||||
write!(f, "const {}({})", self.ty, self.expression)
|
write!(f, "const {}({})", self.ty, self.expression)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::typed_absy::types::Constant;
|
use crate::typed_absy::types::DeclarationConstant;
|
||||||
use crate::typed_absy::GVariable;
|
use crate::typed_absy::GVariable;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ impl<'ast, S> From<GVariable<'ast, S>> for GParameter<'ast, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationParameter<'ast> = GParameter<'ast, Constant<'ast>>;
|
pub type DeclarationParameter<'ast> = GParameter<'ast, DeclarationConstant<'ast>>;
|
||||||
|
|
||||||
impl<'ast, S: fmt::Display + Clone> fmt::Display for GParameter<'ast, S> {
|
impl<'ast, S: fmt::Display + Clone> fmt::Display for GParameter<'ast, S> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Generic walk through a typed AST. Not mutating in place
|
// Generic walk through a typed AST. Not mutating in place
|
||||||
|
|
||||||
use crate::typed_absy::types::{ArrayType, StructMember, StructType};
|
use crate::typed_absy::types::*;
|
||||||
use crate::typed_absy::*;
|
use crate::typed_absy::*;
|
||||||
use zokrates_field::Field;
|
use zokrates_field::Field;
|
||||||
|
|
||||||
|
@ -97,6 +97,13 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
||||||
fold_signature(self, s)
|
fold_signature(self, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_constant(
|
||||||
|
&mut self,
|
||||||
|
c: DeclarationConstant<'ast>,
|
||||||
|
) -> Result<DeclarationConstant<'ast>, Self::Error> {
|
||||||
|
fold_declaration_constant(self, c)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_parameter(
|
fn fold_parameter(
|
||||||
&mut self,
|
&mut self,
|
||||||
p: DeclarationParameter<'ast>,
|
p: DeclarationParameter<'ast>,
|
||||||
|
@ -107,6 +114,20 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_canonical_constant_identifier(
|
||||||
|
&mut self,
|
||||||
|
i: CanonicalConstantIdentifier<'ast>,
|
||||||
|
) -> Result<CanonicalConstantIdentifier<'ast>, Self::Error> {
|
||||||
|
Ok(CanonicalConstantIdentifier {
|
||||||
|
module: self.fold_module_id(i.module)?,
|
||||||
|
id: i.id,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_module_id(&mut self, i: OwnedTypedModuleId) -> Result<OwnedTypedModuleId, Self::Error> {
|
||||||
|
Ok(i)
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_name(&mut self, n: Identifier<'ast>) -> Result<Identifier<'ast>, Self::Error> {
|
fn fold_name(&mut self, n: Identifier<'ast>) -> Result<Identifier<'ast>, Self::Error> {
|
||||||
Ok(n)
|
Ok(n)
|
||||||
}
|
}
|
||||||
|
@ -224,6 +245,34 @@ pub trait ResultFolder<'ast, T: Field>: Sized {
|
||||||
Ok(t)
|
Ok(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_array_type(
|
||||||
|
&mut self,
|
||||||
|
t: DeclarationArrayType<'ast>,
|
||||||
|
) -> Result<DeclarationArrayType<'ast>, Self::Error> {
|
||||||
|
Ok(DeclarationArrayType {
|
||||||
|
ty: box self.fold_declaration_type(*t.ty)?,
|
||||||
|
size: self.fold_declaration_constant(t.size)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_struct_type(
|
||||||
|
&mut self,
|
||||||
|
t: DeclarationStructType<'ast>,
|
||||||
|
) -> Result<DeclarationStructType<'ast>, Self::Error> {
|
||||||
|
Ok(DeclarationStructType {
|
||||||
|
members: t
|
||||||
|
.members
|
||||||
|
.into_iter()
|
||||||
|
.map(|m| {
|
||||||
|
let id = m.id;
|
||||||
|
self.fold_declaration_type(*m.ty)
|
||||||
|
.map(|ty| DeclarationStructMember { ty: box ty, id })
|
||||||
|
})
|
||||||
|
.collect::<Result<_, _>>()?,
|
||||||
|
..t
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_assignee(
|
fn fold_assignee(
|
||||||
&mut self,
|
&mut self,
|
||||||
a: TypedAssignee<'ast, T>,
|
a: TypedAssignee<'ast, T>,
|
||||||
|
@ -909,6 +958,7 @@ pub fn fold_declaration_function_key<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
key: DeclarationFunctionKey<'ast>,
|
key: DeclarationFunctionKey<'ast>,
|
||||||
) -> Result<DeclarationFunctionKey<'ast>, F::Error> {
|
) -> Result<DeclarationFunctionKey<'ast>, F::Error> {
|
||||||
Ok(DeclarationFunctionKey {
|
Ok(DeclarationFunctionKey {
|
||||||
|
module: f.fold_module_id(key.module)?,
|
||||||
signature: f.fold_signature(key.signature)?,
|
signature: f.fold_signature(key.signature)?,
|
||||||
..key
|
..key
|
||||||
})
|
})
|
||||||
|
@ -955,6 +1005,13 @@ fn fold_signature<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_declaration_constant<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
|
_: &mut F,
|
||||||
|
c: DeclarationConstant<'ast>,
|
||||||
|
) -> Result<DeclarationConstant<'ast>, F::Error> {
|
||||||
|
Ok(c)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
pub fn fold_array_expression<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
f: &mut F,
|
f: &mut F,
|
||||||
e: ArrayExpression<'ast, T>,
|
e: ArrayExpression<'ast, T>,
|
||||||
|
@ -1046,7 +1103,9 @@ pub fn fold_constant_symbol<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
) -> Result<TypedConstantSymbol<'ast, T>, F::Error> {
|
) -> Result<TypedConstantSymbol<'ast, T>, F::Error> {
|
||||||
match s {
|
match s {
|
||||||
TypedConstantSymbol::Here(tc) => Ok(TypedConstantSymbol::Here(f.fold_constant(tc)?)),
|
TypedConstantSymbol::Here(tc) => Ok(TypedConstantSymbol::Here(f.fold_constant(tc)?)),
|
||||||
there => Ok(there),
|
TypedConstantSymbol::There(id) => Ok(TypedConstantSymbol::There(
|
||||||
|
f.fold_canonical_constant_identifier(id)?,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1056,7 +1115,10 @@ pub fn fold_function_symbol<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
) -> Result<TypedFunctionSymbol<'ast, T>, F::Error> {
|
) -> Result<TypedFunctionSymbol<'ast, T>, F::Error> {
|
||||||
match s {
|
match s {
|
||||||
TypedFunctionSymbol::Here(fun) => Ok(TypedFunctionSymbol::Here(f.fold_function(fun)?)),
|
TypedFunctionSymbol::Here(fun) => Ok(TypedFunctionSymbol::Here(f.fold_function(fun)?)),
|
||||||
there => Ok(there), // by default, do not fold modules recursively
|
TypedFunctionSymbol::There(key) => Ok(TypedFunctionSymbol::There(
|
||||||
|
f.fold_declaration_function_key(key)?,
|
||||||
|
)),
|
||||||
|
s => Ok(s),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1088,6 +1150,6 @@ pub fn fold_program<'ast, T: Field, F: ResultFolder<'ast, T>>(
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(module_id, module)| f.fold_module(module).map(|m| (module_id, m)))
|
.map(|(module_id, module)| f.fold_module(module).map(|m| (module_id, m)))
|
||||||
.collect::<Result<_, _>>()?,
|
.collect::<Result<_, _>>()?,
|
||||||
main: p.main,
|
main: f.fold_module_id(p.main)?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,37 +101,51 @@ impl<'ast> fmt::Display for GenericIdentifier<'ast> {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SpecializationError;
|
pub struct SpecializationError;
|
||||||
|
|
||||||
|
pub type ConstantIdentifier<'ast> = &'ast str;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
|
||||||
|
pub struct CanonicalConstantIdentifier<'ast> {
|
||||||
|
pub module: OwnedTypedModuleId,
|
||||||
|
pub id: ConstantIdentifier<'ast>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ast> CanonicalConstantIdentifier<'ast> {
|
||||||
|
pub fn new(id: ConstantIdentifier<'ast>, module: OwnedTypedModuleId) -> Self {
|
||||||
|
CanonicalConstantIdentifier { module, id }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum Constant<'ast> {
|
pub enum DeclarationConstant<'ast> {
|
||||||
Generic(GenericIdentifier<'ast>),
|
Generic(GenericIdentifier<'ast>),
|
||||||
Concrete(u32),
|
Concrete(u32),
|
||||||
Identifier(&'ast str, usize),
|
Constant(CanonicalConstantIdentifier<'ast>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<u32> for Constant<'ast> {
|
impl<'ast> From<u32> for DeclarationConstant<'ast> {
|
||||||
fn from(e: u32) -> Self {
|
fn from(e: u32) -> Self {
|
||||||
Constant::Concrete(e)
|
DeclarationConstant::Concrete(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<usize> for Constant<'ast> {
|
impl<'ast> From<usize> for DeclarationConstant<'ast> {
|
||||||
fn from(e: usize) -> Self {
|
fn from(e: usize) -> Self {
|
||||||
Constant::Concrete(e as u32)
|
DeclarationConstant::Concrete(e as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> From<GenericIdentifier<'ast>> for Constant<'ast> {
|
impl<'ast> From<GenericIdentifier<'ast>> for DeclarationConstant<'ast> {
|
||||||
fn from(e: GenericIdentifier<'ast>) -> Self {
|
fn from(e: GenericIdentifier<'ast>) -> Self {
|
||||||
Constant::Generic(e)
|
DeclarationConstant::Generic(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> fmt::Display for Constant<'ast> {
|
impl<'ast> fmt::Display for DeclarationConstant<'ast> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Constant::Generic(i) => write!(f, "{}", i),
|
DeclarationConstant::Generic(i) => write!(f, "{}", i),
|
||||||
Constant::Concrete(v) => write!(f, "{}", v),
|
DeclarationConstant::Concrete(v) => write!(f, "{}", v),
|
||||||
Constant::Identifier(v, _) => write!(f, "{}", v),
|
DeclarationConstant::Constant(v) => write!(f, "{}/{}", v.module.display(), v.id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -142,15 +156,17 @@ impl<'ast, T> From<usize> for UExpression<'ast, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast, T> From<Constant<'ast>> for UExpression<'ast, T> {
|
impl<'ast, T> From<DeclarationConstant<'ast>> for UExpression<'ast, T> {
|
||||||
fn from(c: Constant<'ast>) -> Self {
|
fn from(c: DeclarationConstant<'ast>) -> Self {
|
||||||
match c {
|
match c {
|
||||||
Constant::Generic(i) => {
|
DeclarationConstant::Generic(i) => {
|
||||||
UExpressionInner::Identifier(i.name.into()).annotate(UBitwidth::B32)
|
UExpressionInner::Identifier(i.name.into()).annotate(UBitwidth::B32)
|
||||||
}
|
}
|
||||||
Constant::Concrete(v) => UExpressionInner::Value(v as u128).annotate(UBitwidth::B32),
|
DeclarationConstant::Concrete(v) => {
|
||||||
Constant::Identifier(v, size) => {
|
UExpressionInner::Value(v as u128).annotate(UBitwidth::B32)
|
||||||
UExpressionInner::Identifier(Identifier::from(v)).annotate(UBitwidth::from(size))
|
}
|
||||||
|
DeclarationConstant::Constant(v) => {
|
||||||
|
UExpressionInner::Identifier(Identifier::from(v.id)).annotate(UBitwidth::B32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,12 +185,12 @@ impl<'ast, T> TryInto<usize> for UExpression<'ast, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ast> TryInto<usize> for Constant<'ast> {
|
impl<'ast> TryInto<usize> for DeclarationConstant<'ast> {
|
||||||
type Error = SpecializationError;
|
type Error = SpecializationError;
|
||||||
|
|
||||||
fn try_into(self) -> Result<usize, Self::Error> {
|
fn try_into(self) -> Result<usize, Self::Error> {
|
||||||
match self {
|
match self {
|
||||||
Constant::Concrete(v) => Ok(v as usize),
|
DeclarationConstant::Concrete(v) => Ok(v as usize),
|
||||||
_ => Err(SpecializationError),
|
_ => Err(SpecializationError),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -190,7 +206,7 @@ pub struct GStructMember<S> {
|
||||||
pub ty: Box<GType<S>>,
|
pub ty: Box<GType<S>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationStructMember<'ast> = GStructMember<Constant<'ast>>;
|
pub type DeclarationStructMember<'ast> = GStructMember<DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteStructMember = GStructMember<usize>;
|
pub type ConcreteStructMember = GStructMember<usize>;
|
||||||
pub type StructMember<'ast, T> = GStructMember<UExpression<'ast, T>>;
|
pub type StructMember<'ast, T> = GStructMember<UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -242,7 +258,7 @@ pub struct GArrayType<S> {
|
||||||
pub ty: Box<GType<S>>,
|
pub ty: Box<GType<S>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationArrayType<'ast> = GArrayType<Constant<'ast>>;
|
pub type DeclarationArrayType<'ast> = GArrayType<DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteArrayType = GArrayType<usize>;
|
pub type ConcreteArrayType = GArrayType<usize>;
|
||||||
pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
|
pub type ArrayType<'ast, T> = GArrayType<UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -250,7 +266,7 @@ impl<'ast, T: PartialEq> PartialEq<DeclarationArrayType<'ast>> for ArrayType<'as
|
||||||
fn eq(&self, other: &DeclarationArrayType<'ast>) -> bool {
|
fn eq(&self, other: &DeclarationArrayType<'ast>) -> bool {
|
||||||
*self.ty == *other.ty
|
*self.ty == *other.ty
|
||||||
&& match (self.size.as_inner(), &other.size) {
|
&& match (self.size.as_inner(), &other.size) {
|
||||||
(UExpressionInner::Value(l), Constant::Concrete(r)) => *l as u32 == *r,
|
(UExpressionInner::Value(l), DeclarationConstant::Concrete(r)) => *l as u32 == *r,
|
||||||
_ => true,
|
_ => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -349,7 +365,7 @@ pub struct GStructType<S> {
|
||||||
pub members: Vec<GStructMember<S>>,
|
pub members: Vec<GStructMember<S>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationStructType<'ast> = GStructType<Constant<'ast>>;
|
pub type DeclarationStructType<'ast> = GStructType<DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteStructType = GStructType<usize>;
|
pub type ConcreteStructType = GStructType<usize>;
|
||||||
pub type StructType<'ast, T> = GStructType<UExpression<'ast, T>>;
|
pub type StructType<'ast, T> = GStructType<UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -588,7 +604,7 @@ impl<'de, S: Deserialize<'de>> Deserialize<'de> for GType<S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationType<'ast> = GType<Constant<'ast>>;
|
pub type DeclarationType<'ast> = GType<DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteType = GType<usize>;
|
pub type ConcreteType = GType<usize>;
|
||||||
pub type Type<'ast, T> = GType<UExpression<'ast, T>>;
|
pub type Type<'ast, T> = GType<UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -711,7 +727,7 @@ impl<'ast, T: fmt::Display + PartialEq + fmt::Debug> Type<'ast, T> {
|
||||||
// check the size if types match
|
// check the size if types match
|
||||||
match (&l.size.as_inner(), &r.size) {
|
match (&l.size.as_inner(), &r.size) {
|
||||||
// compare the sizes for concrete ones
|
// compare the sizes for concrete ones
|
||||||
(UExpressionInner::Value(v), Constant::Concrete(c)) => {
|
(UExpressionInner::Value(v), DeclarationConstant::Concrete(c)) => {
|
||||||
(*v as u32) == *c
|
(*v as u32) == *c
|
||||||
}
|
}
|
||||||
_ => true,
|
_ => true,
|
||||||
|
@ -772,7 +788,7 @@ pub struct GFunctionKey<'ast, S> {
|
||||||
pub signature: GSignature<S>,
|
pub signature: GSignature<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, Constant<'ast>>;
|
pub type DeclarationFunctionKey<'ast> = GFunctionKey<'ast, DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, usize>;
|
pub type ConcreteFunctionKey<'ast> = GFunctionKey<'ast, usize>;
|
||||||
pub type FunctionKey<'ast, T> = GFunctionKey<'ast, UExpression<'ast, T>>;
|
pub type FunctionKey<'ast, T> = GFunctionKey<'ast, UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -948,7 +964,7 @@ pub mod signature {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationSignature<'ast> = GSignature<Constant<'ast>>;
|
pub type DeclarationSignature<'ast> = GSignature<DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteSignature = GSignature<usize>;
|
pub type ConcreteSignature = GSignature<usize>;
|
||||||
pub type Signature<'ast, T> = GSignature<UExpression<'ast, T>>;
|
pub type Signature<'ast, T> = GSignature<UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
@ -968,15 +984,17 @@ pub mod signature {
|
||||||
&& match &t0.size {
|
&& match &t0.size {
|
||||||
// if the declared size is an identifier, we insert into the map, or check if the concrete size
|
// if the declared size is an identifier, we insert into the map, or check if the concrete size
|
||||||
// matches if this identifier is already in the map
|
// matches if this identifier is already in the map
|
||||||
Constant::Generic(id) => match constants.0.entry(id.clone()) {
|
DeclarationConstant::Generic(id) => match constants.0.entry(id.clone()) {
|
||||||
Entry::Occupied(e) => *e.get() == s1,
|
Entry::Occupied(e) => *e.get() == s1,
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
e.insert(s1);
|
e.insert(s1);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Constant::Concrete(s0) => s1 == *s0 as usize,
|
DeclarationConstant::Concrete(s0) => s1 == *s0 as usize,
|
||||||
Constant::Identifier(_, s0) => s1 == *s0,
|
// in the case of a constant, we do not know the value yet, so we optimistically assume it's correct
|
||||||
|
// if it does not match, it will be caught during inlining
|
||||||
|
DeclarationConstant::Constant(..) => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(DeclarationType::FieldElement, GType::FieldElement)
|
(DeclarationType::FieldElement, GType::FieldElement)
|
||||||
|
@ -1000,9 +1018,11 @@ pub mod signature {
|
||||||
|
|
||||||
let ty = box specialize_type(*t0.ty, &constants)?;
|
let ty = box specialize_type(*t0.ty, &constants)?;
|
||||||
let size = match t0.size {
|
let size = match t0.size {
|
||||||
Constant::Generic(s) => constants.0.get(&s).cloned().ok_or(s),
|
DeclarationConstant::Generic(s) => constants.0.get(&s).cloned().ok_or(s),
|
||||||
Constant::Concrete(s) => Ok(s.into()),
|
DeclarationConstant::Concrete(s) => Ok(s.into()),
|
||||||
Constant::Identifier(_, s) => Ok((s as u32).into()),
|
DeclarationConstant::Constant(..) => {
|
||||||
|
unreachable!("identifiers should have been removed in constant inlining")
|
||||||
|
}
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
GType::Array(GArrayType { size, ty })
|
GType::Array(GArrayType { size, ty })
|
||||||
|
@ -1053,7 +1073,7 @@ pub mod signature {
|
||||||
assert_eq!(self.generics.len(), values.len());
|
assert_eq!(self.generics.len(), values.len());
|
||||||
|
|
||||||
let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() {
|
let decl_generics = self.generics.iter().map(|g| match g.clone().unwrap() {
|
||||||
Constant::Generic(g) => g,
|
DeclarationConstant::Generic(g) => g,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1096,7 +1116,7 @@ pub mod signature {
|
||||||
v.map(|v| {
|
v.map(|v| {
|
||||||
(
|
(
|
||||||
match g.clone().unwrap() {
|
match g.clone().unwrap() {
|
||||||
Constant::Generic(g) => g,
|
DeclarationConstant::Generic(g) => g,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
v,
|
v,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::typed_absy::types::{Constant, GStructType, UBitwidth};
|
use crate::typed_absy::types::{DeclarationConstant, GStructType, UBitwidth};
|
||||||
use crate::typed_absy::types::{GType, SpecializationError};
|
use crate::typed_absy::types::{GType, SpecializationError};
|
||||||
use crate::typed_absy::Identifier;
|
use crate::typed_absy::Identifier;
|
||||||
use crate::typed_absy::UExpression;
|
use crate::typed_absy::UExpression;
|
||||||
|
@ -11,7 +11,7 @@ pub struct GVariable<'ast, S> {
|
||||||
pub _type: GType<S>,
|
pub _type: GType<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DeclarationVariable<'ast> = GVariable<'ast, Constant<'ast>>;
|
pub type DeclarationVariable<'ast> = GVariable<'ast, DeclarationConstant<'ast>>;
|
||||||
pub type ConcreteVariable<'ast> = GVariable<'ast, usize>;
|
pub type ConcreteVariable<'ast> = GVariable<'ast, usize>;
|
||||||
pub type Variable<'ast, T> = GVariable<'ast, UExpression<'ast, T>>;
|
pub type Variable<'ast, T> = GVariable<'ast, UExpression<'ast, T>>;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"entry_point": "./tests/tests/constants/import/destination.zok",
|
||||||
|
"tests": []
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
from "./origin.zok" import foo
|
||||||
|
def main():
|
||||||
|
assert(foo([1, 1]))
|
||||||
|
return
|
|
@ -0,0 +1,3 @@
|
||||||
|
const u32 N = 1 + 1
|
||||||
|
def foo(field[N] a) -> bool:
|
||||||
|
return true
|
|
@ -3,9 +3,17 @@
|
||||||
import "utils/casts/u32_to_bits"
|
import "utils/casts/u32_to_bits"
|
||||||
import "utils/casts/u32_from_bits"
|
import "utils/casts/u32_from_bits"
|
||||||
|
|
||||||
|
// right rotation
|
||||||
def rotr32<N>(u32 x) -> u32:
|
def rotr32<N>(u32 x) -> u32:
|
||||||
return (x >> N) | (x << (32 - N))
|
return (x >> N) | (x << (32 - N))
|
||||||
|
|
||||||
|
// change endianness
|
||||||
|
def swap_u32(u32 val) -> u32:
|
||||||
|
return (val << 24) | \
|
||||||
|
((val << 8) & 0x00ff0000) | \
|
||||||
|
((val >> 8) & 0x0000ff00) | \
|
||||||
|
((val >> 24) & 0x000000ff)
|
||||||
|
|
||||||
def blake2s_iv() -> (u32[8]):
|
def blake2s_iv() -> (u32[8]):
|
||||||
return [
|
return [
|
||||||
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
|
||||||
|
@ -73,8 +81,8 @@ def blake2s_init(u32[2] p) -> (u32[8]):
|
||||||
iv[3],
|
iv[3],
|
||||||
iv[4],
|
iv[4],
|
||||||
iv[5],
|
iv[5],
|
||||||
iv[6] ^ p[0],
|
iv[6] ^ swap_u32(p[0]),
|
||||||
iv[7] ^ p[1]
|
iv[7] ^ swap_u32(p[1])
|
||||||
]
|
]
|
||||||
return h
|
return h
|
||||||
|
|
||||||
|
@ -84,6 +92,13 @@ def main<K>(u32[K][16] input, u32[2] p) -> (u32[8]):
|
||||||
u32 t0 = 0
|
u32 t0 = 0
|
||||||
u32 t1 = 0
|
u32 t1 = 0
|
||||||
|
|
||||||
|
// change endianness of inputs from big endian to little endian
|
||||||
|
for u32 i in 0..K do
|
||||||
|
for u32 j in 0..16 do
|
||||||
|
input[i][j] = swap_u32(input[i][j])
|
||||||
|
endfor
|
||||||
|
endfor
|
||||||
|
|
||||||
for u32 i in 0..K-1 do
|
for u32 i in 0..K-1 do
|
||||||
t0 = (i + 1) * 64
|
t0 = (i + 1) * 64
|
||||||
t1 = if t0 == 0 then t1 + 1 else t1 fi
|
t1 = if t0 == 0 then t1 + 1 else t1 fi
|
||||||
|
@ -94,4 +109,10 @@ def main<K>(u32[K][16] input, u32[2] p) -> (u32[8]):
|
||||||
t1 = if t0 == 0 then t1 + 1 else t1 fi
|
t1 = if t0 == 0 then t1 + 1 else t1 fi
|
||||||
|
|
||||||
h = blake2s_compression(h, input[K - 1], [t0, t1], true)
|
h = blake2s_compression(h, input[K - 1], [t0, t1], true)
|
||||||
|
|
||||||
|
// change endianness of output from little endian to big endian
|
||||||
|
for u32 i in 0..8 do
|
||||||
|
h[i] = swap_u32(h[i])
|
||||||
|
endfor
|
||||||
|
|
||||||
return h
|
return h
|
|
@ -28,6 +28,12 @@ def rc() -> u64[24]:
|
||||||
def rotl64(u64 x, u32 n) -> u64:
|
def rotl64(u64 x, u32 n) -> u64:
|
||||||
return ((x << n) | (x >> (64 - n)))
|
return ((x << n) | (x >> (64 - n)))
|
||||||
|
|
||||||
|
// change endianness
|
||||||
|
def swap_u64(u64 val) -> u64:
|
||||||
|
val = ((val << 8) & 0xFF00FF00FF00FF00) | ((val >> 8) & 0x00FF00FF00FF00FF)
|
||||||
|
val = ((val << 16) & 0xFFFF0000FFFF0000) | ((val >> 16) & 0x0000FFFF0000FFFF)
|
||||||
|
return (val << 32) | (val >> 32)
|
||||||
|
|
||||||
// compression function
|
// compression function
|
||||||
def keccakf(u64[25] st) -> u64[25]:
|
def keccakf(u64[25] st) -> u64[25]:
|
||||||
u32[24] rotc = rho()
|
u32[24] rotc = rho()
|
||||||
|
@ -80,6 +86,11 @@ def main<N, W>(u64[N] input, u64 pad) -> u64[25]:
|
||||||
u32 rate = (200 - (W / 4)) / 8
|
u32 rate = (200 - (W / 4)) / 8
|
||||||
u32 pt = 0
|
u32 pt = 0
|
||||||
|
|
||||||
|
// change endianness of inputs from big endian to little endian
|
||||||
|
for u32 i in 0..N do
|
||||||
|
input[i] = swap_u64(input[i])
|
||||||
|
endfor
|
||||||
|
|
||||||
// update
|
// update
|
||||||
for u32 i in 0..N do
|
for u32 i in 0..N do
|
||||||
q[pt] = q[pt] ^ input[i]
|
q[pt] = q[pt] ^ input[i]
|
||||||
|
@ -90,6 +101,11 @@ def main<N, W>(u64[N] input, u64 pad) -> u64[25]:
|
||||||
// finalize
|
// finalize
|
||||||
q[pt] = q[pt] ^ pad
|
q[pt] = q[pt] ^ pad
|
||||||
q[rate - 1] = q[rate - 1] ^ 0x8000000000000000
|
q[rate - 1] = q[rate - 1] ^ 0x8000000000000000
|
||||||
|
|
||||||
q = keccakf(q)
|
q = keccakf(q)
|
||||||
|
|
||||||
|
// change endianness of output from little endian to big endian
|
||||||
|
for u32 i in 0..W/64 do
|
||||||
|
q[i] = swap_u64(q[i])
|
||||||
|
endfor
|
||||||
|
|
||||||
return q
|
return q
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/blake2/blake2s"
|
import "hashes/blake2/blake2s"
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from hashlib import blake2s
|
||||||
|
|
||||||
|
// >>> digest = blake2s()
|
||||||
|
// >>> digest.update(b'\x12\x34\x56\x78' * 32)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '4858b8174f8f5851ddac0507003b2490f42c33df8362770c5e79b770c84ffdb4'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u32[8] h = blake2s::<2>([[0; 16]; 2])
|
u32[8] h = blake2s::<2>([[0x12345678; 16]; 2]) // 2 * 16 * 32 = 1024 bit input
|
||||||
assert(h == [0x2005424E, 0x7BCE81B9, 0x2CCEF4DB, 0x94DBBA4D, 0x7D9B0750, 0xB53797EB, 0xD3572923, 0xCB01F823])
|
assert(h == [
|
||||||
|
0x4858B817, 0x4F8F5851, 0xDDAC0507, 0x003B2490,
|
||||||
|
0xF42C33DF, 0x8362770C, 0x5E79B770, 0xC84FFDB4
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/blake2/blake2s"
|
import "hashes/blake2/blake2s"
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from hashlib import blake2s
|
||||||
|
|
||||||
|
// >>> digest = blake2s()
|
||||||
|
// >>> digest.update(b'\x12\x34\x56\x78' * 48)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '879043503b04cab2f3c0d7a4bb01c1db74c238c49887da84e8a619893092b6e2'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u32[8] h = blake2s::<3>([[0x42424242; 16]; 3])
|
u32[8] h = blake2s::<3>([[0x12345678; 16]; 3]) // 3 * 16 * 32 = 1536 bit input
|
||||||
assert(h == [0x804BD0E6, 0x90AD426E, 0x6BCF0BAD, 0xCB2D22C1, 0xF717B3C3, 0x4D9CB47F, 0xEB541A97, 0x061D9ED0])
|
assert(h == [
|
||||||
|
0x87904350, 0x3B04CAB2, 0xF3C0D7A4, 0xBB01C1DB,
|
||||||
|
0x74C238C4, 0x9887DA84, 0xE8A61989, 0x3092B6E2
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/blake2/blake2s"
|
import "hashes/blake2/blake2s"
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from hashlib import blake2s
|
||||||
|
|
||||||
|
// >>> digest = blake2s()
|
||||||
|
// >>> digest.update(b'\x12\x34\x56\x78' * 16)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '52af1aec3e6663bcc759d55fc7557fbb2f710219f0de138b1b52c919f5c94415'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u32[8] h = blake2s::<1>([[0; 16]])
|
u32[8] h = blake2s::<1>([[0x12345678; 16]; 1]) // 16 * 32 = 512 bit input
|
||||||
assert(h == [0x7CDB09AE, 0xB4424FD5, 0xB609EF90, 0xF61A54BC, 0x9B95E488, 0x353FC5B8, 0xE3566F9A, 0xA354B48A])
|
assert(h == [
|
||||||
|
0x52AF1AEC, 0x3E6663BC, 0xC759D55F, 0xC7557FBB,
|
||||||
|
0x2F710219, 0xF0DE138B, 0x1B52C919, 0xF5C94415
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/blake2/blake2s"
|
import "hashes/blake2/blake2s"
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from hashlib import blake2s
|
||||||
|
|
||||||
|
// >>> digest = blake2s()
|
||||||
|
// >>> digest.update(b'\x12\x34\x56\x78' * 256)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// 'b41c4704f49df139039bbc91c6e23a84198ffedc78d0b677e8b2a6a57f3460e8'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u32[8] h = blake2s::<16>([[0; 16]; 16])
|
u32[8] h = blake2s::<16>([[0x12345678; 16]; 16]) // 16 * 16 * 32 = 8192 bit input
|
||||||
assert(h == [0x63665303, 0x046C502A, 0xC8514A5D, 0x67B7E833, 0xA9DAD591, 0xB421A8BC, 0x662A73A2, 0x2DA25AFB])
|
assert(h == [
|
||||||
|
0xB41C4704, 0xF49DF139, 0x039BBC91, 0xC6E23A84,
|
||||||
|
0x198FFEDC, 0x78D0B677, 0xE8B2A6A5, 0x7F3460E8
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/blake2/blake2s_p" as blake2s
|
import "hashes/blake2/blake2s_p" as blake2s
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from hashlib import blake2s
|
||||||
|
|
||||||
|
// >>> digest = blake2s(person=b'\x12\x34\x56\x78\x00\x00\x00\x00')
|
||||||
|
// >>> digest.update(b'\x12\x34\x56\x78' * 16)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '780105bc9ca7633b1f289b3d1558dece65e04ac23f88e711dc29600fa3e0258a'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u32[8] h = blake2s::<1>([[0; 16]], [0x12345678, 0])
|
u32[8] h = blake2s::<1>([[0x12345678; 16]; 1], [0x12345678, 0])
|
||||||
assert(h == [0xC63C8C31, 0x5FCA3E69, 0x13850D46, 0x1DE48657, 0x208D2534, 0x9AA6E0EF, 0xAFEE7610, 0xFBDFAC13])
|
assert(h == [
|
||||||
|
0x780105BC, 0x9CA7633B, 0x1F289B3D, 0x1558DECE,
|
||||||
|
0x65E04AC2, 0x3F88E711, 0xDC29600F, 0xA3E0258A
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,14 @@
|
||||||
import "hashes/keccak/256bit" as keccak256
|
import "hashes/keccak/256bit" as keccak256
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import keccak
|
||||||
|
|
||||||
|
// >>> digest = keccak.new(digest_bits=256)
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '33d0141407fee6e5d9caf6ae44e840bc67a37da55e3c845fbc2b4a6dce1f02f0'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[4] h = keccak256::<20>([42; 20])
|
u64[4] h = keccak256::<20>([42; 20])
|
||||||
assert(h == [0x09330DD35B609CA9, 0xDACFC1598C95602C, 0xACD911013FB018F3, 0x17233D68F05E0826])
|
assert(h == [0x33D0141407FEE6E5, 0xD9CAF6AE44E840BC, 0x67A37DA55E3C845F, 0xBC2B4A6DCE1F02F0])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/keccak/384bit" as keccak384
|
import "hashes/keccak/384bit" as keccak384
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import keccak
|
||||||
|
|
||||||
|
// >>> digest = keccak.new(digest_bits=384)
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// 'a944b9b859c1e69d66b52d4cf1f678b24ed8a9ccb0a32bbe882af8a3a1acbd3b68eed9c628307e5d3789f1a64a50e8e7'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[6] h = keccak384::<20>([42; 20])
|
u64[6] h = keccak384::<20>([42; 20])
|
||||||
assert(h == [0x2E9DCE590F0A1908, 0x0C4234AB952C5598, 0xFB2DF066B44780C2, 0x717039E101D4A8DA, 0xBAD1EFE140C4B2C4, 0xFAE08DAC3438416E])
|
assert(h == [
|
||||||
|
0xA944B9B859C1E69D, 0x66B52D4CF1F678B2, 0x4ED8A9CCB0A32BBE,
|
||||||
|
0x882AF8A3A1ACBD3B, 0x68EED9C628307E5D, 0x3789F1A64A50E8E7
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,9 +1,17 @@
|
||||||
import "hashes/keccak/512bit" as keccak512
|
import "hashes/keccak/512bit" as keccak512
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import keccak
|
||||||
|
|
||||||
|
// >>> digest = keccak.new(digest_bits=512)
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '5451affca80019c7ac9a7ff647ca073b56e19d55857031df14e00bb1d36ed18a05bdac99bcc0417240dea0cf3fddd19144b8d1e9618fd3f6c8f1a79f7e489eb8'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[8] h = keccak512::<20>([42; 20])
|
u64[8] h = keccak512::<20>([42; 20])
|
||||||
assert(h == [
|
assert(h == [
|
||||||
0x2716192386255918, 0x68DFF390376BBF13, 0xBD695ADA4CD230E3, 0xF3B00388676A04D3,
|
0x5451AFFCA80019C7, 0xAC9A7FF647CA073B, 0x56E19D55857031DF, 0x14E00BB1D36ED18A,
|
||||||
0x484F3F1BB9F36A09, 0x9D0119067282F940, 0xDF27DE0F48072A66, 0xF5957972134160EB
|
0x05BDAC99BCC04172, 0x40DEA0CF3FDDD191, 0x44B8D1E9618FD3F6, 0xC8F1A79F7E489EB8
|
||||||
])
|
])
|
||||||
return
|
return
|
|
@ -1,6 +1,14 @@
|
||||||
import "hashes/sha3/256bit" as sha3_256
|
import "hashes/sha3/256bit" as sha3_256
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import SHA3_256
|
||||||
|
|
||||||
|
// >>> digest = SHA3_256.new()
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '18d00c9e97cd5516243b67b243ede9e2cf0d45d3a844d33340bfc4efc9165100'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[4] h = sha3_256::<20>([42; 20])
|
u64[4] h = sha3_256::<20>([42; 20])
|
||||||
assert(h == [0x84350A3A90DED183, 0x70518606C7DC401A, 0x2D44F39C0FCEAC92, 0x3E9533A716130C5A])
|
assert(h == [0x18D00C9E97CD5516, 0x243B67B243EDE9E2, 0xCF0D45D3A844D333, 0x40BFC4EFC9165100])
|
||||||
return
|
return
|
|
@ -1,6 +1,17 @@
|
||||||
import "hashes/sha3/384bit" as sha3_384
|
import "hashes/sha3/384bit" as sha3_384
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import SHA3_384
|
||||||
|
|
||||||
|
// >>> digest = SHA3_384.new()
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// 'fbb5abd69915e316836d438f0e833a3ebd0f2d8a11e17e248c96c77210b183aab0874eaaef37609d2c4a9a37a6e9740f'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[6] h = sha3_384::<20>([42; 20])
|
u64[6] h = sha3_384::<20>([42; 20])
|
||||||
assert(h == [0x75A036FA8B615B37, 0x6C73086BB56F092C, 0x536E658916EC18AE, 0xB2F2EEE620CDF698, 0xB7E904DE62A70A31, 0x84FDAA0665836ADD])
|
assert(h == [
|
||||||
|
0xFBB5ABD69915E316, 0x836D438F0E833A3E, 0xBD0F2D8A11E17E24,
|
||||||
|
0x8C96C77210B183AA, 0xB0874EAAEF37609D, 0x2C4A9A37A6E9740F
|
||||||
|
])
|
||||||
return
|
return
|
|
@ -1,9 +1,17 @@
|
||||||
import "hashes/sha3/512bit" as sha3_512
|
import "hashes/sha3/512bit" as sha3_512
|
||||||
|
|
||||||
|
// Python code:
|
||||||
|
// >>> from Crypto.Hash import SHA3_512
|
||||||
|
|
||||||
|
// >>> digest = SHA3_512.new()
|
||||||
|
// >>> digest.update(b'\x00\x00\x00\x00\x00\x00\x00\x2A' * 20)
|
||||||
|
// >>> digest.hexdigest()
|
||||||
|
// '73a0967b68de5ce1093cbd7482fd4de9ccc9c782e2edc71b583d26fe16fb19e3322a2a024b7f6e163fbb1a15161686dd3a39233f9cf8616e7c74e91fa1aa3b2b'
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
u64[8] h = sha3_512::<20>([42; 20])
|
u64[8] h = sha3_512::<20>([42; 20])
|
||||||
assert(h == [
|
assert(h == [
|
||||||
0x22DFD92B47C60DAC, 0xDA47C8C247A84FA2, 0x7C5809F122D6950A, 0x8034D41097680656,
|
0x73A0967B68DE5CE1, 0x093CBD7482FD4DE9, 0xCCC9C782E2EDC71B, 0x583D26FE16FB19E3,
|
||||||
0xD6D06F820B046994, 0xF62743594A554B88, 0x4966E0821CB4D667, 0x974D4391624C5619
|
0x322A2A024B7F6E16, 0x3FBB1A15161686DD, 0x3A39233F9CF8616E, 0x7C74E91FA1AA3B2B
|
||||||
])
|
])
|
||||||
return
|
return
|
Loading…
Reference in a new issue