From f4029f65ff52230c0921cd150734c0691c481b06 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 10:53:36 +0100 Subject: [PATCH 01/11] Enable Bus in tests --- pipeline/src/test_util.rs | 33 +++++++++++++++++++++++++-------- pipeline/tests/asm.rs | 24 +++++++++++++++++------- pipeline/tests/pil.rs | 23 ++++++++++------------- 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/pipeline/src/test_util.rs b/pipeline/src/test_util.rs index 6770b7ceb3..03846ada5d 100644 --- a/pipeline/src/test_util.rs +++ b/pipeline/src/test_util.rs @@ -1,4 +1,5 @@ use powdr_ast::analyzed::Analyzed; +use powdr_linker::{DegreeMode, LinkerMode, LinkerParams}; use powdr_number::{ BabyBearField, BigInt, Bn254Field, FieldElement, GoldilocksField, KoalaBearField, }; @@ -37,9 +38,15 @@ pub fn make_prepared_pipeline( file_name: &str, inputs: Vec, external_witness_values: Vec<(String, Vec)>, + linker_mode: LinkerMode, ) -> Pipeline { + let linker_params = LinkerParams { + mode: linker_mode, + degree_mode: DegreeMode::Vadcop, + }; let mut pipeline = Pipeline::default() .with_tmp_output() + .with_linker_params(linker_params) .from_file(resolve_test_file(file_name)) .with_prover_inputs(inputs) .add_external_witness_values(external_witness_values); @@ -62,7 +69,8 @@ pub fn regular_test_small_field(file_name: &str, inputs: &[i32]) { /// Tests witness generation, mock prover, pilcom and plonky3 with BabyBear. pub fn regular_test_bb(file_name: &str, inputs: &[i32]) { let inputs_bb = inputs.iter().map(|x| BabyBearField::from(*x)).collect(); - let pipeline_bb = make_prepared_pipeline(file_name, inputs_bb, vec![]); + // LinkerMode::Native because the bus is not implemented for small fields + let pipeline_bb = make_prepared_pipeline(file_name, inputs_bb, vec![], LinkerMode::Native); test_mock_backend(pipeline_bb.clone()); test_plonky3_pipeline(pipeline_bb); } @@ -70,19 +78,28 @@ pub fn regular_test_bb(file_name: &str, inputs: &[i32]) { /// Tests witness generation, mock prover, pilcom and plonky3 with BabyBear and KoalaBear. pub fn regular_test_kb(file_name: &str, inputs: &[i32]) { let inputs_kb = inputs.iter().map(|x| KoalaBearField::from(*x)).collect(); - let pipeline_kb = make_prepared_pipeline(file_name, inputs_kb, vec![]); + // LinkerMode::Native because the bus is not implemented for small fields + let pipeline_kb = make_prepared_pipeline(file_name, inputs_kb, vec![], LinkerMode::Native); test_mock_backend(pipeline_kb.clone()); test_plonky3_pipeline(pipeline_kb); } /// Tests witness generation, mock prover, pilcom and plonky3 with Goldilocks. pub fn regular_test_gl(file_name: &str, inputs: &[i32]) { - let inputs_gl = inputs.iter().map(|x| GoldilocksField::from(*x)).collect(); - let pipeline_gl = make_prepared_pipeline(file_name, inputs_gl, vec![]); - - test_mock_backend(pipeline_gl.clone()); - run_pilcom_with_backend_variant(pipeline_gl.clone(), BackendVariant::Composite).unwrap(); - test_plonky3_pipeline(pipeline_gl); + let inputs_gl = inputs + .iter() + .map(|x| GoldilocksField::from(*x)) + .collect::>(); + + let pipeline_gl_native = + make_prepared_pipeline(file_name, inputs_gl.clone(), vec![], LinkerMode::Native); + test_mock_backend(pipeline_gl_native.clone()); + run_pilcom_with_backend_variant(pipeline_gl_native, BackendVariant::Composite).unwrap(); + + let pipeline_gl_bus = + make_prepared_pipeline(file_name, inputs_gl.clone(), vec![], LinkerMode::Bus); + test_mock_backend(pipeline_gl_bus.clone()); + test_plonky3_pipeline(pipeline_gl_bus); } pub fn test_pilcom(pipeline: Pipeline) { diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 99ecf47326..3271252344 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -1,7 +1,7 @@ use std::collections::BTreeMap; use powdr_executor::constant_evaluator; -use powdr_linker::LinkerParams; +use powdr_linker::{LinkerMode, LinkerParams}; use powdr_number::{FieldElement, GoldilocksField}; use powdr_pipeline::{ test_util::{ @@ -22,7 +22,8 @@ fn slice_to_vec(arr: &[i32]) -> Vec { fn sqrt_asm() { let f = "asm/sqrt.asm"; let i = [3]; - let pipeline: Pipeline = make_prepared_pipeline(f, slice_to_vec(&i), vec![]); + let pipeline: Pipeline = + make_prepared_pipeline(f, slice_to_vec(&i), vec![], LinkerMode::Bus); test_mock_backend(pipeline); } @@ -110,7 +111,8 @@ fn block_machine_cache_miss() { fn palindrome() { let f = "asm/palindrome.asm"; let i = [7, 1, 7, 3, 9, 3, 7, 1]; - let pipeline: Pipeline = make_prepared_pipeline(f, slice_to_vec(&i), vec![]); + let pipeline: Pipeline = + make_prepared_pipeline(f, slice_to_vec(&i), vec![], LinkerMode::Bus); test_mock_backend(pipeline); } @@ -341,7 +343,8 @@ fn multi_return_wrong_assignment_register_length() { fn bit_access() { let f = "asm/bit_access.asm"; let i = [20]; - let pipeline: Pipeline = make_prepared_pipeline(f, slice_to_vec(&i), vec![]); + let pipeline: Pipeline = + make_prepared_pipeline(f, slice_to_vec(&i), vec![], LinkerMode::Bus); test_mock_backend(pipeline); } @@ -356,7 +359,8 @@ fn sqrt() { fn functional_instructions() { let f = "asm/functional_instructions.asm"; let i = [20]; - let pipeline: Pipeline = make_prepared_pipeline(f, slice_to_vec(&i), vec![]); + let pipeline: Pipeline = + make_prepared_pipeline(f, slice_to_vec(&i), vec![], LinkerMode::Bus); test_mock_backend(pipeline); } @@ -538,7 +542,12 @@ mod book { fn run_book_test(file: &str) { use powdr_pipeline::test_util::test_mock_backend; // passing 0 to all tests currently works as they either take no prover input or 0 works - let pipeline = make_prepared_pipeline::(file, vec![0.into()], vec![]); + let pipeline = make_prepared_pipeline::( + file, + vec![0.into()], + vec![], + LinkerMode::Bus, + ); test_mock_backend(pipeline); } @@ -550,7 +559,8 @@ mod book { fn hello_world_asm_fail() { let f = "asm/book/hello_world.asm"; let i = [2]; - let pipeline: Pipeline = make_prepared_pipeline(f, slice_to_vec(&i), vec![]); + let pipeline: Pipeline = + make_prepared_pipeline(f, slice_to_vec(&i), vec![], LinkerMode::Bus); test_mock_backend(pipeline); } diff --git a/pipeline/tests/pil.rs b/pipeline/tests/pil.rs index 20ce509a2c..df197943ec 100644 --- a/pipeline/tests/pil.rs +++ b/pipeline/tests/pil.rs @@ -1,3 +1,4 @@ +use powdr_linker::LinkerMode; use powdr_number::GoldilocksField; use powdr_pipeline::{ test_util::{ @@ -110,7 +111,8 @@ 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 mut pipeline: Pipeline = make_prepared_pipeline(f, vec![], vec![]); + let mut pipeline: Pipeline = + make_prepared_pipeline(f, vec![], vec![], LinkerMode::Bus); pipeline.compute_witness().unwrap(); } @@ -164,8 +166,7 @@ fn external_witgen_fails_if_none_provided() { fn external_witgen_a_provided() { let f = "pil/external_witgen.pil"; let external_witness = vec![("main::a".to_string(), vec![GoldilocksField::from(3); 16])]; - let pipeline = make_prepared_pipeline(f, Default::default(), external_witness); - test_pilcom(pipeline.clone()); + let pipeline = make_prepared_pipeline(f, Default::default(), external_witness, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -173,8 +174,7 @@ fn external_witgen_a_provided() { fn external_witgen_b_provided() { let f = "pil/external_witgen.pil"; let external_witness = vec![("main::b".to_string(), vec![GoldilocksField::from(4); 16])]; - let pipeline = make_prepared_pipeline(f, Default::default(), external_witness); - test_pilcom(pipeline.clone()); + let pipeline = make_prepared_pipeline(f, Default::default(), external_witness, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -185,8 +185,7 @@ fn external_witgen_both_provided() { ("main::a".to_string(), vec![GoldilocksField::from(3); 16]), ("main::b".to_string(), vec![GoldilocksField::from(4); 16]), ]; - let pipeline = make_prepared_pipeline(f, Default::default(), external_witness); - test_pilcom(pipeline.clone()); + let pipeline = make_prepared_pipeline(f, Default::default(), external_witness, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -199,8 +198,7 @@ fn external_witgen_fails_on_conflicting_external_witness() { // Does not satisfy b = a + 1 ("main::b".to_string(), vec![GoldilocksField::from(3); 16]), ]; - let pipeline = make_prepared_pipeline(f, Default::default(), external_witness); - test_pilcom(pipeline.clone()); + let pipeline = make_prepared_pipeline(f, Default::default(), external_witness, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -209,8 +207,8 @@ fn sum_via_witness_query() { let f = "pil/sum_via_witness_query.pil"; // Only 3 inputs -> Checks that if we return "None", the system still tries to figure it out on its own. let inputs = vec![7.into(), 8.into(), 2.into()]; - let pipeline = make_prepared_pipeline(f, inputs, Default::default()); - test_pilcom(pipeline.clone()); + let pipeline = + make_prepared_pipeline::(f, inputs, Default::default(), LinkerMode::Bus); test_mock_backend(pipeline); } @@ -221,8 +219,7 @@ fn witness_lookup() { .into_iter() .map(GoldilocksField::from) .collect::>(); - let pipeline = make_prepared_pipeline(f, inputs, Default::default()); - test_pilcom(pipeline.clone()); + let pipeline = make_prepared_pipeline(f, inputs, Default::default(), LinkerMode::Bus); test_mock_backend(pipeline); } From 5b87910aed28db56ce84beb6428cb27b42c82e39 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 11:54:07 +0100 Subject: [PATCH 02/11] JIT: Don't ignore bus interactions --- executor/src/witgen/jit/witgen_inference.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/executor/src/witgen/jit/witgen_inference.rs b/executor/src/witgen/jit/witgen_inference.rs index f1b4b3a97f..0e400b497f 100644 --- a/executor/src/witgen/jit/witgen_inference.rs +++ b/executor/src/witgen/jit/witgen_inference.rs @@ -5,8 +5,8 @@ use itertools::Itertools; use powdr_ast::analyzed::{ AlgebraicBinaryOperation, AlgebraicBinaryOperator, AlgebraicExpression as Expression, AlgebraicReference, AlgebraicUnaryOperation, AlgebraicUnaryOperator, Identity, LookupIdentity, - PermutationIdentity, PhantomBusInteractionIdentity, PhantomLookupIdentity, - PhantomPermutationIdentity, PolynomialIdentity, PolynomialType, + PermutationIdentity, PhantomLookupIdentity, PhantomPermutationIdentity, PolynomialIdentity, + PolynomialType, }; use powdr_number::FieldElement; @@ -86,12 +86,8 @@ impl<'a, T: FieldElement, FixedEval: FixedEvaluator> WitgenInference<'a, T, F &left.expressions, row_offset, ), - Identity::PhantomBusInteraction(PhantomBusInteractionIdentity { - id, - multiplicity, - tuple, - .. - }) => self.process_call(can_process, *id, multiplicity, &tuple.0, row_offset), + // TODO(bus_interaction) + Identity::PhantomBusInteraction(_) => ProcessResult::empty(), Identity::Connect(_) => ProcessResult::empty(), }; self.ingest_effects(result) From 40b80096d739b3a12218a4de9b7b475d9d1667fc Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 12:15:58 +0100 Subject: [PATCH 03/11] Linker: Don't namespace std paths --- ast/src/parsed/asm.rs | 10 ++++++++++ linker/src/lib.rs | 8 +++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/ast/src/parsed/asm.rs b/ast/src/parsed/asm.rs index c807060bbd..ff6a85710d 100644 --- a/ast/src/parsed/asm.rs +++ b/ast/src/parsed/asm.rs @@ -191,6 +191,16 @@ impl SymbolPath { pub fn into_parts(self) -> impl DoubleEndedIterator + ExactSizeIterator { self.parts.into_iter() } + + pub fn is_std(&self) -> bool { + self.parts + .get(0) + .map(|p| match p { + Part::Named(n) => n == "std", + Part::Super => false, + }) + .unwrap_or(false) + } } impl FromStr for SymbolPath { diff --git a/linker/src/lib.rs b/linker/src/lib.rs index 44e6cafdd1..e109e7c80a 100644 --- a/linker/src/lib.rs +++ b/linker/src/lib.rs @@ -360,9 +360,11 @@ fn namespaced_expression(namespace: String, mut expr: Expression) -> Expression expr.visit_expressions_mut( &mut |expr| { if let Expression::Reference(_, refs) = expr { - refs.path = SymbolPath::from_parts( - once(Part::Named(namespace.clone())).chain(refs.path.clone().into_parts()), - ); + if !refs.path.is_std() { + refs.path = SymbolPath::from_parts( + once(Part::Named(namespace.clone())).chain(refs.path.clone().into_parts()), + ); + } } ControlFlow::Continue::<(), _>(()) }, From 29e2f3a92195828366d93bfd189c2b1e2e6a1ab4 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 12:33:54 +0100 Subject: [PATCH 04/11] Bug in for secondary VM multiplicity witgen --- executor/src/witgen/machines/dynamic_machine.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/executor/src/witgen/machines/dynamic_machine.rs b/executor/src/witgen/machines/dynamic_machine.rs index d41fccf86e..26f25f1bd8 100644 --- a/executor/src/witgen/machines/dynamic_machine.rs +++ b/executor/src/witgen/machines/dynamic_machine.rs @@ -96,7 +96,9 @@ impl<'a, T: FieldElement> Machine<'a, T> for DynamicMachine<'a, T> { self.data.extend(updated_data.block); self.publics.extend(updated_data.publics); - let latch_row = self.data.len() - 1; + // The block we just added contains the first row of the next block, + // so the latch row is the second-to-last row. + let latch_row = self.data.len() - 2; self.multiplicity_counter .increment_at_row(identity_id, latch_row); From 8b204362d7ae99b1088162b46f1f62261b98207c Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 12:54:08 +0100 Subject: [PATCH 05/11] Mark test as should_panic --- pipeline/tests/asm.rs | 2 ++ test_data/asm/single_operation.asm | 3 +++ 2 files changed, 5 insertions(+) diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 3271252344..a9697a995f 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -129,6 +129,8 @@ fn empty() { } #[test] +// TODO: https://github.com/powdr-labs/powdr/issues/2292 +#[should_panic = "Identity references no namespace: Constr::PhantomBusInteraction(1, [0]);"] fn single_operation() { let f = "asm/single_operation.asm"; regular_test_all_fields(f, &[]); diff --git a/test_data/asm/single_operation.asm b/test_data/asm/single_operation.asm index 98b09e5c80..7dc1413354 100644 --- a/test_data/asm/single_operation.asm +++ b/test_data/asm/single_operation.asm @@ -14,4 +14,7 @@ machine Main with degree: 8 { SingleOperation m; link => m.nothing(); + + col witness w; + w = w * w; } From 0c0ec207b880f8af8bcb8a1b49b0a6e04ff0d46f Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 12:56:18 +0100 Subject: [PATCH 06/11] Clippy --- ast/src/parsed/asm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ast/src/parsed/asm.rs b/ast/src/parsed/asm.rs index ff6a85710d..4cd897eec5 100644 --- a/ast/src/parsed/asm.rs +++ b/ast/src/parsed/asm.rs @@ -194,7 +194,7 @@ impl SymbolPath { pub fn is_std(&self) -> bool { self.parts - .get(0) + .first() .map(|p| match p { Part::Named(n) => n == "std", Part::Super => false, From e6832b2c3fbaf54878236ef85c8be276141f1405 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 13:00:34 +0100 Subject: [PATCH 07/11] Bug in block machine multiplicity witgen --- executor/src/witgen/machines/block_machine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor/src/witgen/machines/block_machine.rs b/executor/src/witgen/machines/block_machine.rs index 385327a52d..513ac1beb0 100644 --- a/executor/src/witgen/machines/block_machine.rs +++ b/executor/src/witgen/machines/block_machine.rs @@ -445,7 +445,7 @@ impl<'a, T: FieldElement> BlockMachine<'a, T> { let updates = updates.report_side_effect(); - let global_latch_row_index = self.data.len() - 1 - self.block_size + self.latch_row; + let global_latch_row_index = self.data.len() - self.block_size + self.latch_row; self.multiplicity_counter .increment_at_row(identity_id, global_latch_row_index); From 737bd78340c700f8e9641b22b5be4b94613e86ed Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 14:41:29 +0100 Subject: [PATCH 08/11] Use bus in more cases --- pipeline/src/test_util.rs | 10 ++++++- pipeline/tests/asm.rs | 52 ++++++++++++++++++---------------- pipeline/tests/mock_backend.rs | 5 ++-- pipeline/tests/pil.rs | 45 ++++++++++++----------------- pipeline/tests/powdr_std.rs | 22 ++++++++------ 5 files changed, 71 insertions(+), 63 deletions(-) diff --git a/pipeline/src/test_util.rs b/pipeline/src/test_util.rs index 03846ada5d..4fda2dabc9 100644 --- a/pipeline/src/test_util.rs +++ b/pipeline/src/test_util.rs @@ -23,9 +23,17 @@ pub fn resolve_test_file(file_name: &str) -> PathBuf { /// Makes a new pipeline for the given file. All steps until witness generation are /// already computed, so that the test can branch off from there, without having to re-compute /// these steps. -pub fn make_simple_prepared_pipeline(file_name: &str) -> Pipeline { +pub fn make_simple_prepared_pipeline( + file_name: &str, + linker_mode: LinkerMode, +) -> Pipeline { + let linker_params = LinkerParams { + mode: linker_mode, + degree_mode: DegreeMode::Vadcop, + }; let mut pipeline = Pipeline::default() .with_tmp_output() + .with_linker_params(linker_params) .from_file(resolve_test_file(file_name)); pipeline.compute_witness().unwrap(); pipeline diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index a9697a995f..9a526029e8 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -32,14 +32,14 @@ fn block_machine_exact_number_of_rows_asm() { let f = "asm/block_machine_exact_number_of_rows.asm"; // This test needs machines to be of unequal length. Also, this is mostly testing witgen, so // we just run one backend that supports variable-length machines. - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn challenges_asm() { let f = "asm/challenges.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -62,14 +62,14 @@ fn secondary_machine_plonk() { #[test] fn secondary_block_machine_add2() { let f = "asm/secondary_block_machine_add2.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn second_phase_hint() { let f = "asm/second_phase_hint.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -103,7 +103,7 @@ fn mem_write_once_external_write() { #[test] fn block_machine_cache_miss() { let f = "asm/block_machine_cache_miss.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -145,7 +145,7 @@ fn empty_vm() { #[test] fn vm_to_block_unique_interface() { let f = "asm/vm_to_block_unique_interface.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -164,7 +164,7 @@ fn block_to_block() { #[test] fn block_to_block_empty_submachine() { let f = "asm/block_to_block_empty_submachine.asm"; - let mut pipeline: Pipeline = make_simple_prepared_pipeline(f); + let mut pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); let witness = pipeline.compute_witness().unwrap(); let arith_size = witness @@ -182,7 +182,7 @@ fn block_to_block_empty_submachine() { #[test] fn block_to_block_with_bus_monolithic() { let f = "asm/block_to_block_with_bus.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -190,7 +190,7 @@ fn block_to_block_with_bus_monolithic() { #[test] fn block_to_block_with_bus_different_sizes() { let f = "asm/block_to_block_with_bus_different_sizes.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -206,10 +206,14 @@ fn block_to_block_with_bus_composite() { // challenges. As a result, the challenges during verification differ and the constraints are // not satisfied. + use powdr_number::Bn254Field; use powdr_pipeline::test_util::test_halo2_with_backend_variant; let f = "asm/block_to_block_with_bus.asm"; - let pipeline = make_simple_prepared_pipeline(f); - test_mock_backend(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); + test_mock_backend(pipeline); + + // Native linker mode, because bus constraints are exponential in Halo2 + let pipeline = make_simple_prepared_pipeline(f, LinkerMode::Native); test_halo2_with_backend_variant(pipeline, BackendVariant::Composite); } @@ -255,7 +259,7 @@ fn vm_to_block_array() { fn dynamic_vadcop() { let f = "asm/dynamic_vadcop.asm"; - let mut pipeline_gl = make_simple_prepared_pipeline(f); + let mut pipeline_gl = make_simple_prepared_pipeline::(f, LinkerMode::Bus); let witness = pipeline_gl.compute_witness().unwrap(); let witness_by_name = witness .iter() @@ -289,28 +293,28 @@ fn vm_to_block_multiple_links() { #[test] fn mem_read_write() { let f = "asm/mem_read_write.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn mem_read_write_no_memory_accesses() { let f = "asm/mem_read_write_no_memory_accesses.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn mem_read_write_with_bootloader() { let f = "asm/mem_read_write_with_bootloader.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn mem_read_write_large_diffs() { let f = "asm/mem_read_write_large_diffs.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -353,7 +357,7 @@ fn bit_access() { #[test] fn sqrt() { let f = "asm/sqrt.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -438,7 +442,7 @@ fn enum_in_asm() { #[test] fn pass_range_constraints() { let f = "asm/pass_range_constraints.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -570,7 +574,7 @@ fn hello_world_asm_fail() { #[should_panic = "FailedAssertion(\"This should fail.\")"] fn failing_assertion() { let f = "asm/failing_assertion.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -767,7 +771,7 @@ fn keccak() { #[test] fn connect_no_witgen() { let f = "asm/connect_no_witgen.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Native); // TODO Mock prover doesn't support this test yet. test_pilcom(pipeline); } @@ -775,7 +779,7 @@ fn connect_no_witgen() { #[test] fn generics_preservation() { let f = "asm/generics_preservation.asm"; - make_simple_prepared_pipeline::(f); + make_simple_prepared_pipeline::(f, LinkerMode::Bus); // No need to generate a proof here. } @@ -783,21 +787,21 @@ fn generics_preservation() { fn trait_parsing() { // Should be expanded/renamed when traits functionality is fully implemented let f = "asm/trait_parsing.asm"; - make_simple_prepared_pipeline::(f); + make_simple_prepared_pipeline::(f, LinkerMode::Bus); // No need to generate a proof here. } #[test] fn dynamic_fixed_cols() { let f = "asm/dynamic_fixed_cols.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn type_vars_in_local_decl() { let f = "asm/type_vars_in_local_decl.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } diff --git a/pipeline/tests/mock_backend.rs b/pipeline/tests/mock_backend.rs index 3845a9830d..3cf8cc6704 100644 --- a/pipeline/tests/mock_backend.rs +++ b/pipeline/tests/mock_backend.rs @@ -1,3 +1,4 @@ +use powdr_linker::LinkerMode; use powdr_number::GoldilocksField; use powdr_pipeline::test_util::{make_simple_prepared_pipeline, test_mock_backend}; use test_log::test; @@ -15,7 +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); + 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]), @@ -34,7 +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 pipeline = make_simple_prepared_pipeline::(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); // Get the correct witness let witness = pipeline.witness().unwrap(); diff --git a/pipeline/tests/pil.rs b/pipeline/tests/pil.rs index df197943ec..59a553ff80 100644 --- a/pipeline/tests/pil.rs +++ b/pipeline/tests/pil.rs @@ -7,7 +7,7 @@ use powdr_pipeline::{ assert_proofs_fail_for_invalid_witnesses_pilcom, assert_proofs_fail_for_invalid_witnesses_stwo, make_prepared_pipeline, make_simple_prepared_pipeline, regular_test_all_fields, regular_test_gl, - test_halo2_with_backend_variant, test_mock_backend, test_pilcom, test_stwo, BackendVariant, + test_halo2_with_backend_variant, test_mock_backend, test_stwo, BackendVariant, }, Pipeline, }; @@ -157,8 +157,7 @@ fn fib_arrays() { #[should_panic = "Witness generation failed."] fn external_witgen_fails_if_none_provided() { let f = "pil/external_witgen.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -227,24 +226,21 @@ fn witness_lookup() { #[should_panic(expected = "Witness generation failed.")] fn underdetermined_zero_no_solution() { let f = "pil/underdetermined_zero_no_solution.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn pair_lookup() { let f = "pil/pair_lookup.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn block_lookup_or() { let f = "pil/block_lookup_or.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -252,8 +248,7 @@ fn block_lookup_or() { #[ignore = "Too slow"] fn block_lookup_or_permutation() { let f = "pil/block_lookup_or_permutation.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -324,48 +319,42 @@ fn fibonacci_invalid_witness_stwo() { #[test] fn simple_div() { let f = "pil/simple_div.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn single_line_blocks() { let f = "pil/single_line_blocks.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn two_block_machine_functions() { let f = "pil/two_block_machine_functions.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn fixed_columns() { let f = "pil/fixed_columns.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn witness_via_let() { let f = "pil/witness_via_let.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } #[test] fn conditional_fixed_constraints() { let f = "pil/conditional_fixed_constraints.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -379,7 +368,9 @@ fn referencing_arrays() { fn naive_byte_decomposition_bn254() { // This should pass, because BN254 is a field that can fit all 64-Bit integers. let f = "pil/naive_byte_decomposition.pil"; - let pipeline = make_simple_prepared_pipeline(f); + + // Native linker mode, because bus constraints are exponential in Halo2 + let pipeline = make_simple_prepared_pipeline(f, LinkerMode::Native); test_halo2_with_backend_variant(pipeline, BackendVariant::Composite); } @@ -388,8 +379,7 @@ fn naive_byte_decomposition_bn254() { fn naive_byte_decomposition_gl() { // This should fail, because GoldilocksField is a field that cannot fit all 64-Bit integers. let f = "pil/naive_byte_decomposition.pil"; - let pipeline = make_simple_prepared_pipeline(f); - test_pilcom(pipeline.clone()); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline); } @@ -441,7 +431,8 @@ mod book { use test_log::test; fn run_book_test(file: &str) { - test_pilcom(make_simple_prepared_pipeline(file)); + let pipeline = make_simple_prepared_pipeline::(file, LinkerMode::Bus); + test_mock_backend(pipeline); } include!(concat!(env!("OUT_DIR"), "/pil_book_tests.rs")); diff --git a/pipeline/tests/powdr_std.rs b/pipeline/tests/powdr_std.rs index 97ed8a50e3..7dadb21b83 100644 --- a/pipeline/tests/powdr_std.rs +++ b/pipeline/tests/powdr_std.rs @@ -1,5 +1,6 @@ use std::sync::Arc; +use powdr_linker::LinkerMode; use powdr_number::{BabyBearField, BigInt, Bn254Field, GoldilocksField}; use powdr_pil_analyzer::evaluator::Value; @@ -18,7 +19,7 @@ use test_log::test; #[test] fn fingerprint_test() { let f = "std/fingerprint_test.asm"; - let pipeline = make_simple_prepared_pipeline::(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_plonky3_pipeline(pipeline); } @@ -26,7 +27,8 @@ fn fingerprint_test() { #[ignore = "Too slow"] fn poseidon_bn254_test() { let f = "std/poseidon_bn254_test.asm"; - let pipeline = make_simple_prepared_pipeline(f); + // Native linker mode, because bus constraints are exponential in Halo2 + let pipeline = make_simple_prepared_pipeline(f, LinkerMode::Native); test_halo2_with_backend_variant(pipeline.clone(), BackendVariant::Composite); // `test_halo2` only does a mock proof in the PR tests. @@ -94,7 +96,9 @@ fn poseidon2_gl_test() { #[ignore = "Too slow"] fn split_bn254_test() { let f = "std/split_bn254_test.asm"; - test_halo2_with_backend_variant(make_simple_prepared_pipeline(f), BackendVariant::Composite); + // Native linker mode, because bus constraints are exponential in Halo2 + let pipeline = make_simple_prepared_pipeline(f, LinkerMode::Native); + test_halo2_with_backend_variant(pipeline, BackendVariant::Composite); } #[test] @@ -146,7 +150,7 @@ fn memory_large_test() { regular_test_gl(f, &[]); // This one test was selected to also run estark. - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Native); gen_estark_proof_with_backend_variant(pipeline, BackendVariant::Composite); } @@ -174,7 +178,7 @@ fn memory_small_test() { #[test] fn permutation_via_challenges() { let f = "std/permutation_via_challenges.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -182,7 +186,7 @@ fn permutation_via_challenges() { #[test] fn lookup_via_challenges() { let f = "std/lookup_via_challenges.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -190,7 +194,7 @@ fn lookup_via_challenges() { #[test] fn lookup_via_challenges_range_constraint() { let f = "std/lookup_via_challenges_range_constraint.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -198,7 +202,7 @@ fn lookup_via_challenges_range_constraint() { #[test] fn bus_lookup() { let f = "std/bus_lookup.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } @@ -206,7 +210,7 @@ fn bus_lookup() { #[test] fn bus_permutation() { let f = "std/bus_permutation.asm"; - let pipeline: Pipeline = make_simple_prepared_pipeline(f); + let pipeline = make_simple_prepared_pipeline::(f, LinkerMode::Bus); test_mock_backend(pipeline.clone()); test_plonky3_pipeline(pipeline); } From 6b949ad9741cebc385d4aba7b32efb6057abec4b Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 15:17:16 +0100 Subject: [PATCH 09/11] Enable bus in RISC-V tests --- riscv/tests/common/mod.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/riscv/tests/common/mod.rs b/riscv/tests/common/mod.rs index a5ed2269a6..4a78b48a27 100644 --- a/riscv/tests/common/mod.rs +++ b/riscv/tests/common/mod.rs @@ -1,4 +1,6 @@ +use core::unreachable; use mktemp::Temp; +use powdr_linker::{LinkerMode, LinkerParams}; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField, KoalaBearField}; use powdr_pipeline::{ test_util::{ @@ -22,8 +24,21 @@ pub fn verify_riscv_asm_string LinkerMode::Bus, + Some(_) => LinkerMode::Native, + None => unreachable!(), + }; + let linker_params = LinkerParams { + mode: linker_mode, + ..Default::default() + }; + let mut pipeline = Pipeline::default() .with_prover_inputs(inputs.to_vec()) + .with_linker_params(linker_params) .with_output(temp_dir.to_path_buf(), true) .from_asm_string(contents.to_string(), Some(PathBuf::from(file_name))); @@ -51,8 +66,18 @@ pub fn verify_riscv_asm_string = - unsafe { std::mem::transmute(pipeline.clone()) }; + // In that case, we would have used the bus linker mode above, but this is not + // supported by PILCOM. So, we recreate the pipeline using the native linker mode (which is the default). + // Note that this means that the witness is computed again. + let mut pipeline = Pipeline::default() + .with_prover_inputs(inputs.to_vec()) + .with_output(temp_dir.to_path_buf(), true) + .from_asm_string(contents.to_string(), Some(PathBuf::from(file_name))); + + if let Some(data) = data { + pipeline = pipeline.add_data_vec(data); + } + let pipeline_gl = unsafe { std::mem::transmute(pipeline.clone()) }; run_pilcom_with_backend_variant(pipeline_gl, BackendVariant::Composite).unwrap(); } From 97367b7fdc8fdc806ca91b3afe0d11d975c8a3e1 Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 15:21:05 +0100 Subject: [PATCH 10/11] Revert "Enable bus in RISC-V tests" This reverts commit 6b949ad9741cebc385d4aba7b32efb6057abec4b. --- riscv/tests/common/mod.rs | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/riscv/tests/common/mod.rs b/riscv/tests/common/mod.rs index 4a78b48a27..a5ed2269a6 100644 --- a/riscv/tests/common/mod.rs +++ b/riscv/tests/common/mod.rs @@ -1,6 +1,4 @@ -use core::unreachable; use mktemp::Temp; -use powdr_linker::{LinkerMode, LinkerParams}; use powdr_number::{BabyBearField, FieldElement, GoldilocksField, KnownField, KoalaBearField}; use powdr_pipeline::{ test_util::{ @@ -24,21 +22,8 @@ pub fn verify_riscv_asm_string LinkerMode::Bus, - Some(_) => LinkerMode::Native, - None => unreachable!(), - }; - let linker_params = LinkerParams { - mode: linker_mode, - ..Default::default() - }; - let mut pipeline = Pipeline::default() .with_prover_inputs(inputs.to_vec()) - .with_linker_params(linker_params) .with_output(temp_dir.to_path_buf(), true) .from_asm_string(contents.to_string(), Some(PathBuf::from(file_name))); @@ -66,18 +51,8 @@ pub fn verify_riscv_asm_string = + unsafe { std::mem::transmute(pipeline.clone()) }; run_pilcom_with_backend_variant(pipeline_gl, BackendVariant::Composite).unwrap(); } From 32ddf48fabd7f4e53658592619a315de76238a5d Mon Sep 17 00:00:00 2001 From: Georg Wiese Date: Mon, 30 Dec 2024 17:29:49 +0100 Subject: [PATCH 11/11] Remove PILCOM test --- pipeline/tests/asm.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pipeline/tests/asm.rs b/pipeline/tests/asm.rs index 9a526029e8..c49de0074c 100644 --- a/pipeline/tests/asm.rs +++ b/pipeline/tests/asm.rs @@ -6,9 +6,8 @@ use powdr_number::{FieldElement, GoldilocksField}; use powdr_pipeline::{ test_util::{ asm_string_to_pil, make_prepared_pipeline, make_simple_prepared_pipeline, - regular_test_all_fields, regular_test_gl, resolve_test_file, - run_pilcom_with_backend_variant, test_mock_backend, test_pilcom, test_plonky3_pipeline, - BackendVariant, + regular_test_all_fields, regular_test_gl, resolve_test_file, test_mock_backend, + test_pilcom, test_plonky3_pipeline, BackendVariant, }, Pipeline, }; @@ -271,9 +270,6 @@ fn dynamic_vadcop() { assert_eq!(witness_by_name["main_arith::y"].len(), 32); assert_eq!(witness_by_name["main_memory::m_addr"].len(), 32); - // Because machines have different lengths, this can only be proven - // with a composite proof. - run_pilcom_with_backend_variant(pipeline_gl.clone(), BackendVariant::Composite).unwrap(); test_mock_backend(pipeline_gl.clone()); test_plonky3_pipeline(pipeline_gl); }