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

add check command

This commit is contained in:
schaeff 2020-05-14 15:33:51 +02:00
parent 3efcab6afc
commit a28f2080d5
2 changed files with 101 additions and 11 deletions

View file

@ -16,7 +16,7 @@ use std::io::{stdin, BufReader, BufWriter, Read, Write};
use std::path::{Path, PathBuf};
use std::string::String;
use zokrates_abi::Encode;
use zokrates_core::compile::{compile, CompilationArtifacts, CompileError};
use zokrates_core::compile::{check, compile, CompilationArtifacts, CompileError};
use zokrates_core::ir::{self, ProgEnum};
use zokrates_core::proof_system::*;
use zokrates_core::typed_absy::abi::Abi;
@ -342,6 +342,46 @@ fn cli_compile<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
Ok(())
}
fn cli_check<T: Field>(sub_matches: &ArgMatches) -> Result<(), String> {
println!("Checking {}\n", sub_matches.value_of("input").unwrap());
let path = PathBuf::from(sub_matches.value_of("input").unwrap());
let file = File::open(path.clone())
.map_err(|why| format!("Couldn't open input file {}: {}", path.display(), why))?;
let mut reader = BufReader::new(file);
let mut source = String::new();
reader.read_to_string(&mut source).unwrap();
let fmt_error = |e: &CompileError| {
format!(
"{}:{}",
e.file()
.canonicalize()
.unwrap()
.strip_prefix(std::env::current_dir().unwrap())
.unwrap()
.display(),
e.value()
)
};
let resolver = FileSystemResolver::new();
let _ = check::<T, _>(source, path, Some(&resolver)).map_err(|e| {
format!(
"Check failed:\n\n{}",
e.0.iter()
.map(|e| fmt_error(e))
.collect::<Vec<_>>()
.join("\n\n")
)
})?;
println!("Program checked, no errors found.");
Ok(())
}
fn cli_verify<T: Field, P: ProofSystem<T>>(sub_matches: &ArgMatches) -> Result<(), String> {
let vk_path = Path::new(sub_matches.value_of("verification-key-path").unwrap());
let vk = std::fs::read_to_string(vk_path)
@ -420,6 +460,25 @@ fn cli() -> Result<(), String> {
.required(false)
)
)
.subcommand(SubCommand::with_name("check")
.about("Checks a program for errors")
.arg(Arg::with_name("input")
.short("i")
.long("input")
.help("Path of the source code")
.value_name("FILE")
.takes_value(true)
.required(true)
).arg(Arg::with_name("curve")
.short("c")
.long("curve")
.help("Curve to be used in the compilation")
.takes_value(true)
.required(false)
.possible_values(CURVES)
.default_value(&default_curve)
)
)
.subcommand(SubCommand::with_name("setup")
.about("Performs a trusted setup for a given constraint system")
.arg(Arg::with_name("input")
@ -667,6 +726,15 @@ fn cli() -> Result<(), String> {
_ => unreachable!(),
}
}
("check", Some(sub_matches)) => {
let curve = sub_matches.value_of("curve").unwrap();
match curve {
constants::BN128 => cli_check::<Bn128Field>(sub_matches)?,
constants::BLS12_381 => cli_check::<Bls12Field>(sub_matches)?,
_ => unreachable!(),
}
}
("compute-witness", Some(sub_matches)) => {
println!("Computing witness...");

View file

@ -17,6 +17,7 @@ use std::fmt;
use std::io;
use std::path::PathBuf;
use typed_absy::abi::Abi;
use typed_absy::TypedProgram;
use typed_arena::Arena;
use zokrates_common::Resolver;
use zokrates_field::Field;
@ -149,19 +150,10 @@ pub fn compile<T: Field, E: Into<imports::Error>>(
) -> Result<CompilationArtifacts<T>, CompileErrors> {
let arena = Arena::new();
let source = arena.alloc(source);
let compiled = compile_program(source, location.clone(), resolver, &arena)?;
// check semantics
let typed_ast = Checker::check(compiled).map_err(|errors| {
CompileErrors(errors.into_iter().map(|e| CompileError::from(e)).collect())
})?;
let typed_ast = check_with_arena(source, location, resolver, &arena)?;
let abi = typed_ast.abi();
// analyse (unroll and constant propagation)
let typed_ast = typed_ast.analyse();
// flatten input program
let program_flattened = Flattener::flatten(typed_ast);
@ -183,6 +175,36 @@ pub fn compile<T: Field, E: Into<imports::Error>>(
})
}
pub fn check<'ast, T: Field, E: Into<imports::Error>>(
source: String,
location: FilePath,
resolver: Option<&dyn Resolver<E>>,
) -> Result<(), CompileErrors> {
let arena = Arena::new();
check_with_arena::<T, _>(source, location, resolver, &arena).map(|_| ())
}
fn check_with_arena<'ast, T: Field, E: Into<imports::Error>>(
source: String,
location: FilePath,
resolver: Option<&dyn Resolver<E>>,
arena: &'ast Arena<String>,
) -> Result<TypedProgram<'ast, T>, CompileErrors> {
let source = arena.alloc(source);
let compiled = compile_program(source, location.clone(), resolver, &arena)?;
// check semantics
let typed_ast = Checker::check(compiled).map_err(|errors| {
CompileErrors(errors.into_iter().map(|e| CompileError::from(e)).collect())
})?;
// analyse (unroll and constant propagation)
let typed_ast = typed_ast.analyse();
Ok(typed_ast)
}
pub fn compile_program<'ast, T: Field, E: Into<imports::Error>>(
source: &'ast str,
location: FilePath,