From b159d9e4451b86807bd3d2d64cddd81516ef4959 Mon Sep 17 00:00:00 2001 From: Steve Wang Date: Wed, 26 Mar 2025 17:19:40 +0800 Subject: [PATCH] Default pipeline with backend arguments (#2557) Depends on #2535 and standardizes the backend argument in `Pipeline`: 1. `backend` now defaults to `BackendType::Mock` when constructing the pipeline. 2. For tests that only computes up to witgen without actually running the backend, `with_backend_factory` API is used instead of `with_backend`. - If the test doesn't care which backend the witgen is computed for, NO `with_backend_factory` is called, because the default pipeline already defaults to `BackendType::Mock`. - Note that `with_backend_factory(backend)` is equivalent to `with_backend(backend, None)`. 3. For tests that generate proof, `with_backend` API is used. --- backend/src/lib.rs | 3 ++- cli-rs/src/main.rs | 2 +- pipeline/benches/jit_witgen_benchmark.rs | 7 ++----- pipeline/src/pipeline.rs | 24 +++++++++++------------- pipeline/tests/asm.rs | 5 ++--- pipeline/tests/executor.rs | 1 - pipeline/tests/mock_backend.rs | 6 ++---- pipeline/tests/pil.rs | 7 ++----- riscv/benches/executor_benchmark.rs | 5 +---- riscv/src/continuations.rs | 4 ---- riscv/tests/common/mod.rs | 4 +--- riscv/tests/riscv.rs | 2 -- 12 files changed, 24 insertions(+), 46 deletions(-) diff --git a/backend/src/lib.rs b/backend/src/lib.rs index 78570da86..759a44240 100644 --- a/backend/src/lib.rs +++ b/backend/src/lib.rs @@ -17,9 +17,10 @@ use powdr_number::{DegreeType, FieldElement}; use std::{collections::BTreeMap, io, path::PathBuf, sync::Arc}; use strum::{Display, EnumString, EnumVariantNames}; -#[derive(Clone, EnumString, EnumVariantNames, Display, Copy)] +#[derive(Clone, Default, EnumString, EnumVariantNames, Display, Copy)] pub enum BackendType { #[strum(serialize = "mock")] + #[default] Mock, #[cfg(feature = "halo2")] #[strum(serialize = "halo2")] diff --git a/cli-rs/src/main.rs b/cli-rs/src/main.rs index 1f7b4de97..fabfc92f0 100644 --- a/cli-rs/src/main.rs +++ b/cli-rs/src/main.rs @@ -426,7 +426,7 @@ fn execute( ) -> Result<(), Vec> { let mut pipeline = Pipeline::::default() .from_asm_file(file_name.to_path_buf()) - .with_backend(backend, None) + .with_backend_factory(backend) .with_prover_inputs(inputs) .with_output(output_dir.into(), true); diff --git a/pipeline/benches/jit_witgen_benchmark.rs b/pipeline/benches/jit_witgen_benchmark.rs index d2e578def..eebb1cfdb 100644 --- a/pipeline/benches/jit_witgen_benchmark.rs +++ b/pipeline/benches/jit_witgen_benchmark.rs @@ -1,5 +1,4 @@ use ::powdr_pipeline::Pipeline; -use powdr_backend::BackendType; use powdr_number::GoldilocksField; use criterion::{criterion_group, criterion_main, Criterion}; @@ -11,10 +10,8 @@ fn jit_witgen_benchmark(c: &mut Criterion) { group.sample_size(10); // Poseidon benchmark - let mut pipeline = Pipeline::::default() - .from_file("../test_data/std/poseidon_benchmark.asm".into()) - .with_backend(BackendType::Mock, None); - // this `jit_witgen_benchmark` function will also require backend type + let mut pipeline = + Pipeline::::default().from_file("../test_data/std/poseidon_benchmark.asm".into()); pipeline.compute_backend_tuned_pil().unwrap(); pipeline.compute_fixed_cols().unwrap(); diff --git a/pipeline/src/pipeline.rs b/pipeline/src/pipeline.rs index 9fa962cdd..425263e0f 100644 --- a/pipeline/src/pipeline.rs +++ b/pipeline/src/pipeline.rs @@ -105,8 +105,8 @@ struct Arguments { external_witness_values: Vec<(String, Vec)>, /// Callback for queries for witness generation. query_callback: Option>>, - /// Backend to use for proving. If None, proving will fail. - backend: Option, + /// Backend to use for proving. Defaults to Mock Backend. + backend: BackendType, /// Backend options backend_options: BackendOptions, /// Linker options @@ -365,19 +365,17 @@ impl Pipeline { self } - pub fn with_backend(mut self, backend: BackendType, options: Option) -> Self { - self.arguments.backend = Some(backend); - self.arguments.backend_options = options.unwrap_or_default(); + pub fn with_backend_factory(mut self, backend: BackendType) -> Self { + self.arguments.backend = backend; self.artifact.backend = None; self } - pub fn with_backend_if_none(&mut self, backend: BackendType, options: Option) { - if self.arguments.backend.is_none() { - self.arguments.backend = Some(backend); - self.arguments.backend_options = options.unwrap_or_default(); - self.artifact.backend = None; - } + pub fn with_backend(mut self, backend: BackendType, options: Option) -> Self { + self.arguments.backend = backend; + self.arguments.backend_options = options.unwrap_or_default(); + self.artifact.backend = None; + self } pub fn with_setup_file(mut self, setup_file: Option) -> Self { @@ -1002,7 +1000,7 @@ impl Pipeline { self.compute_optimized_pil()?; - let backend_type = self.arguments.backend.expect("no backend selected!"); + let backend_type = self.arguments.backend; // If backend option is set, compute and cache the backend-tuned pil in artifacts and return backend-tuned pil. let optimized_pil = self.artifact.optimized_pil.clone().unwrap(); @@ -1146,7 +1144,7 @@ impl Pipeline { let pil = self.compute_backend_tuned_pil()?; // will panic if backend type is not set yet let fixed_cols = self.compute_fixed_cols()?; - let backend = self.arguments.backend.expect("no backend selected!"); + let backend = self.arguments.backend; let factory = backend.factory::(); // Opens the setup file, if set. diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 3f9c82cf0..1e616ac10 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -172,7 +172,7 @@ fn block_to_block_empty_submachine() { .iter() .for_each(|backend| { let mut pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus) - .with_backend(*backend, None); + .with_backend_factory(*backend); let witness_and_publics = pipeline.compute_witness().unwrap(); let arith_size = witness_and_publics .0 @@ -313,7 +313,7 @@ fn dynamic_vadcop() { // Witness generation require backend to be known for backend in [BackendType::Mock, BackendType::Plonky3].iter() { let mut pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus) - .with_backend(*backend, None); + .with_backend_factory(*backend); let witness = &pipeline.compute_witness().unwrap().0; let witness_by_name = witness .iter() @@ -890,7 +890,6 @@ fn expand_fixed_jit() { let file_name = "asm/expand_fixed.asm"; let mut pipeline = Pipeline::::default() - .with_backend(BackendType::Mock, None) .with_tmp_output() .from_file(resolve_test_file(file_name)); let pil = pipeline.compute_backend_tuned_pil().unwrap(); diff --git a/pipeline/tests/executor.rs b/pipeline/tests/executor.rs index a63133b1f..b8807c727 100644 --- a/pipeline/tests/executor.rs +++ b/pipeline/tests/executor.rs @@ -5,7 +5,6 @@ use test_log::test; fn run_witgen_pil(pil: &str) -> Columns { Pipeline::default() - .with_backend(powdr_pipeline::BackendType::Mock, None) .from_pil_string(pil.to_string()) .compute_witness() .unwrap() diff --git a/pipeline/tests/mock_backend.rs b/pipeline/tests/mock_backend.rs index 4c5daf4a1..67593f9ca 100644 --- a/pipeline/tests/mock_backend.rs +++ b/pipeline/tests/mock_backend.rs @@ -16,8 +16,7 @@ fn fibonacci_wrong_initialization() { // Initializes y with 2 instead of 1 // -> fails `ISLAST * (y' - 1) = 0;` in the last row let f = "pil/fibonacci.pil"; - let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus) - .with_backend(powdr_backend::BackendType::Mock, None); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); let pipeline = pipeline.set_witness(vec![ // This would be the correct witness: // col("Fibonacci::x", [1, 1, 2, 3]), @@ -36,8 +35,7 @@ fn block_to_block_wrong_connection() { // So, if we multiply all columns with a constant, the constraint // should still be satisfied, but the connection argument should fail. let f = "asm/block_to_block.asm"; - let mut pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus) - .with_backend(powdr_backend::BackendType::Mock, None); + let mut pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); pipeline.compute_witness().unwrap(); diff --git a/pipeline/tests/pil.rs b/pipeline/tests/pil.rs index 8e0b6ef68..6160aaa9a 100644 --- a/pipeline/tests/pil.rs +++ b/pipeline/tests/pil.rs @@ -110,12 +110,9 @@ fn fibonacci() { fn fibonacci_with_public() { // Public references are not supported by the backends yet, but we can test witness generation. let f = "pil/fibonacci_with_public.pil"; - let pipeline: Pipeline = + let mut pipeline: Pipeline = make_prepared_pipeline(f, vec![], vec![], LinkerMode::Bus); - pipeline - .with_backend(powdr_backend::BackendType::Mock, None) - .compute_witness() - .unwrap(); + pipeline.compute_witness().unwrap(); } #[test] diff --git a/riscv/benches/executor_benchmark.rs b/riscv/benches/executor_benchmark.rs index 6936bb05d..f2e910020 100644 --- a/riscv/benches/executor_benchmark.rs +++ b/riscv/benches/executor_benchmark.rs @@ -1,5 +1,4 @@ use ::powdr_pipeline::Pipeline; -use powdr_backend::BackendType; use powdr_number::GoldilocksField; use powdr_riscv::{compile_rust_crate_to_riscv, elf, CompilerOptions}; @@ -19,9 +18,7 @@ fn executor_benchmark(c: &mut Criterion) { compile_rust_crate_to_riscv("./tests/riscv_data/keccak/Cargo.toml", &tmp_dir, None); let options = CompilerOptions::new_gl(); let contents = elf::translate(&executable, options); - let mut pipeline = Pipeline::::default() - .from_asm_string(contents, None) - .with_backend(BackendType::Mock, None); + let mut pipeline = Pipeline::::default().from_asm_string(contents, None); pipeline.compute_backend_tuned_pil().unwrap(); pipeline.compute_fixed_cols().unwrap(); diff --git a/riscv/src/continuations.rs b/riscv/src/continuations.rs index 3fb3f856e..c47924823 100644 --- a/riscv/src/continuations.rs +++ b/riscv/src/continuations.rs @@ -59,8 +59,6 @@ pub fn rust_continuations( where PipelineCallback: Fn(&mut Pipeline) -> Result<(), E>, { - pipeline.with_backend_if_none(powdr_pipeline::BackendType::Mock, None); - let bootloader_inputs = dry_run_result.bootloader_inputs; let num_chunks = bootloader_inputs.len(); @@ -339,8 +337,6 @@ pub fn rust_continuations_dry_run( pipeline: &mut Pipeline, profiler_opt: Option, ) -> DryRunResult { - pipeline.with_backend_if_none(powdr_pipeline::BackendType::Mock, None); - let field = F::known_field().unwrap(); // All inputs for all chunks. diff --git a/riscv/tests/common/mod.rs b/riscv/tests/common/mod.rs index d5abef784..3c08efa46 100644 --- a/riscv/tests/common/mod.rs +++ b/riscv/tests/common/mod.rs @@ -1,5 +1,4 @@ use mktemp::Temp; -use powdr_backend::BackendType; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField, KoalaBearField}; use powdr_pipeline::{ test_util::{test_mock_backend, test_plonky3_pipeline}, @@ -24,8 +23,7 @@ pub fn verify_riscv_asm_string(options: CompilerOptions) { let mut pipeline = Pipeline::::default() .from_asm_string(powdr_asm, Some(PathBuf::from(case))) - .with_backend(powdr_backend::BackendType::Mock, None) .with_prover_inputs(vec![answer.into()]) .with_prover_dict_inputs(d); @@ -612,7 +611,6 @@ fn output_syscall_with_options(options: CompilerOptions) { let inputs = vec![1u32, 2, 3].into_iter().map(T::from).collect(); let mut pipeline = Pipeline::::default() - .with_backend(powdr_backend::BackendType::Mock, None) .from_asm_string(powdr_asm, Some(PathBuf::from(case))) .with_prover_inputs(inputs);