Merge pull request #376 from powdr-org/move-csv-export

Move CSV export to pil command
This commit is contained in:
chriseth
2023-07-10 10:39:43 +02:00
committed by GitHub
3 changed files with 63 additions and 62 deletions

View File

@@ -5,6 +5,7 @@ use std::fs;
use std::io::BufWriter;
use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
use std::time::Instant;
use ast::analyzed::Analyzed;
@@ -35,9 +36,9 @@ pub fn compile_pil_or_asm<T: FieldElement>(
output_dir: &Path,
force_overwrite: bool,
prove_with: Option<Backend>,
) {
) -> PathBuf {
if file_name.ends_with(".asm") {
compile_asm(file_name, inputs, output_dir, force_overwrite, prove_with);
compile_asm(file_name, inputs, output_dir, force_overwrite, prove_with)
} else {
compile_pil(
Path::new(file_name),
@@ -45,6 +46,7 @@ pub fn compile_pil_or_asm<T: FieldElement>(
Some(inputs_to_query_callback(inputs)),
prove_with,
);
PathBuf::from(file_name)
}
}
@@ -103,7 +105,7 @@ pub fn compile_asm<T: FieldElement>(
output_dir: &Path,
force_overwrite: bool,
prove_with: Option<Backend>,
) {
) -> PathBuf {
let contents = fs::read_to_string(file_name).unwrap();
compile_asm_string(
file_name,
@@ -112,7 +114,7 @@ pub fn compile_asm<T: FieldElement>(
output_dir,
force_overwrite,
prove_with,
);
)
}
/// Compiles the contents of a .asm file, outputs the PIL on stdout and tries to generate
@@ -126,7 +128,7 @@ pub fn compile_asm_string<T: FieldElement>(
output_dir: &Path,
force_overwrite: bool,
prove_with: Option<Backend>,
) -> String {
) -> PathBuf {
let parsed = parser::parse_asm(Some(file_name), contents).unwrap_or_else(|err| {
eprintln!("Error parsing .asm file:");
err.output_to_stderr();
@@ -139,13 +141,13 @@ pub fn compile_asm_string<T: FieldElement>(
Path::new(file_name).file_stem().unwrap().to_str().unwrap()
);
let pil_file_path = output_dir.join(&pil_file_name);
let pil_file_path = output_dir.join(pil_file_name);
if pil_file_path.exists() && !force_overwrite {
eprint!(
"Target file {} already exists. Not overwriting.",
pil_file_path.to_str().unwrap()
);
return pil_file_name;
return pil_file_path;
}
fs::write(pil_file_path.clone(), format!("{pil}")).unwrap();
@@ -157,7 +159,7 @@ pub fn compile_asm_string<T: FieldElement>(
prove_with,
);
pil_file_name
pil_file_path
}
fn compile<T: FieldElement, QueryCallback>(

View File

@@ -5,7 +5,8 @@ use crate::compile_asm_string;
pub fn verify_asm_string<T: FieldElement>(file_name: &str, contents: &str, inputs: Vec<T>) {
let temp_dir = mktemp::Temp::new_dir().unwrap();
let pil_file_name = compile_asm_string(file_name, contents, inputs, &temp_dir, true, None);
let pil_file_path = compile_asm_string(file_name, contents, inputs, &temp_dir, true, None);
let pil_file_name = pil_file_path.file_name().unwrap().to_string_lossy();
verify(&pil_file_name, &temp_dir);
}

View File

@@ -9,7 +9,7 @@ use env_logger::{Builder, Target};
use log::LevelFilter;
use number::{Bn254Field, FieldElement, GoldilocksField};
use riscv::{compile_riscv_asm, compile_rust};
use std::{borrow::Cow, fs, io::Write, path::Path};
use std::{borrow::Cow, collections::HashSet, fs, io::Write, path::Path};
use strum::{Display, EnumString, EnumVariantNames};
use std::io::{BufWriter, Cursor};
@@ -74,6 +74,17 @@ enum Commands {
#[arg(short, long)]
#[arg(value_parser = clap_enum_variants!(Backend))]
prove_with: Option<Backend>,
/// Generate a CSV file containing the fixed and witness column values. Useful for debugging purposes.
#[arg(long)]
#[arg(default_value_t = false)]
export_csv: bool,
/// How to render field elements in the csv file
#[arg(long)]
#[arg(default_value_t = CsvRenderMode::Hex)]
#[arg(value_parser = clap_enum_variants!(CsvRenderMode))]
csv_mode: CsvRenderMode,
},
/// Compiles (no-std) rust code to riscv assembly, then to powdr assembly
/// and finally to PIL and generates fixed and witness columns.
@@ -164,11 +175,11 @@ enum Commands {
backend: Backend,
/// File containing previously generated proof for aggregation.
#[arg(short, long)]
#[arg(long)]
proof: Option<String>,
/// File containing previously generated setup parameters.
#[arg(short, long)]
#[arg(long)]
params: Option<String>,
},
@@ -210,29 +221,6 @@ enum Commands {
#[arg(value_parser = clap_enum_variants!(FieldArgument))]
field: FieldArgument,
},
/// Exports witness and fixed columns to a csv file.
ExportCsv {
/// Input PIL file
file: String,
/// Directory to find the committed and fixed values
#[arg(short, long)]
#[arg(default_value_t = String::from("."))]
dir: String,
/// The field to use
#[arg(long)]
#[arg(default_value_t = FieldArgument::Gl)]
#[arg(value_parser = clap_enum_variants!(FieldArgument))]
field: FieldArgument,
/// How to render field elements in the csv file
#[arg(long)]
#[arg(default_value_t = CsvRenderMode::Hex)]
#[arg(value_parser = clap_enum_variants!(CsvRenderMode))]
render_mode: CsvRenderMode,
},
}
fn split_inputs<T: FieldElement>(inputs: &str) -> Vec<T> {
@@ -310,13 +298,26 @@ fn main() {
inputs,
force,
prove_with,
} => call_with_field!(compile_pil_or_asm::<field>(
&file,
split_inputs(&inputs),
Path::new(&output_directory),
force,
prove_with
)),
export_csv,
csv_mode,
} => {
let pil_filename = call_with_field!(compile_pil_or_asm::<field>(
&file,
split_inputs(&inputs),
Path::new(&output_directory),
force,
prove_with
));
if export_csv {
let pil = Path::new(&pil_filename);
let dir = Path::new(&output_directory);
let csv_path = dir.join("columns.csv");
call_with_field!(export_columns_to_csv::<field>(
pil, dir, &csv_path, csv_mode
));
}
}
Commands::Prove {
file,
dir,
@@ -344,24 +345,6 @@ fn main() {
log::info!("Wrote {proof_filename}.");
}
}
Commands::ExportCsv {
file,
dir,
field,
render_mode,
} => {
let pil = Path::new(&file);
let dir = Path::new(&dir);
let csv_path = dir.join("columns.csv");
call_with_field!(export_columns_to_csv::<field>(
pil,
dir,
&csv_path,
render_mode
));
}
Commands::Setup {
size,
dir,
@@ -413,11 +396,26 @@ fn export_columns_to_csv<T: FieldElement>(
let mut csv_file = fs::File::create(csv_path).unwrap();
let mut csv_writer = BufWriter::new(&mut csv_file);
// Write the column headers
// Remove prefixes (e.g. "Assembly.") if column names are still unique after
let headers = columns
.iter()
.map(|(header, _)| header.clone())
.map(|(header, _)| header.to_owned())
.collect::<Vec<_>>();
let headers_without_prefix = headers
.iter()
.map(|header| {
let suffix_start = header.rfind('.').map(|i| i + 1).unwrap_or(0);
header[suffix_start..].to_owned()
})
.collect::<Vec<_>>();
let unique_elements = headers_without_prefix.iter().collect::<HashSet<_>>();
let headers = if unique_elements.len() == headers.len() {
headers_without_prefix
} else {
headers
};
writeln!(csv_writer, "Row,{}", headers.join(",")).unwrap();
// Write the column values