diff --git a/Cargo.toml b/Cargo.toml index 3ed85d7d3a..c21ee10eee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,11 +10,11 @@ members = [ "pil_analyzer", "compiler", "pilgen", - "halo2" + "halo2", ] [patch."https://github.com/privacy-scaling-explorations/halo2.git"] -halo2_proofs = { git ="https://github.com/ed255/halo2", rev = "63e969673de83a410f21553fabec8f4b35bda1a5" } +halo2_proofs = { git = "https://github.com/appliedzkp/halo2.git", rev = "d3746109d7d38be53afc8ddae8fdfaf1f02ad1d7" } [patch.crates-io] -halo2_proofs = { git ="https://github.com/ed255/halo2", rev = "63e969673de83a410f21553fabec8f4b35bda1a5" } +halo2_proofs = { git = "https://github.com/appliedzkp/halo2.git", rev = "d3746109d7d38be53afc8ddae8fdfaf1f02ad1d7" } diff --git a/README.md b/README.md index e76691db1a..7fbe582562 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@ which is compiled to RISCV, then to powdr-asm and finally to PIL. *powdr*-PIL can be used to generate proofs using multiple backends, such as: +- Halo2 - eSTARKs: *powdr*-PIL is fully compatible with the eSTARKS backend from Polygon Hermez, although not yet fully integrated in an automatic way. -- Halo2: ongoing work, should be ready soon. - Nova: ongoing work, should be ready after soon. - other STARKs: maybe? diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index dedb3e5890..37f0f548cc 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -12,4 +12,6 @@ parser_util = { path = "../parser_util" } parser = { path = "../parser" } executor = { path = "../executor" } pilgen = { path = "../pilgen" } -pil_analyzer = { path = "../pil_analyzer" } \ No newline at end of file +pil_analyzer = { path = "../pil_analyzer" } +halo2 = { path = "../halo2" } +strum = { version = "0.24.1", features = ["derive"] } \ No newline at end of file diff --git a/compiler/src/backends.rs b/compiler/src/backends.rs new file mode 100644 index 0000000000..0c0a5dda9e --- /dev/null +++ b/compiler/src/backends.rs @@ -0,0 +1,7 @@ +use strum::{Display, EnumString, EnumVariantNames}; + +#[derive(Clone, EnumString, EnumVariantNames, Display)] +pub enum Backend { + #[strum(serialize = "halo2")] + Halo2, +} diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index c99d0d24cf..0d867bf2a2 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -6,7 +6,10 @@ use std::io::BufWriter; use std::path::Path; use std::time::Instant; +mod backends; mod verify; + +pub use backends::Backend; use number::write_polys_file; use pil_analyzer::json_exporter; pub use verify::{compile_asm_string_temp, verify, verify_asm_string}; @@ -26,16 +29,18 @@ pub fn compile_pil_or_asm( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { if file_name.ends_with(".asm") { - compile_asm(file_name, inputs, output_dir, force_overwrite) + compile_asm(file_name, inputs, output_dir, force_overwrite, prove_with) } else { compile_pil( Path::new(file_name), output_dir, Some(inputs_to_query_callback(inputs)), + prove_with, ); - } + }; } /// Compiles a .pil file to its json form and also tries to generate @@ -46,12 +51,14 @@ pub fn compile_pil( pil_file: &Path, output_dir: &Path, query_callback: Option Option>, + prove_with: Option, ) -> bool { compile( &pil_analyzer::analyze(pil_file), pil_file.file_name().unwrap(), output_dir, query_callback, + prove_with, ) } @@ -60,6 +67,7 @@ pub fn compile_pil_ast( file_name: &OsStr, output_dir: &Path, query_callback: Option Option>, + prove_with: Option, ) -> bool { // TODO exporting this to string as a hack because the parser // is tied into the analyzer due to imports. @@ -68,6 +76,7 @@ pub fn compile_pil_ast( file_name, output_dir, query_callback, + prove_with, ) } @@ -78,9 +87,17 @@ pub fn compile_asm( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { let contents = fs::read_to_string(file_name).unwrap(); - compile_asm_string(file_name, &contents, inputs, output_dir, force_overwrite) + compile_asm_string( + file_name, + &contents, + inputs, + output_dir, + force_overwrite, + prove_with, + ) } /// Compiles the contents of a .asm file, outputs the PIL on stdout and tries to generate @@ -91,6 +108,7 @@ pub fn compile_asm_string( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { let pil = pilgen::compile(Some(file_name), contents).unwrap_or_else(|err| { eprintln!("Error parsing .asm file:"); @@ -115,6 +133,7 @@ pub fn compile_asm_string( pil_file_name.file_name().unwrap(), output_dir, Some(inputs_to_query_callback(inputs)), + prove_with, ); } @@ -123,6 +142,7 @@ fn compile( file_name: &OsStr, output_dir: &Path, query_callback: Option Option>, + prove_with: Option, ) -> bool { let mut success = true; let start = Instant::now(); @@ -144,6 +164,15 @@ fn compile( &commits, ); log::info!("Wrote commits.bin."); + if let Some(Backend::Halo2) = prove_with { + use std::io::Write; + let proof = halo2::prove_ast(analyzed, constants, commits); + let mut proof_file = fs::File::create(output_dir.join("proof.bin")).unwrap(); + let mut proof_writer = BufWriter::new(&mut proof_file); + proof_writer.write_all(&proof).unwrap(); + proof_writer.flush().unwrap(); + log::info!("Wrote proof.bin."); + } } else { log::warn!("Not writing constants.bin because not all declared constants are defined (or there are none)."); success = false; @@ -158,6 +187,7 @@ fn compile( .write(&mut fs::File::create(output_dir.join(&json_file)).unwrap()) .unwrap(); log::info!("Wrote {}.", json_file.to_string_lossy()); + success } diff --git a/compiler/src/verify.rs b/compiler/src/verify.rs index c5ee05605c..1c2141952e 100644 --- a/compiler/src/verify.rs +++ b/compiler/src/verify.rs @@ -36,6 +36,7 @@ pub fn compile_asm_string_temp( _ => None, } }), + None, )); (pil_file_name.to_string(), temp_dir) } diff --git a/compiler/tests/asm.rs b/compiler/tests/asm.rs index 4eb9f41db4..221a90a4af 100644 --- a/compiler/tests/asm.rs +++ b/compiler/tests/asm.rs @@ -1,5 +1,5 @@ -use compiler::verify_asm_string; -use number::{FieldElement, GoldilocksField}; +use compiler::{compile_pil_or_asm, verify_asm_string, Backend}; +use number::{Bn254Field, FieldElement, GoldilocksField}; use std::fs; fn verify_asm(file_name: &str, inputs: Vec) { @@ -7,46 +7,70 @@ fn verify_asm(file_name: &str, inputs: Vec) { verify_asm_string(file_name, &contents, inputs) } +fn halo2_proof(file_name: &str, inputs: Vec) { + compile_pil_or_asm( + format!("../test_data/asm/{file_name}").as_str(), + inputs, + &mktemp::Temp::new_dir().unwrap(), + true, + Some(Backend::Halo2), + ); +} + +fn slice_to_vec(arr: &[i32]) -> Vec { + arr.iter().cloned().map(|x| x.into()).collect() +} + #[test] fn simple_sum_asm() { - verify_asm::( - "simple_sum.asm", - [16, 4, 1, 2, 8, 5].iter().map(|&x| x.into()).collect(), - ); + let f = "simple_sum.asm"; + let i = [16, 4, 1, 2, 8, 5]; + verify_asm::(f, slice_to_vec(&i)); + halo2_proof(f, slice_to_vec(&i)); } #[test] fn palindrome() { - verify_asm::( - "palindrome.asm", - [7, 1, 7, 3, 9, 3, 7, 1].iter().map(|&x| x.into()).collect(), - ); + let f = "palindrome.asm"; + let i = [7, 1, 7, 3, 9, 3, 7, 1]; + verify_asm::(f, slice_to_vec(&i)); + halo2_proof(f, slice_to_vec(&i)); } #[test] fn test_mem_read_write() { - verify_asm::("mem_read_write.asm", Default::default()); + let f = "mem_read_write.asm"; + verify_asm::(f, Default::default()); + halo2_proof(f, Default::default()); } #[test] fn test_multi_assign() { - verify_asm::("multi_assign.asm", [7].iter().map(|&x| x.into()).collect()); + let f = "multi_assign.asm"; + let i = [7]; + verify_asm::(f, slice_to_vec(&i)); + halo2_proof(f, slice_to_vec(&i)); } #[test] fn test_bit_access() { - verify_asm::("bit_access.asm", [20].iter().map(|&x| x.into()).collect()); + let f = "bit_access.asm"; + let i = [20]; + verify_asm::(f, slice_to_vec(&i)); + halo2_proof(f, slice_to_vec(&i)); } #[test] fn functional_instructions() { - verify_asm::( - "functional_instructions.asm", - [20].iter().map(|&x| x.into()).collect(), - ); + let f = "functional_instructions.asm"; + let i = [20]; + verify_asm::(f, slice_to_vec(&i)); + halo2_proof(f, slice_to_vec(&i)); } #[test] fn full_pil_constant() { - verify_asm::("full_pil_constant.asm", Default::default()); + let f = "full_pil_constant.asm"; + verify_asm::(f, Default::default()); + halo2_proof(f, Default::default()); } diff --git a/compiler/tests/pil.rs b/compiler/tests/pil.rs index a8d3567424..3a1039e4d7 100644 --- a/compiler/tests/pil.rs +++ b/compiler/tests/pil.rs @@ -12,6 +12,7 @@ pub fn verify_pil(file_name: &str, query_callback: Option Option( // generate fixed and witness (witness). - let query = |column, rotation| Expr::Var(PlonkVar::ColumnQuery { column, rotation }); + let query = |column, rotation| Expr::Var(PlonkVar::Query(ColumnQuery { column, rotation })); let mut cd = CircuitData::from(fixed, witness); @@ -84,66 +84,77 @@ pub(crate) fn analyzed_to_circuit( // build Plaf polys. ------------------------------------------------------------------------- for id in &analyzed.identities { - if id.kind == IdentityKind::Polynomial { - // polynomial identities. - - assert_eq!(id.right.expressions.len(), 0); - assert_eq!(id.right.selector, None); - assert_eq!(id.left.expressions.len(), 0); - - let exp = id.left.selector.as_ref().unwrap(); - let contains_next_ref = exp.contains_next_ref(); - - let exp = expression_2_expr(&cd, exp); - - // depending whether this polynomial contains a rotation, - // enable for all rows or all except the last one. - - let exp = Expr::Mul(vec![ - exp, - if contains_next_ref { - q_enable_next.clone() - } else { - q_enable_cur.clone() - }, - ]); - polys.push(Poly { - name: "".to_string(), - exp, - }); - } else if id.kind == IdentityKind::Plookup { - // lookups. - - assert_eq!(id.right.selector, None); - - let left_selector = id - .left - .selector - .clone() - .map_or(Expr::Const(BigUint::one()), |expr| { - expression_2_expr(&cd, &expr) + match id.kind { + IdentityKind::Polynomial => { + // polynomial identities. + + assert_eq!(id.right.expressions.len(), 0); + assert_eq!(id.right.selector, None); + assert_eq!(id.left.expressions.len(), 0); + + let exp = id.left.selector.as_ref().unwrap(); + let contains_next_ref = exp.contains_next_ref(); + + let exp = expression_2_expr(&cd, exp); + + // depending whether this polynomial contains a rotation, + // enable for all rows or all except the last one. + + let exp = Expr::Mul(vec![ + exp, + if contains_next_ref { + q_enable_next.clone() + } else { + q_enable_cur.clone() + }, + ]); + polys.push(Poly { + name: "".to_string(), + exp, }); - - let left = id - .left - .expressions - .iter() - .map(|expr| left_selector.clone() * expression_2_expr(&cd, expr)) - .collect(); - - let right = id - .right - .expressions - .iter() - .map(|expr| expression_2_expr(&cd, expr)) - .collect(); - - lookups.push(Lookup { - name: "".to_string(), - exps: (left, right), - }); - } else { - unimplemented!() + } + IdentityKind::Plookup => { + // lookups. + + let wrap_lookup = |side: &SelectedExpressions| { + let selector = side + .selector + .clone() + .map_or(Expr::Const(BigUint::one()), |expr| { + expression_2_expr(&cd, &expr) + }); + + let contains_next_ref = + side.expressions.iter().any(|exp| exp.contains_next_ref()); + + let selector = Expr::Mul(vec![ + selector, + if contains_next_ref { + q_enable_next.clone() + } else { + q_enable_cur.clone() + }, + ]); + + side.expressions + .iter() + .map(|expr| selector.clone() * expression_2_expr(&cd, expr)) + .collect() + }; + + let left = wrap_lookup(&id.left); + let right = wrap_lookup(&id.right); + + lookups.push(Lookup { + name: "".to_string(), + exps: (left, right), + }); + } + IdentityKind::Permutation => { + // TODO anything that uses permutations is + // fully unconstrained right now!!! + } + _ => unimplemented!(), } } @@ -193,6 +204,7 @@ pub(crate) fn analyzed_to_circuit( info, columns, polys, + metadata: Default::default(), lookups, copys, fixed, @@ -209,10 +221,10 @@ fn expression_2_expr(cd: &CircuitData, expr: &Expression) Expression::PolynomialReference(polyref) => { assert_eq!(polyref.index, None); - let plonkvar = PlonkVar::ColumnQuery { + let plonkvar = PlonkVar::Query(ColumnQuery { column: cd.col(&polyref.name), rotation: polyref.next as i32, - }; + }); Expr::Var(plonkvar) } diff --git a/halo2/src/lib.rs b/halo2/src/lib.rs index e21fadcd76..3e4fa0cd78 100644 --- a/halo2/src/lib.rs +++ b/halo2/src/lib.rs @@ -1,5 +1,7 @@ pub(crate) mod circuit_builder; pub(crate) mod circuit_data; pub(crate) mod mock_prover; +pub(crate) mod prover; pub use mock_prover::mock_prove; +pub use prover::prove_ast; diff --git a/halo2/src/mock_prover.rs b/halo2/src/mock_prover.rs index 03fb7b48c8..eee4eb98c5 100644 --- a/halo2/src/mock_prover.rs +++ b/halo2/src/mock_prover.rs @@ -6,16 +6,14 @@ use polyexen::plaf::PlafDisplayBaseTOML; use super::circuit_builder::analyzed_to_circuit; use halo2_proofs::{dev::MockProver, halo2curves::bn256::Fr}; -use number::{BigInt, Bn254Field, FieldElement}; +use number::{BigInt, FieldElement}; -pub fn mock_prove(file: &Path, dir: &Path) { - let analyzed: Analyzed = pil_analyzer::analyze(file); +pub fn mock_prove(file: &Path, dir: &Path) { + let analyzed: Analyzed = pil_analyzer::analyze(file); - assert_eq!( - polyexen::expr::get_field_p::(), - Bn254Field::modulus().to_arbitrary_integer(), - "powdr modulus doesn't match halo2 modulus" - ); + if polyexen::expr::get_field_p::() != T::modulus().to_arbitrary_integer() { + panic!("powdr modulus doesn't match halo2 modulus. Make sure you are using Bn254"); + } let fixed_columns: Vec<&str> = analyzed .constant_polys_in_source_order() @@ -69,6 +67,8 @@ fn mock_prove_ast( mod test { use std::fs; + use number::Bn254Field; + use super::*; fn mock_prove_asm(file_name: &str, inputs: &[Bn254Field]) { diff --git a/halo2/src/prover.rs b/halo2/src/prover.rs new file mode 100644 index 0000000000..86a469ffb8 --- /dev/null +++ b/halo2/src/prover.rs @@ -0,0 +1,75 @@ +use halo2_proofs::{ + halo2curves::bn256::{Bn256, Fr, G1Affine}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof}, + poly::{ + commitment::ParamsProver, + kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG}, + multiopen::{ProverGWC, VerifierGWC}, + strategy::SingleStrategy, + }, + }, + transcript::{Keccak256Read, Keccak256Write, TranscriptReadBuffer, TranscriptWriterBuffer}, +}; +use number::{BigInt, FieldElement}; +use pil_analyzer::Analyzed; +use polyexen::plaf::PlafDisplayBaseTOML; +use rand::{rngs::StdRng, SeedableRng}; + +use crate::circuit_builder::analyzed_to_circuit; + +/// Create a halo2 proof for a given PIL, fixed column values and witness column values +/// We use KZG ([GWC variant](https://eprint.iacr.org/2019/953)) and Keccak256 +pub fn prove_ast( + pil: &Analyzed, + fixed: Vec<(&str, Vec)>, + witness: Vec<(&str, Vec)>, +) -> Vec { + if polyexen::expr::get_field_p::() != T::modulus().to_arbitrary_integer() { + panic!("powdr modulus doesn't match halo2 modulus. Make sure you are using Bn254"); + } + + let circuit = analyzed_to_circuit(pil, fixed, witness); + + let circuit_row_count_log = usize::BITS - circuit.plaf.info.num_rows.leading_zeros(); + + let expanded_row_count_log = circuit_row_count_log + 1; + + log::debug!("{}", PlafDisplayBaseTOML(&circuit.plaf)); + + let inputs = vec![]; + + let params = ParamsKZG::::new(expanded_row_count_log); + let vk = keygen_vk(¶ms, &circuit).unwrap(); + let pk = keygen_pk(¶ms, vk.clone(), &circuit).unwrap(); + let mut transcript: Keccak256Write< + Vec, + G1Affine, + halo2_proofs::transcript::Challenge255, + > = Keccak256Write::init(vec![]); + + create_proof::, ProverGWC<_>, _, _, _, _>( + ¶ms, + &pk, + &[circuit], + &[&inputs], + StdRng::from_entropy(), + &mut transcript, + ) + .unwrap(); + + let proof = transcript.finalize(); + + let mut transcript = Keccak256Read::init(&proof[..]); + + assert!(verify_proof::<_, VerifierGWC<_>, _, _, _>( + ¶ms, + &vk, + SingleStrategy::new(¶ms), + &[&inputs], + &mut transcript + ) + .is_ok()); + + proof +} diff --git a/powdr_cli/src/main.rs b/powdr_cli/src/main.rs index 829e51738a..9026763372 100644 --- a/powdr_cli/src/main.rs +++ b/powdr_cli/src/main.rs @@ -3,9 +3,11 @@ mod util; use clap::{Parser, Subcommand}; +use compiler::{compile_pil_or_asm, Backend}; use env_logger::{Builder, Target}; use log::LevelFilter; use number::{Bn254Field, FieldElement, GoldilocksField}; +use riscv::{compile_riscv_asm, compile_rust}; use std::{fs, io::Write, path::Path}; use strum::{Display, EnumString, EnumVariantNames}; @@ -54,6 +56,11 @@ enum Commands { #[arg(short, long)] #[arg(default_value_t = false)] force: bool, + + /// Generate a proof with a given backend + #[arg(short, long)] + #[arg(value_parser = clap_enum_variants!(Backend))] + prove_with: Option, }, /// Compiles (no-std) rust code to riscv assembly, then to powdr assembly /// and finally to PIL and generates fixed and witness columns. @@ -62,6 +69,12 @@ enum Commands { /// Input file (rust source file) or directory (containing a crate). file: String, + /// The field to use + #[arg(long)] + #[arg(default_value_t = FieldArgument::Gl)] + #[arg(value_parser = clap_enum_variants!(FieldArgument))] + field: FieldArgument, + /// Comma-separated list of free inputs (numbers). #[arg(short, long)] #[arg(default_value_t = String::new())] @@ -76,6 +89,11 @@ enum Commands { #[arg(short, long)] #[arg(default_value_t = false)] force: bool, + + /// Generate a proof with a given backend + #[arg(short, long)] + #[arg(value_parser = clap_enum_variants!(Backend))] + prove_with: Option, }, /// Compiles riscv assembly to powdr assembly and then to PIL @@ -84,6 +102,12 @@ enum Commands { /// Input file file: String, + /// The field to use + #[arg(long)] + #[arg(default_value_t = FieldArgument::Gl)] + #[arg(value_parser = clap_enum_variants!(FieldArgument))] + field: FieldArgument, + /// Comma-separated list of free inputs (numbers). #[arg(short, long)] #[arg(default_value_t = String::new())] @@ -98,9 +122,14 @@ enum Commands { #[arg(short, long)] #[arg(default_value_t = false)] force: bool, + + /// Generate a proof with a given backend. + #[arg(short, long)] + #[arg(value_parser = clap_enum_variants!(Backend))] + prove_with: Option, }, - /// Apply the Halo2 workflow on an input file and prover values. + /// Apply the Halo2 workflow on an input file and prover values over the Bn254 field /// That means parsing, analysis, witness generation, /// and Halo2 mock proving. Halo2MockProver { @@ -142,31 +171,37 @@ fn main() { match command { Commands::Rust { file, + field, inputs, output_directory, force, - } => { - riscv::compile_rust::( - &file, - split_inputs(&inputs), - Path::new(&output_directory), - force, - ); - } + prove_with, + } => call_with_field!( + compile_rust, + field, + &file, + split_inputs(&inputs), + Path::new(&output_directory), + force, + prove_with + ), Commands::RiscvAsm { file, + field, inputs, output_directory, force, - } => { - riscv::compile_riscv_asm::( - &file, - &file, - split_inputs(&inputs), - Path::new(&output_directory), - force, - ); - } + prove_with, + } => call_with_field!( + compile_riscv_asm, + field, + &file, + &file, + split_inputs(&inputs), + Path::new(&output_directory), + force, + prove_with + ), Commands::Reformat { file } => { let contents = fs::read_to_string(&file).unwrap(); match parser::parse::(Some(&file), &contents) { @@ -180,22 +215,18 @@ fn main() { output_directory, inputs, force, - } => match field { - FieldArgument::Gl => compiler::compile_pil_or_asm::( - &file, - split_inputs(&inputs), - Path::new(&output_directory), - force, - ), - FieldArgument::Bn254 => compiler::compile_pil_or_asm::( - &file, - split_inputs(&inputs), - Path::new(&output_directory), - force, - ), - }, + prove_with, + } => call_with_field!( + compile_pil_or_asm, + field, + &file, + split_inputs(&inputs), + Path::new(&output_directory), + force, + prove_with + ), Commands::Halo2MockProver { file, dir } => { - halo2::mock_prove(Path::new(&file), Path::new(&dir)); + halo2::mock_prove::(Path::new(&file), Path::new(&dir)); } } } diff --git a/powdr_cli/src/util.rs b/powdr_cli/src/util.rs index 6ff6acc194..fef0e0e23a 100644 --- a/powdr_cli/src/util.rs +++ b/powdr_cli/src/util.rs @@ -7,3 +7,14 @@ macro_rules! clap_enum_variants { clap::builder::PossibleValuesParser::new(<$e>::VARIANTS).map(|s| s.parse::<$e>().unwrap()) }}; } + +/// Call a function using a given field generic +#[macro_export] +macro_rules! call_with_field { + ($function:ident, $case:expr, $($args:expr),*) => { + match $case { + FieldArgument::Gl => $function::($($args),*), + FieldArgument::Bn254 => $function::($($args),*), + } + }; +} diff --git a/riscv/src/lib.rs b/riscv/src/lib.rs index 7b84f5f0f8..0e6642396a 100644 --- a/riscv/src/lib.rs +++ b/riscv/src/lib.rs @@ -2,7 +2,7 @@ use std::{collections::BTreeMap, path::Path, process::Command}; -use ::compiler::compile_asm_string; +use ::compiler::{compile_asm_string, Backend}; use mktemp::Temp; use std::fs; use walkdir::WalkDir; @@ -22,6 +22,7 @@ pub fn compile_rust( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { let riscv_asm = if file_name.ends_with("Cargo.toml") { compile_rust_crate_to_riscv_asm(file_name) @@ -50,7 +51,14 @@ pub fn compile_rust( log::info!("Wrote {}", riscv_asm_file_name.to_str().unwrap()); } - compile_riscv_asm_bundle(file_name, riscv_asm, inputs, output_dir, force_overwrite) + compile_riscv_asm_bundle( + file_name, + riscv_asm, + inputs, + output_dir, + force_overwrite, + prove_with, + ) } pub fn compile_riscv_asm_bundle( @@ -59,6 +67,7 @@ pub fn compile_riscv_asm_bundle( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { let powdr_asm_file_name = output_dir.join(format!( "{}.asm", @@ -87,6 +96,7 @@ pub fn compile_riscv_asm_bundle( inputs, output_dir, force_overwrite, + prove_with, ) } @@ -98,6 +108,7 @@ pub fn compile_riscv_asm( inputs: Vec, output_dir: &Path, force_overwrite: bool, + prove_with: Option, ) { let contents = fs::read_to_string(file_name).unwrap(); compile_riscv_asm_bundle( @@ -108,6 +119,7 @@ pub fn compile_riscv_asm( inputs, output_dir, force_overwrite, + prove_with, ) } diff --git a/test_data/asm/full_pil_constant.asm b/test_data/asm/full_pil_constant.asm index 348ef93969..1a8ccdb4c0 100644 --- a/test_data/asm/full_pil_constant.asm +++ b/test_data/asm/full_pil_constant.asm @@ -1,5 +1,7 @@ -degree 1; +degree 2; pil{ - pol constant C = [1]; + pol constant C = [1]*; + col commit w; + w = 0; } \ No newline at end of file diff --git a/test_data/asm/mem_read_write.asm b/test_data/asm/mem_read_write.asm index 24beedd505..3335a13fce 100644 --- a/test_data/asm/mem_read_write.asm +++ b/test_data/asm/mem_read_write.asm @@ -29,7 +29,7 @@ pil{ // positive numbers (assumed to be much smaller than the field order) col fixed POSITIVE(i) { i + 1 }; col fixed FIRST = [1] + [0]*; - col fixed LAST(i) { FIRST(i + 1) }; + col fixed LAST = [0]* + [1]; col fixed STEP(i) { i }; m_change * (1 - m_change) = 0; diff --git a/test_data/asm/palindrome.asm b/test_data/asm/palindrome.asm index 309a69e788..2599c6e9a1 100644 --- a/test_data/asm/palindrome.asm +++ b/test_data/asm/palindrome.asm @@ -25,7 +25,7 @@ pil{ // positive numbers (assumed to be less than half the field order) col fixed POSITIVE(i) { i + 1 }; col fixed FIRST = [1] + [0]*; - col fixed NOTLAST(i) { 1 - FIRST(i + 1) }; + col fixed NOTLAST = [1]* + [0]; // This enforces that addresses are stored in an ascending order // (and in particular, are unique).