1
0
Fork 0
mirror of synced 2025-09-23 12:18:44 +00:00

add log to core and env_log to cli

This commit is contained in:
schaeff 2021-07-29 11:13:54 +02:00
parent 7c2a23df63
commit dbcd0bd558
9 changed files with 122 additions and 51 deletions

View file

@ -12,6 +12,8 @@ bellman = ["zokrates_core/bellman"]
ark = ["zokrates_core/ark"]
[dependencies]
log = "0.4"
env_logger = "0.9.0"
cfg-if = "0.1"
clap = "2.26.2"
bincode = "0.8.0"

View file

@ -20,6 +20,8 @@ fn main() {
// set a custom panic hook
std::panic::set_hook(Box::new(panic_hook));
env_logger::init();
cli().unwrap_or_else(|e| {
println!("{}", e);
std::process::exit(1);

View file

@ -99,6 +99,8 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
let abi_spec_path = Path::new(sub_matches.value_of("abi-spec").unwrap());
let hr_output_path = bin_output_path.to_path_buf().with_extension("ztf");
log::debug!("Load entry point file {}", path.display());
let file = File::open(path.clone())
.map_err(|why| format!("Could not open {}: {}", path.display(), why))?;
@ -131,6 +133,9 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
.isolate_branches(sub_matches.is_present("isolate-branches"));
let resolver = FileSystemResolver::with_stdlib_root(stdlib_path);
log::debug!("Compile");
let artifacts: CompilationArtifacts<T> = compile(source, path, Some(&resolver), &config)
.map_err(|e| {
format!(
@ -148,6 +153,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
let num_constraints = program_flattened.constraint_count();
// serialize flattened program and write to binary file
log::debug!("Serialize program");
let bin_output_file = File::create(&bin_output_path)
.map_err(|why| format!("Could not create {}: {}", bin_output_path.display(), why))?;
@ -156,6 +162,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
program_flattened.serialize(&mut writer);
// serialize ABI spec and write to JSON file
log::debug!("Serialize ABI");
let abi_spec_file = File::create(&abi_spec_path)
.map_err(|why| format!("Could not create {}: {}", abi_spec_path.display(), why))?;
@ -173,6 +180,7 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
if sub_matches.is_present("ztf") {
// write human-readable output file
log::debug!("Serialize human readable program");
let hr_output_file = File::create(&hr_output_path)
.map_err(|why| format!("Could not create {}: {}", hr_output_path.display(), why))?;

View file

@ -16,6 +16,7 @@ multicore = ["bellman_ce/multicore"]
ark = ["ark-ff", "ark-ec", "ark-bn254", "ark-bls12-377", "ark-bw6-761", "ark-gm17", "ark-serialize", "ark-relations", "ark-marlin", "ark-poly", "ark-poly-commit", "zokrates_field/ark", "sha2"]
[dependencies]
log = "0.4"
cfg-if = "0.1"
num = { version = "0.1.36", default-features = false }
num-bigint = { version = "0.2", default-features = false }

View file

@ -192,18 +192,23 @@ pub fn compile<T: Field, E: Into<imports::Error>>(
let (typed_ast, abi) = check_with_arena(source, location, resolver, config, &arena)?;
// flatten input program
log::debug!("Flatten");
let program_flattened = Flattener::flatten(typed_ast, config);
// analyse (constant propagation after call resolution)
log::debug!("Analyse flat program");
let program_flattened = program_flattened.analyse();
// convert to ir
log::debug!("Convert to IR");
let ir_prog = ir::Prog::from(program_flattened);
// optimize
log::debug!("Optimise IR");
let optimized_ir_prog = ir_prog.optimize();
// analyse (check constraints)
log::debug!("Analyse IR");
let optimized_ir_prog = optimized_ir_prog.analyse();
Ok(CompilationArtifacts {
@ -231,7 +236,12 @@ fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
arena: &'ast Arena<String>,
) -> Result<(ZirProgram<'ast, T>, Abi), CompileErrors> {
let source = arena.alloc(source);
let compiled = compile_program::<T, E>(source, location, resolver, &arena)?;
log::debug!("Parse program with entry file {}", location.display());
let compiled = parse_program::<T, E>(source, location, resolver, &arena)?;
log::debug!("Check semantics");
// check semantics
let typed_ast = Checker::check(compiled)
@ -239,13 +249,15 @@ fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
let main_module = typed_ast.main.clone();
log::debug!("Run static analysis");
// analyse (unroll and constant propagation)
typed_ast
.analyse(config)
.map_err(|e| CompileErrors(vec![CompileErrorInner::from(e).in_file(&main_module)]))
}
pub fn compile_program<'ast, T: Field, E: Into<imports::Error>>(
pub fn parse_program<'ast, T: Field, E: Into<imports::Error>>(
source: &'ast str,
location: FilePath,
resolver: Option<&dyn Resolver<E>>,
@ -253,7 +265,7 @@ pub fn compile_program<'ast, T: Field, E: Into<imports::Error>>(
) -> Result<Program<'ast>, CompileErrors> {
let mut modules = HashMap::new();
let main = compile_module::<T, E>(&source, location.clone(), resolver, &mut modules, &arena)?;
let main = parse_module::<T, E>(&source, location.clone(), resolver, &mut modules, &arena)?;
modules.insert(location.clone(), main);
@ -263,21 +275,29 @@ pub fn compile_program<'ast, T: Field, E: Into<imports::Error>>(
})
}
pub fn compile_module<'ast, T: Field, E: Into<imports::Error>>(
pub fn parse_module<'ast, T: Field, E: Into<imports::Error>>(
source: &'ast str,
location: FilePath,
resolver: Option<&dyn Resolver<E>>,
modules: &mut HashMap<OwnedModuleId, Module<'ast>>,
arena: &'ast Arena<String>,
) -> Result<Module<'ast>, CompileErrors> {
log::debug!("Generate pest AST for {}", location.display());
let ast = pest::generate_ast(&source)
.map_err(|e| CompileErrors::from(CompileErrorInner::from(e).in_file(&location)))?;
log::debug!("Process macros for {}", location.display());
let ast = process_macros::<T>(ast)
.map_err(|e| CompileErrors::from(CompileErrorInner::from(e).in_file(&location)))?;
log::debug!("Generate absy for {}", location.display());
let module_without_imports: Module = Module::from(ast);
log::debug!("Apply imports to absy for {}", location.display());
Importer::apply_imports::<T, E>(
module_without_imports,
location.clone(),

View file

@ -40,18 +40,18 @@ pub struct Flattener<'ast, T: Field> {
}
trait FlattenOutput<T: Field>: Sized {
fn flat(&self) -> FlatExpression<T>;
fn flat(self) -> FlatExpression<T>;
}
impl<T: Field> FlattenOutput<T> for FlatExpression<T> {
fn flat(&self) -> FlatExpression<T> {
self.clone()
fn flat(self) -> FlatExpression<T> {
self
}
}
impl<T: Field> FlattenOutput<T> for FlatUExpression<T> {
fn flat(&self) -> FlatExpression<T> {
self.clone().get_field_unchecked()
fn flat(self) -> FlatExpression<T> {
self.get_field_unchecked()
}
}
@ -905,8 +905,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// Y == X * M
// 0 == (1-Y) * X
assert!(lhs.metadata.clone().unwrap().should_reduce.to_bool());
assert!(rhs.metadata.clone().unwrap().should_reduce.to_bool());
assert!(lhs.metadata.as_ref().unwrap().should_reduce.to_bool());
assert!(rhs.metadata.as_ref().unwrap().should_reduce.to_bool());
let lhs = self
.flatten_uint_expression(statements_flattened, lhs)
@ -924,7 +924,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
);
let eq = self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::FieldEq(box lhs.clone(), box rhs.clone()),
BooleanExpression::FieldEq(box lhs, box rhs),
);
FlatExpression::Add(box eq, box lt)
}
@ -1018,7 +1018,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
);
let eq = self.flatten_boolean_expression(
statements_flattened,
BooleanExpression::UintEq(box lhs.clone(), box rhs.clone()),
BooleanExpression::UintEq(box lhs, box rhs),
);
FlatExpression::Add(box eq, box lt)
}
@ -1045,7 +1045,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
box x.clone(),
box FlatExpression::Sub(box y.clone(), box name_x_or_y.into()),
),
FlatExpression::Mult(box x.clone(), box y.clone()),
FlatExpression::Mult(box x, box y),
RuntimeError::Or,
));
name_x_or_y.into()
@ -1089,9 +1089,9 @@ impl<'ast, T: Field> Flattener<'ast, T> {
bitwidth: UBitwidth,
) -> Vec<FlatUExpression<T>> {
let expression = UExpression::try_from(expression).unwrap();
let from = expression.metadata.clone().unwrap().bitwidth();
let from = expression.metadata.as_ref().unwrap().bitwidth();
let p = self.flatten_uint_expression(statements_flattened, expression);
self.get_bits(p, from as usize, bitwidth, statements_flattened)
self.get_bits(&p, from as usize, bitwidth, statements_flattened)
.into_iter()
.map(FlatUExpression::with_field)
.collect()
@ -1128,27 +1128,29 @@ impl<'ast, T: Field> Flattener<'ast, T> {
statements_flattened: &mut FlatStatements<T>,
embed: FlatEmbed,
generics: Vec<u32>,
param_expressions: Vec<ZirExpression<'ast, T>>,
mut param_expressions: Vec<ZirExpression<'ast, T>>,
) -> Vec<FlatUExpression<T>> {
match embed {
crate::embed::FlatEmbed::U64ToBits => self.flatten_u_to_bits(
statements_flattened,
param_expressions[0].clone(),
param_expressions.pop().unwrap(),
64.into(),
),
crate::embed::FlatEmbed::U32ToBits => self.flatten_u_to_bits(
statements_flattened,
param_expressions[0].clone(),
param_expressions.pop().unwrap(),
32.into(),
),
crate::embed::FlatEmbed::U16ToBits => self.flatten_u_to_bits(
statements_flattened,
param_expressions[0].clone(),
param_expressions.pop().unwrap(),
16.into(),
),
crate::embed::FlatEmbed::U8ToBits => {
self.flatten_u_to_bits(statements_flattened, param_expressions[0].clone(), 8.into())
}
crate::embed::FlatEmbed::U8ToBits => self.flatten_u_to_bits(
statements_flattened,
param_expressions.pop().unwrap(),
8.into(),
),
crate::embed::FlatEmbed::U64FromBits => {
vec![self.flatten_bits_to_u(statements_flattened, param_expressions, 64.into())]
}
@ -1293,10 +1295,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
self.define(e, statements_flattened).into()
} else if n == T::from(1) {
self.define(
FlatExpression::Sub(
box FlatExpression::Number(T::from(1)),
box e.clone(),
),
FlatExpression::Sub(box FlatExpression::Number(T::from(1)), box e),
statements_flattened,
)
.into()
@ -1319,8 +1318,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
box FlatExpression::Sub(box y.clone(), box name.into()),
),
FlatExpression::Mult(
box FlatExpression::Add(box x.clone(), box x.clone()),
box y.clone(),
box FlatExpression::Add(box x.clone(), box x),
box y,
),
RuntimeError::Xor,
),
@ -1391,7 +1390,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// q in range
let _ = self.get_bits(
FlatUExpression::with_field(FlatExpression::from(q)),
&FlatUExpression::with_field(FlatExpression::from(q)),
target_bitwidth.to_usize(),
target_bitwidth,
statements_flattened,
@ -1399,7 +1398,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// r in range
let _ = self.get_bits(
FlatUExpression::with_field(FlatExpression::from(r)),
&FlatUExpression::with_field(FlatExpression::from(r)),
target_bitwidth.to_usize(),
target_bitwidth,
statements_flattened,
@ -1407,7 +1406,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// r < d <=> r - d + 2**w < 2**w
let _ = self.get_bits(
FlatUExpression::with_field(FlatExpression::Add(
&FlatUExpression::with_field(FlatExpression::Add(
box FlatExpression::Sub(box r.into(), box d.clone()),
box FlatExpression::Number(T::from(2_u128.pow(target_bitwidth.to_usize() as u32))),
)),
@ -1514,7 +1513,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
UExpressionInner::Sub(box left, box right) => {
// see uint optimizer for the reasoning here
let offset = FlatExpression::Number(T::from(2).pow(std::cmp::max(
right.metadata.clone().unwrap().bitwidth() as usize,
right.metadata.as_ref().unwrap().bitwidth() as usize,
target_bitwidth as usize,
)));
@ -1818,10 +1817,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
}
}
(x, y) => self
.define(
FlatExpression::Mult(box x.clone(), box y.clone()),
statements_flattened,
)
.define(FlatExpression::Mult(box x, box y), statements_flattened)
.into(),
})
.collect();
@ -1883,12 +1879,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
let res = match should_reduce {
true => {
let bits = self.get_bits(
res.clone(),
actual_bitwidth,
target_bitwidth,
statements_flattened,
);
let bits =
self.get_bits(&res, actual_bitwidth, target_bitwidth, statements_flattened);
let field = if actual_bitwidth > target_bitwidth.to_usize() {
bits.iter().enumerate().fold(
@ -1919,7 +1911,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
fn get_bits(
&mut self,
e: FlatUExpression<T>,
e: &FlatUExpression<T>,
from: usize,
to: UBitwidth,
statements_flattened: &mut FlatStatements<T>,
@ -1993,7 +1985,8 @@ impl<'ast, T: Field> Flattener<'ast, T> {
assert_eq!(bits.len(), to);
self.bits_cache.insert(e.field.unwrap(), bits.clone());
self.bits_cache
.insert(e.field.clone().unwrap(), bits.clone());
self.bits_cache.insert(sum, bits.clone());
bits
@ -2597,7 +2590,7 @@ impl<'ast, T: Field> Flattener<'ast, T> {
// to constrain unsigned integer inputs to be in range, we get their bit decomposition.
// it will be cached
self.get_bits(
FlatUExpression::with_field(FlatExpression::Identifier(variable)),
&FlatUExpression::with_field(FlatExpression::Identifier(variable)),
bitwidth.to_usize(),
bitwidth,
statements_flattened,

View file

@ -5,7 +5,7 @@
//! @date 2018
use crate::absy::*;
use crate::compile::compile_module;
use crate::compile::parse_module;
use crate::compile::{CompileErrorInner, CompileErrors};
use crate::embed::FlatEmbed;
use crate::parser::Position;
@ -222,7 +222,7 @@ impl Importer {
Some(_) => {}
None => {
let source = arena.alloc(source);
let compiled = compile_module::<T, E>(
let compiled = parse_module::<T, E>(
source,
new_location.clone(),
resolver,

View file

@ -21,12 +21,30 @@ use zokrates_field::Field;
impl<T: Field> Prog<T> {
pub fn optimize(self) -> Self {
// remove redefinitions
log::debug!("Constraints: {}", self.constraint_count());
log::debug!("Optimizer: Remove redefinitions");
let r = RedefinitionOptimizer::optimize(self);
log::debug!("Done");
// remove constraints that are always satisfied
log::debug!("Constraints: {}", r.constraint_count());
log::debug!("Optimizer: Remove tautologies");
let r = TautologyOptimizer::optimize(r);
// // deduplicate directives which take the same input
log::debug!("Done");
// deduplicate directives which take the same input
log::debug!("Constraints: {}", r.constraint_count());
log::debug!("Optimizer: Remove duplicate directive");
let r = DirectiveOptimizer::optimize(r);
log::debug!("Done");
// remove duplicate constraints
DuplicateOptimizer::optimize(r)
log::debug!("Constraints: {}", r.constraint_count());
log::debug!("Optimizer: Remove duplicate constraints");
let r = DuplicateOptimizer::optimize(r);
log::debug!("Done");
log::debug!("Constraints: {}", r.constraint_count());
r
}
}

View file

@ -73,29 +73,54 @@ impl fmt::Display for Error {
impl<'ast, T: Field> TypedProgram<'ast, T> {
pub fn analyse(self, config: &CompileConfig) -> Result<(ZirProgram<'ast, T>, Abi), Error> {
// inline user-defined constants
log::debug!("Static analyser: Inline constants");
let r = ConstantInliner::inline(self);
log::trace!("\n{}", r);
// isolate branches
let r = if config.isolate_branches {
Isolator::isolate(r)
log::debug!("Static analyser: Isolate branches");
let r = Isolator::isolate(r);
log::trace!("\n{}", r);
r
} else {
log::debug!("Static analyser: Branch isolation skipped");
r
};
// reduce the program to a single function
log::debug!("Static analyser: Reduce program");
let r = reduce_program(r).map_err(Error::from)?;
log::trace!("\n{}", r);
// generate abi
log::debug!("Static analyser: Generate abi");
let abi = r.abi();
// propagate
log::debug!("Static analyser: Propagate");
let r = Propagator::propagate(r).map_err(Error::from)?;
log::trace!("\n{}", r);
// remove assignment to variable index
log::debug!("Static analyser: Remove variable index");
let r = VariableWriteRemover::apply(r);
log::trace!("\n{}", r);
// detect non constant shifts
log::debug!("Static analyser: Detect non constant shifts");
let r = ShiftChecker::check(r).map_err(Error::from)?;
log::trace!("\n{}", r);
// convert to zir, removing complex types
log::debug!("Static analyser: Convert to zir");
let zir = Flattener::flatten(r);
log::trace!("\n{}", zir);
// optimize uint expressions
log::debug!("Static analyser: Optimize uints");
let zir = UintOptimizer::optimize(zir);
log::trace!("\n{}", zir);
Ok((zir, abi))
}
@ -103,12 +128,14 @@ impl<'ast, T: Field> TypedProgram<'ast, T> {
impl<T: Field> Analyse for FlatProg<T> {
fn analyse(self) -> Self {
log::debug!("Static analyser: Propagate flat");
self.propagate()
}
}
impl<T: Field> Analyse for Prog<T> {
fn analyse(self) -> Self {
log::debug!("Static analyser: Detect unconstrained zir");
UnconstrainedVariableDetector::detect(self)
}
}