From 109ee4fc3dc41a38982ec2c8a99b6b8f876a2357 Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Sat, 6 Sep 2025 16:06:49 +0000 Subject: [PATCH 1/6] binary file --- tooling/ssa_fuzzer/README.md | 8 +- .../{fuzz_target.rs => acir_vs_brillig.rs} | 2 + .../fuzzer/src/fuzz_lib/.block_context.rs.swp | Bin 0 -> 16384 bytes .../src/fuzz_lib/.initial_witness.rs.swp | Bin 0 -> 16384 bytes .../ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs | 71 ++++++++++++---- .../src/fuzz_lib/tests/advanced_references.rs | 4 +- .../fuzzer/src/fuzz_lib/tests/arrays.rs | 8 +- .../fuzzer/src/fuzz_lib/tests/basic_tests.rs | 14 ++-- .../src/fuzz_lib/tests/basic_unsigned_test.rs | 2 +- .../fuzzer/src/fuzz_lib/tests/ecdsa.rs | 12 ++- .../src/fuzz_lib/tests/embedded_curve_ops.rs | 4 +- .../src/fuzz_lib/tests/function_calls.rs | 14 ++-- .../fuzzer/src/fuzz_lib/tests/hash_tests.rs | 13 +-- .../fuzzer/src/fuzz_lib/tests/loops.rs | 18 ++-- .../fuzzer/src/fuzz_lib/tests/witness.rs | 12 +-- tooling/ssa_fuzzer/fuzzer/src/fuzzer.rs | 79 ++++++++++++++++++ tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs | 57 +++++++++++-- tooling/ssa_fuzzer/src/lib.rs | 2 +- tooling/ssa_fuzzer/src/runner.rs | 4 +- 19 files changed, 248 insertions(+), 76 deletions(-) rename tooling/ssa_fuzzer/fuzzer/src/{fuzz_target.rs => acir_vs_brillig.rs} (98%) create mode 100644 tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp create mode 100644 tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.initial_witness.rs.swp create mode 100644 tooling/ssa_fuzzer/fuzzer/src/fuzzer.rs diff --git a/tooling/ssa_fuzzer/README.md b/tooling/ssa_fuzzer/README.md index 9ffa9612b55..6c7d9c1f1a7 100644 --- a/tooling/ssa_fuzzer/README.md +++ b/tooling/ssa_fuzzer/README.md @@ -31,23 +31,23 @@ cargo install cargo-fuzz 2. Run fuzzer: ``` -cargo +nightly fuzz run base_target --fuzz-dir ./fuzzer +cargo +nightly fuzz run acir_vs_brillig --fuzz-dir ./fuzzer ``` or in 5 threads ``` -cargo +nightly fuzz run base_target --fuzz-dir ./fuzzer -- -jobs=5 -workers=5 +cargo +nightly fuzz run acir_vs_brillig --fuzz-dir ./fuzzer -- -jobs=5 -workers=5 ``` 3. Triage crashes: ``` -TRIAGE=FULL/FINAL cargo +nightly fuzz run base_target --fuzz-dir ./fuzzer PATH_TO_CRASH +TRIAGE=FULL/FINAL cargo +nightly fuzz run acir_vs_brillig --fuzz-dir ./fuzzer PATH_TO_CRASH ``` FULL mode will show all SSA passes, FINAL mode will show only the final SSA pass (After Dead Instruction Elimination (3)). 4. Minimize crashes: ``` -cargo +nightly fuzz tmin base_target --fuzz-dir ./fuzzer PATH_TO_CRASH -runs=1000 +cargo +nightly fuzz tmin acir_vs_brillig --fuzz-dir ./fuzzer PATH_TO_CRASH -runs=1000 ``` diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_target.rs b/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs similarity index 98% rename from tooling/ssa_fuzzer/fuzzer/src/fuzz_target.rs rename to tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs index 65ff1eb2309..5bda6829b5e 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_target.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs @@ -15,6 +15,7 @@ use mutations::mutate; use noirc_driver::CompileOptions; use rand::{SeedableRng, rngs::StdRng}; use sha1::{Digest, Sha1}; +#[cfg(feature = "redis-support")] use utils::{push_fuzzer_output_to_redis_queue, redis}; const MAX_EXECUTION_TIME_TO_KEEP_IN_CORPUS: u64 = 3; @@ -73,6 +74,7 @@ libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus { let fuzzer_output = fuzz_target(fuzzer_data, options); // If REDIS_URL is set and generated program is executed + #[cfg(feature = "redis-support")] if redis::ensure_redis_connection() && fuzzer_output.is_some() { // cargo-fuzz saves tests with name equal to sha1 of content let fuzzer_output = fuzzer_output.unwrap(); diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp new file mode 100644 index 0000000000000000000000000000000000000000..d06ad53871df544fc1dd665f00ec110b9a25b4db GIT binary patch literal 16384 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
a6QdeTF%78NA~75Av3mx}lbp-amq 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 F{R{Cx7xMrB literal 0 HcmV?d00001 diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs index 4618b8b8fc5..37cf322de5b 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs @@ -54,16 +54,41 @@ pub(crate) struct Fuzzer { #[derive(Clone, Debug)] pub(crate) struct FuzzerOutput { - pub(crate) witness_stack: WitnessStack, - pub(crate) program: CompiledProgram, + pub(crate) witness_stack_acir: WitnessStack, + pub(crate) witness_stack_brillig: WitnessStack, + pub(crate) acir_program: CompiledProgram, + pub(crate) brillig_program: CompiledProgram, } +// TODO(sn): https://github.com/noir-lang/noir/issues/9743 impl FuzzerOutput { - pub(crate) fn get_return_values(&self) -> Vec { - let return_witnesses = &self.program.program.functions[0].return_values.0; - let witness_vec = &self.witness_stack.peek().unwrap().witness; + fn get_return_witnesses( + &self, + program: &CompiledProgram, + witness_stack: &WitnessStack, + ) -> Vec { + let return_witnesses = &program.program.functions[0].return_values.0; + let witness_vec = &witness_stack.peek().unwrap().witness; return_witnesses.iter().map(|witness| witness_vec[witness]).collect() } + + pub(crate) fn get_return_values_acir(&self) -> Vec { + self.get_return_witnesses(&self.acir_program, &self.witness_stack_acir) + } + + // TODO(sn): https://github.com/noir-lang/noir/issues/9743 + #[allow(dead_code)] + pub(crate) fn get_return_values_brillig(&self) -> Vec { + self.get_return_witnesses(&self.brillig_program, &self.witness_stack_brillig) + } + + // TODO(sn): https://github.com/noir-lang/noir/issues/9743 + #[allow(dead_code)] + pub(crate) fn get_input_values_brillig(&self) -> Vec { + let input_witnesses = &self.acir_program.program.functions[0].private_parameters; + let witness_vec = &self.witness_stack_brillig.peek().unwrap().witness; + input_witnesses.iter().map(|witness| witness_vec[witness]).collect() + } } impl Fuzzer { @@ -106,7 +131,7 @@ impl Fuzzer { let results_set = execution_results .values() .map(|result| -> Option> { - result.as_ref().map(|r| r.get_return_values()) + result.as_ref().map(|r| r.get_return_values_acir()) }) .collect::>(); @@ -114,8 +139,10 @@ impl Fuzzer { let mut panic_string = String::new(); for (mode, result) in execution_results { if let Some(result) = result { - panic_string - .push_str(&format!("Mode {mode:?}: {:?}\n", result.get_return_values())); + panic_string.push_str(&format!( + "Mode {mode:?}: {:?}\n", + result.get_return_values_acir() + )); } else { panic_string.push_str(&format!("Mode {mode:?} failed\n")); } @@ -185,19 +212,27 @@ impl Fuzzer { run_and_compare(&acir_program.program, &brillig_program.program, initial_witness); log::debug!("Comparison result: {comparison_result:?}"); match comparison_result { - CompareResults::Agree(result) => { - Some(FuzzerOutput { witness_stack: result, program: acir_program }) - } + CompareResults::Agree(acir_result, brillig_result) => Some(FuzzerOutput { + witness_stack_acir: acir_result, + witness_stack_brillig: brillig_result, + acir_program, + brillig_program, + }), CompareResults::Disagree(acir_return_value, brillig_return_value) => { - let acir_fuzzer_output = - FuzzerOutput { witness_stack: acir_return_value, program: acir_program }; - let brillig_fuzzer_output = - FuzzerOutput { witness_stack: brillig_return_value, program: brillig_program }; - let acir_return_value = acir_fuzzer_output.get_return_values(); - let brillig_return_value = brillig_fuzzer_output.get_return_values(); + let acir_return_values = acir_program.program.functions[0].return_values.0.clone(); + let brillig_return_values = + brillig_program.program.functions[0].return_values.0.clone(); + let acir_return_values: Vec = acir_return_values + .iter() + .map(|witness| acir_return_value.peek().unwrap().witness[witness]) + .collect(); + let brillig_return_values: Vec = brillig_return_values + .iter() + .map(|witness| brillig_return_value.peek().unwrap().witness[witness]) + .collect(); panic!( "ACIR and Brillig programs returned different results: \ - ACIR returned {acir_return_value:?}, Brillig returned {brillig_return_value:?}" + ACIR returned {acir_return_values:?}, Brillig returned {brillig_return_values:?}" ); } CompareResults::AcirFailed(acir_error, brillig_return_value) => { diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs index 39cc4ff7c5e..afc59be613f 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs @@ -77,7 +77,7 @@ fn test_other_function_mutates_reference() { let result = fuzz_target(data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); } None => { panic!("Program failed to execute"); @@ -163,7 +163,7 @@ fn test_reference_to_reference() { let result = fuzz_target(data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); } None => { panic!("Program failed to execute"); diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs index b52308f6c22..848c6a316c7 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs @@ -71,7 +71,7 @@ fn array_get_and_set() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(4_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), None => panic!("Program failed to execute"), } } @@ -161,7 +161,7 @@ fn test_reference_in_array() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), None => panic!("Program failed to execute"), } } @@ -239,7 +239,7 @@ fn regression_fuzzer_generated_wrong_arrays() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(0_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(0_u32)), None => panic!("Program failed to execute"), } } @@ -284,7 +284,7 @@ fn test_create_array_of_arrays() { (0..3).map(|i| FieldElement::from(i as u32)).collect::>().repeat(2); let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values(), expected_return_value), + Some(result) => assert_eq!(result.get_return_values_acir(), expected_return_value), None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs index 8b5b715ec72..ccb1230a176 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs @@ -49,12 +49,12 @@ fn test_field_addition_zero_plus_one() { // Verify the result match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); println!( "✓ Test passed: field_0 + field_1 = {} + {} = {}", 0, 1, - result.get_return_values()[0] + result.get_return_values_acir()[0] ); } None => panic!("Program failed to execute"), @@ -96,7 +96,7 @@ fn test_jmp_if() { let result = fuzz_target(data, FuzzerOptions::default()); // we expect that this program executed successfully match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), None => panic!("Program failed to execute"), } @@ -122,7 +122,7 @@ fn test_jmp_if() { let result = fuzz_target(data, FuzzerOptions::default()); // we expect that this program failed to execute if let Some(result) = result { - panic!("Program executed successfully with result: {:?}", result.get_return_values()); + panic!("Program executed successfully with result: {:?}", result.get_return_values_acir()); } } @@ -189,7 +189,7 @@ fn test_mutable_variable() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(4_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), None => panic!("Program failed to execute"), } } @@ -216,7 +216,7 @@ fn smoke_test_field_to_bytes_to_field() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), None => panic!("Program failed to execute"), } } @@ -251,7 +251,7 @@ fn test_function_can_return_array() { Some(result) => { assert!( result - .get_return_values() + .get_return_values_acir() .iter() .enumerate() .all(|(i, v)| v == &FieldElement::from(i as u32)) diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs index 9febd7741da..32e90cfb9e1 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs @@ -77,7 +77,7 @@ fn test_op_u64(op: UnsignedOp) -> FieldElement { }], initial_witness: default_unsigned_witness(), }; - fuzz_target(data, FuzzerOptions::default()).unwrap().get_return_values()[0] + fuzz_target(data, FuzzerOptions::default()).unwrap().get_return_values_acir()[0] } #[test] diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs index 7a8ade87f9f..aff91f4b0a8 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs @@ -33,7 +33,7 @@ fn test_valid_ecdsa_signature_secp256r1() { initial_witness: default_witness(), }; let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); - assert_eq!(result.get_return_values()[0], FieldElement::one()); + assert_eq!(result.get_return_values_acir()[0], FieldElement::one()); } #[test] @@ -61,7 +61,7 @@ fn test_valid_ecdsa_signature_secp256k1() { initial_witness: default_witness(), }; let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); - assert_eq!(result.get_return_values()[0], FieldElement::one()); + assert_eq!(result.get_return_values_acir()[0], FieldElement::one()); } #[test] @@ -91,7 +91,9 @@ fn test_corrupted_ecdsa_signature_secp256r1() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(res) => panic!("Programs executed with the Result: {:?}", res.get_return_values()), + Some(res) => { + panic!("Programs executed with the Result: {:?}", res.get_return_values_acir()) + } None => println!("Error. As expected"), } } @@ -123,7 +125,9 @@ fn test_corrupted_ecdsa_signature_secp256k1() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(res) => panic!("Programs executed with the Result: {:?}", res.get_return_values()), + Some(res) => { + panic!("Programs executed with the Result: {:?}", res.get_return_values_acir()) + } None => println!("Error. As expected"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs index 6753dd189a3..d9cc862d930 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs @@ -47,7 +47,7 @@ fn smoke_test_embedded_curve_add() { }; let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::try_from_str( "8902249110305491597038405103722863701255802573786510474664632793109847672620" ) @@ -92,7 +92,7 @@ fn smoke_test_embedded_multi_scalar_mul() { }; let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::try_from_str( "-3851299760922698091325321774664553326049887197487063802849283717866939395465" ) diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs index c3ef6e565bc..9bb6a057717 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs @@ -57,7 +57,7 @@ fn simple_function_call() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(4_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), None => panic!("Program failed to execute"), } } @@ -137,7 +137,7 @@ fn several_functions_several_calls() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(12_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(12_u32)), None => panic!("Program failed to execute"), } } @@ -242,7 +242,7 @@ fn call_in_if_else() { FuzzerOptions::default(), ); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(4_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), None => panic!("Program failed to execute"), } @@ -274,7 +274,7 @@ fn call_in_if_else() { }; let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(6_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(6_u32)), None => panic!("Program failed to execute"), } } @@ -362,7 +362,9 @@ fn test_does_not_insert_too_many_instructions_with_function_calls() { let options = FuzzerOptions { max_instructions_num: 100, ..FuzzerOptions::default() }; let result = fuzz_target(data.clone(), options); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1024_u32)), + Some(result) => { + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1024_u32)); + } None => panic!("Program failed to execute"), } // with max 1000 instructions both functions should be executed @@ -372,7 +374,7 @@ fn test_does_not_insert_too_many_instructions_with_function_calls() { match result { Some(result) => { assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::from(2_u32).pow(&FieldElement::from(200_u32)) // 2^200 ); } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs index 14bc6dd7beb..d4738dbffcc 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs @@ -44,7 +44,7 @@ fn smoke_test_blake2s_hash() { let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { Some(result) => assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::try_from_str( "-9211429028062209127175291049466917975585300944217240748738694765619842249938" ) @@ -84,7 +84,7 @@ fn smoke_test_blake3_hash() { let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { Some(result) => assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::try_from_str( "11496696481601359239189947342432058980836600577383371976100559912527609453094" ) @@ -129,7 +129,7 @@ fn smoke_test_aes128_encrypt() { let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { Some(result) => assert_eq!( - result.get_return_values()[0], + result.get_return_values_acir()[0], FieldElement::try_from_str( "7228449286344697221705732525592563926191809635549234005020486075743434697058" ) @@ -179,7 +179,10 @@ fn smoke_test_keccakf1600() { let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(16929593379567477321_u64)); + assert_eq!( + result.get_return_values_acir()[0], + FieldElement::from(16929593379567477321_u64) + ); } None => panic!("Program failed to execute"), } @@ -223,7 +226,7 @@ fn smoke_test_sha256_compression() { let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(3205228454_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(3205228454_u32)); } None => panic!("Program failed to execute"), } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs index 2c9ccc91f7c..f305947c6f8 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs @@ -60,7 +60,9 @@ fn test_simple_loop() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1024_u32)), + Some(result) => { + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1024_u32)); + } None => panic!("Program failed to execute"), } } @@ -131,7 +133,9 @@ fn test_nested_loop() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(131072_u32)), + Some(result) => { + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(131072_u32)); + } None => panic!("Program failed to execute"), } } @@ -204,7 +208,9 @@ fn test_loop_broken_with_jmp() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(4096_u32)), + Some(result) => { + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4096_u32)); + } None => panic!("Program failed to execute"), } } @@ -277,7 +283,7 @@ fn test_jmp_if_in_cycle() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(22_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(22_u32)), None => panic!("Program failed to execute"), } @@ -313,7 +319,9 @@ fn test_jmp_if_in_cycle() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(2048_u32)), + Some(result) => { + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(2048_u32)); + } None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs index f0978b01679..1469b295da3 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs @@ -54,7 +54,7 @@ fn test_array_as_initial_witness() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), None => panic!("Program failed to execute"), } @@ -65,7 +65,7 @@ fn test_array_as_initial_witness() { }; let result = fuzz_target(data, FuzzerOptions::default()); match result { - Some(result) => assert_eq!(result.get_return_values()[0], FieldElement::from(2_u32)), + Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(2_u32)), None => panic!("Program failed to execute"), } } @@ -113,8 +113,8 @@ fn test_array_of_arrays_as_initial_witness() { let result = fuzz_target(data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(1_u32)); - assert_eq!(result.get_return_values()[1], FieldElement::from(2_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); + assert_eq!(result.get_return_values_acir()[1], FieldElement::from(2_u32)); } None => panic!("Program failed to execute"), } @@ -127,8 +127,8 @@ fn test_array_of_arrays_as_initial_witness() { let result = fuzz_target(data, FuzzerOptions::default()); match result { Some(result) => { - assert_eq!(result.get_return_values()[0], FieldElement::from(3_u32)); - assert_eq!(result.get_return_values()[1], FieldElement::from(4_u32)); + assert_eq!(result.get_return_values_acir()[0], FieldElement::from(3_u32)); + assert_eq!(result.get_return_values_acir()[1], FieldElement::from(4_u32)); } None => panic!("Program failed to execute"), } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzzer.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzzer.rs new file mode 100644 index 00000000000..063b5382dd6 --- /dev/null +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzzer.rs @@ -0,0 +1,79 @@ +//! Binary file to mutate and execute Brillig programs. +//! +//! Usage after calling binary: +//! 1) mutate -> prints b64 mutated data +//! 2) execute -> prints JSON string of the fuzzer output +//! +//! TODO(sn): add cli args to disable ops +mod fuzz_lib; +mod mutations; +mod utils; +use base64::{Engine as _, engine::general_purpose}; +use bincode::serde::{borrow_decode_from_slice, encode_to_vec}; +use fuzz_lib::{fuzz_target_lib::fuzz_target, fuzzer::FuzzerData, options::FuzzerOptions}; +use mutations::mutate as mutate_fuzzer_data; +use rand::{SeedableRng, rngs::StdRng}; +use utils::fuzzer_output_to_json; + +const SEED: u64 = 1337; + +/// Mutates the fuzzer data +/// +/// # Arguments +/// +/// * `b64_data` - The base64 encoded serialized fuzzer data +/// +/// # Returns +/// +/// * `Vec` - The mutated serialized fuzzer data in base64 encoded format +/// +fn mutate(b64_data: &[u8]) -> String { + let data = general_purpose::STANDARD.decode(b64_data).unwrap_or_default(); + let mut new_fuzzer_data: FuzzerData = + borrow_decode_from_slice(&data, bincode::config::legacy()) + .unwrap_or((FuzzerData::default(), 1337)) + .0; + let mut rng = StdRng::seed_from_u64(SEED); + mutate_fuzzer_data(&mut new_fuzzer_data, &mut rng); + let new_bytes = encode_to_vec(&new_fuzzer_data, bincode::config::legacy()).unwrap(); + general_purpose::STANDARD.encode(&new_bytes) +} + +/// Executes the fuzzer data +/// +/// # Arguments +/// +/// * `b64_data` - The base64 encoded serialized fuzzer data +/// +/// # Returns +/// +/// * `String` - The JSON string of the fuzzer output from [``fuzzer_output_to_json``] +/// +fn execute(b64_data: &[u8]) -> String { + let data = general_purpose::STANDARD.decode(b64_data).unwrap_or_default(); + let fuzzer_data: FuzzerData = borrow_decode_from_slice(&data, bincode::config::legacy()) + .unwrap_or((FuzzerData::default(), 1337)) + .0; + let fuzzer_output = fuzz_target(fuzzer_data, FuzzerOptions::default()); + match fuzzer_output { + Some(fuzzer_output) => fuzzer_output_to_json(fuzzer_output), + None => String::new(), + } +} + +fn main() { + use std::io; + let mut user_input = String::new(); + io::stdin().read_line(&mut user_input).expect("Failed to read from stdin"); + let user_input = user_input.trim(); + let parts = user_input.split_whitespace().collect::>(); + if parts.len() != 2 { + println!("Usage: mutate|execute "); + return; + } + match parts[0] { + "mutate" => println!("{}", mutate(parts[1].as_bytes())), + "execute" => println!("{}", execute(parts[1].as_bytes())), + _ => println!("Invalid command"), + } +} diff --git a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs index 7284fa561fd..0208c4808ad 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs @@ -1,27 +1,66 @@ +#[cfg(feature = "redis-support")] pub(crate) mod redis; use crate::fuzz_lib::fuzzer::FuzzerOutput; use base64::{Engine as _, engine::general_purpose}; -fn fuzzer_output_to_json(fuzzer_output: FuzzerOutput) -> String { - let program = fuzzer_output.program; - let program_json = serde_json::to_string(&program).unwrap(); - let mut program_json: serde_json::Value = serde_json::from_str(&program_json).unwrap(); +// TODO(sn): change to impl Serialize for FuzzerOutput with brillig inputs and outputs +// TODO(sn): legacy for https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg/security/ssa_fuzzer_programs_proving +// "program" field -> "acir_program"; witness_stack -> acir_witness_stack +pub(crate) fn fuzzer_output_to_json(fuzzer_output: FuzzerOutput) -> String { + let acir_program = &fuzzer_output.acir_program; + let acir_program_json = serde_json::to_string(acir_program).unwrap(); + let mut acir_program_json: serde_json::Value = + serde_json::from_str(&acir_program_json).unwrap(); + + let brillig_program = &fuzzer_output.brillig_program; + let brillig_program_json = serde_json::to_string(brillig_program).unwrap(); + let mut brillig_program_json: serde_json::Value = + serde_json::from_str(&brillig_program_json).unwrap(); + // Noir program compiles into json, storing bytecode of the program // to "bytecode" field, but default `CompiledProgram` serializer // serializes it to "program" field. - if let Some(program_value) = program_json.get("program").cloned() { - program_json.as_object_mut().unwrap().remove("program"); - program_json.as_object_mut().unwrap().insert("bytecode".to_string(), program_value); + if let Some(acir_program_value) = acir_program_json.get("program").cloned() { + acir_program_json.as_object_mut().unwrap().remove("program"); + acir_program_json + .as_object_mut() + .unwrap() + .insert("bytecode".to_string(), acir_program_value); + } + if let Some(brillig_program_value) = brillig_program_json.get("program").cloned() { + brillig_program_json.as_object_mut().unwrap().remove("program"); + brillig_program_json + .as_object_mut() + .unwrap() + .insert("bytecode".to_string(), brillig_program_value); } - let witness_map_bytes = fuzzer_output.witness_stack.serialize().unwrap(); + let witness_map_bytes = fuzzer_output.witness_stack_acir.serialize().unwrap(); let witness_map_b64 = general_purpose::STANDARD.encode(&witness_map_bytes); + + let brillig_inputs = fuzzer_output.get_input_values_brillig(); + let brillig_outputs = fuzzer_output.get_return_values_brillig(); + let mut output_json = serde_json::Map::new(); - output_json.insert("program".to_string(), program_json.clone()); + output_json.insert("program".to_string(), acir_program_json.clone()); + output_json.insert("brillig_program".to_string(), brillig_program_json.clone()); + output_json.insert( + "brillig_inputs".to_string(), + serde_json::Value::Array( + brillig_inputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), + ), + ); + output_json.insert( + "brillig_outputs".to_string(), + serde_json::Value::Array( + brillig_outputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), + ), + ); output_json.insert("witness_map_b64".to_string(), serde_json::Value::String(witness_map_b64)); serde_json::to_string(&output_json).unwrap() } +#[cfg(feature = "redis-support")] pub(crate) fn push_fuzzer_output_to_redis_queue( queue_name: &str, test_id: String, diff --git a/tooling/ssa_fuzzer/src/lib.rs b/tooling/ssa_fuzzer/src/lib.rs index f545f85f85a..e8f96f85a9f 100644 --- a/tooling/ssa_fuzzer/src/lib.rs +++ b/tooling/ssa_fuzzer/src/lib.rs @@ -99,7 +99,7 @@ mod tests { run_and_compare(&acir_program.program, &brillig_program.program, initial_witness); // If not agree throw panic, it is not intended to happen in tests match compare_results { - CompareResults::Agree(result) => result.peek().unwrap().witness[return_value], + CompareResults::Agree(result, _) => result.peek().unwrap().witness[return_value], CompareResults::Disagree(acir_result, brillig_result) => { let acir_result = acir_result.peek().unwrap().witness[return_value]; let brillig_result = brillig_result.peek().unwrap().witness[return_value]; diff --git a/tooling/ssa_fuzzer/src/runner.rs b/tooling/ssa_fuzzer/src/runner.rs index ee26a047f55..7c451cdec7c 100644 --- a/tooling/ssa_fuzzer/src/runner.rs +++ b/tooling/ssa_fuzzer/src/runner.rs @@ -10,7 +10,7 @@ use std::collections::BTreeSet; #[derive(Debug)] pub enum CompareResults { - Agree(WitnessStack), + Agree(WitnessStack, WitnessStack), Disagree(WitnessStack, WitnessStack), BothFailed(String, String), AcirFailed(String, WitnessStack), @@ -46,7 +46,7 @@ pub fn run_and_compare( let brillig_results = return_witness_brillig.iter().map(|w| brillig_witness_map[w]); let results_equal = acir_results.eq(brillig_results); if results_equal { - CompareResults::Agree(acir_witness) + CompareResults::Agree(acir_witness, brillig_witness) } else { CompareResults::Disagree(acir_witness, brillig_witness) } From e979f1d846ce95fa817dc3712fc75a2981ccd3bd Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Sat, 6 Sep 2025 16:07:07 +0000 Subject: [PATCH 2/6] forgor cargo --- tooling/ssa_fuzzer/fuzzer/Cargo.toml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/tooling/ssa_fuzzer/fuzzer/Cargo.toml b/tooling/ssa_fuzzer/fuzzer/Cargo.toml index 0229f75ebfb..4207f38623c 100644 --- a/tooling/ssa_fuzzer/fuzzer/Cargo.toml +++ b/tooling/ssa_fuzzer/fuzzer/Cargo.toml @@ -11,6 +11,10 @@ cargo-fuzz = true [lints] workspace = true +[features] +default = [] +redis-support = ["dep:redis", "dep:lazy_static"] + [dependencies] libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } noirc_evaluator.workspace = true @@ -25,8 +29,8 @@ serde.workspace = true serde_json.workspace = true base64.workspace = true sha1 = "0.10.6" -redis = "0.26" -lazy_static = "1.4" +redis = { version = "0.26", optional = true } +lazy_static = { version = "1.4", optional = true } strum_macros = "0.24" strum = "0.24" sha2.workspace = true @@ -37,12 +41,19 @@ k256 = "0.13.4" path = "../" [[bin]] -name = "fuzz_target" -path = "src/fuzz_target.rs" +name = "acir_vs_brillig" +path = "src/acir_vs_brillig.rs" test = false doc = false bench = false +required-features = ["redis-support"] +[[bin]] +name = "ssa_fuzzer" +path = "src/fuzzer.rs" +test = false +doc = false +bench = false [[test]] name = "test_fuzz_target" From 2770b8cf038e78395ea63970cdb07f2b633a66b0 Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Mon, 8 Sep 2025 12:01:11 +0000 Subject: [PATCH 3/6] a --- .../ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs | 13 +- tooling/ssa_fuzzer/fuzzer/src/brillig.rs | 97 ++++ .../fuzzer/src/fuzz_lib/.block_context.rs.swp | Bin 16384 -> 0 bytes .../src/fuzz_lib/.initial_witness.rs.swp | Bin 16384 -> 0 bytes .../fuzzer/src/fuzz_lib/block_context.rs | 542 +++++------------- .../fuzzer/src/fuzz_lib/function_context.rs | 172 ++---- .../fuzzer/src/fuzz_lib/fuzz_target_lib.rs | 91 ++- .../ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs | 217 +++---- .../ssa_fuzzer/fuzzer/src/fuzz_lib/options.rs | 2 +- .../fuzzer/src/fuzz_lib/program_context.rs | 58 +- .../src/fuzz_lib/tests/advanced_references.rs | 26 +- .../fuzzer/src/fuzz_lib/tests/arrays.rs | 50 +- .../fuzzer/src/fuzz_lib/tests/basic_tests.rs | 71 ++- .../src/fuzz_lib/tests/basic_unsigned_test.rs | 4 +- .../fuzzer/src/fuzz_lib/tests/common.rs | 9 + .../fuzzer/src/fuzz_lib/tests/ecdsa.rs | 34 +- .../src/fuzz_lib/tests/embedded_curve_ops.rs | 10 +- .../src/fuzz_lib/tests/function_calls.rs | 73 ++- .../fuzzer/src/fuzz_lib/tests/hash_tests.rs | 98 ++-- .../fuzzer/src/fuzz_lib/tests/loops.rs | 62 +- .../fuzzer/src/fuzz_lib/tests/witness.rs | 53 +- tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs | 49 +- tooling/ssa_fuzzer/src/builder.rs | 32 +- tooling/ssa_fuzzer/src/runner.rs | 9 +- 24 files changed, 821 insertions(+), 951 deletions(-) create mode 100644 tooling/ssa_fuzzer/fuzzer/src/brillig.rs delete mode 100644 tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp delete mode 100644 tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.initial_witness.rs.swp diff --git a/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs b/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs index 5bda6829b5e..e9f26ab40d9 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/acir_vs_brillig.rs @@ -13,12 +13,17 @@ use fuzz_lib::{ use libfuzzer_sys::Corpus; use mutations::mutate; use noirc_driver::CompileOptions; +use noirc_evaluator::ssa::ir::function::RuntimeType; +use noirc_frontend::monomorphization::ast::InlineType as FrontendInlineType; use rand::{SeedableRng, rngs::StdRng}; use sha1::{Digest, Sha1}; -#[cfg(feature = "redis-support")] use utils::{push_fuzzer_output_to_redis_queue, redis}; const MAX_EXECUTION_TIME_TO_KEEP_IN_CORPUS: u64 = 3; +const INLINE_TYPE: FrontendInlineType = FrontendInlineType::Inline; +const ACIR_RUNTIME: RuntimeType = RuntimeType::Acir(INLINE_TYPE); +const BRILLIG_RUNTIME: RuntimeType = RuntimeType::Brillig(INLINE_TYPE); +const TARGET_RUNTIMES: [RuntimeType; 2] = [ACIR_RUNTIME, BRILLIG_RUNTIME]; libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus { let _ = env_logger::try_init(); @@ -71,13 +76,11 @@ libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus { .unwrap_or((FuzzerData::default(), 1337)) .0; let start = std::time::Instant::now(); - let fuzzer_output = fuzz_target(fuzzer_data, options); + let fuzzer_output = fuzz_target(fuzzer_data, TARGET_RUNTIMES.to_vec(), options); // If REDIS_URL is set and generated program is executed - #[cfg(feature = "redis-support")] - if redis::ensure_redis_connection() && fuzzer_output.is_some() { + if redis::ensure_redis_connection() { // cargo-fuzz saves tests with name equal to sha1 of content - let fuzzer_output = fuzzer_output.unwrap(); let mut hasher = Sha1::new(); hasher.update(data); let sha1_hash = hasher.finalize(); diff --git a/tooling/ssa_fuzzer/fuzzer/src/brillig.rs b/tooling/ssa_fuzzer/fuzzer/src/brillig.rs new file mode 100644 index 00000000000..2869d1b1a2d --- /dev/null +++ b/tooling/ssa_fuzzer/fuzzer/src/brillig.rs @@ -0,0 +1,97 @@ +#![no_main] + +pub(crate) mod fuzz_lib; +mod mutations; +mod utils; + +use bincode::serde::{borrow_decode_from_slice, encode_to_vec}; +use fuzz_lib::{ + fuzz_target_lib::fuzz_target, + fuzzer::FuzzerData, + options::{FuzzerCommandOptions, FuzzerMode, FuzzerOptions, InstructionOptions}, +}; +use libfuzzer_sys::Corpus; +use mutations::mutate; +use noirc_driver::CompileOptions; +use noirc_evaluator::ssa::ir::function::RuntimeType; +use noirc_frontend::monomorphization::ast::InlineType as FrontendInlineType; +use rand::{SeedableRng, rngs::StdRng}; +use sha1::{Digest, Sha1}; +use utils::{push_fuzzer_output_to_redis_queue, redis}; + +const MAX_EXECUTION_TIME_TO_KEEP_IN_CORPUS: u64 = 3; +const INLINE_TYPE: FrontendInlineType = FrontendInlineType::Inline; +const BRILLIG_RUNTIME: RuntimeType = RuntimeType::Brillig(INLINE_TYPE); +const TARGET_RUNTIMES: [RuntimeType; 1] = [BRILLIG_RUNTIME]; + +libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus { + let _ = env_logger::try_init(); + + let mut compile_options = CompileOptions::default(); + if let Ok(triage_value) = std::env::var("TRIAGE") { + match triage_value.as_str() { + "FULL" => compile_options.show_ssa = true, + "FINAL" => { + compile_options.show_ssa_pass = + vec!["After Dead Instruction Elimination - ACIR".to_string()]; + } + "FIRST_AND_FINAL" => { + compile_options.show_ssa_pass = vec![ + "After Removing Unreachable Functions (1)".to_string(), + "After Dead Instruction Elimination - ACIR".to_string(), + ]; + } + _ => (), + } + } + + // You can disable some instructions with bugs that are not fixed yet + let instruction_options = InstructionOptions { ..InstructionOptions::default() }; + let modes = vec![FuzzerMode::NonConstant]; + let fuzzer_command_options = + FuzzerCommandOptions { loops_enabled: false, ..FuzzerCommandOptions::default() }; + let options = FuzzerOptions { + compile_options, + instruction_options, + modes, + fuzzer_command_options, + ..FuzzerOptions::default() + }; + let fuzzer_data = borrow_decode_from_slice(data, bincode::config::legacy()) + .unwrap_or((FuzzerData::default(), 1337)) + .0; + let start = std::time::Instant::now(); + let fuzzer_output = fuzz_target(fuzzer_data, TARGET_RUNTIMES.to_vec(), options); + + // If REDIS_URL is set and generated program is executed + if redis::ensure_redis_connection() { + // cargo-fuzz saves tests with name equal to sha1 of content + let mut hasher = Sha1::new(); + hasher.update(data); + let sha1_hash = hasher.finalize(); + let test_id = format!("{sha1_hash:x}"); + match push_fuzzer_output_to_redis_queue("fuzzer_output", test_id, fuzzer_output) { + Ok(json_str) => log::debug!("{json_str}"), + Err(e) => log::error!("Failed to push to Redis queue: {e}"), + } + } + + if start.elapsed().as_secs() > MAX_EXECUTION_TIME_TO_KEEP_IN_CORPUS { + return Corpus::Reject; + } + Corpus::Keep +}); + +libfuzzer_sys::fuzz_mutator!(|data: &mut [u8], _size: usize, max_size: usize, seed: u32| { + let mut rng = StdRng::seed_from_u64(seed as u64); + let mut new_fuzzer_data: FuzzerData = borrow_decode_from_slice(data, bincode::config::legacy()) + .unwrap_or((FuzzerData::default(), 1337)) + .0; + mutate(&mut new_fuzzer_data, &mut rng); + let new_bytes = encode_to_vec(&new_fuzzer_data, bincode::config::legacy()).unwrap(); + if new_bytes.len() > max_size { + return 0; + } + data[..new_bytes.len()].copy_from_slice(&new_bytes); + new_bytes.len() +}); diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/.block_context.rs.swp deleted file mode 100644 index d06ad53871df544fc1dd665f00ec110b9a25b4db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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
a6QdeTF%78NA~75Av3mx}lbp-amq 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 F{R{Cx7xMrB diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs index 4b2b3b20631..d313442c26a 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs @@ -66,8 +66,7 @@ impl BlockContext { /// Inserts an instruction that takes a single argument fn insert_instruction_with_single_arg( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, arg: NumericArgument, instruction: InstructionWithOneArg, ) { @@ -76,17 +75,14 @@ impl BlockContext { Some(value) => value, _ => return, }; - let acir_result = instruction(acir_builder, value.clone()); - // insert to brillig, assert id is the same - assert_eq!(acir_result, instruction(brillig_builder, value)); - self.store_variable(&acir_result); + let result = instruction(builder, value.clone()); + self.store_variable(&result); } /// Inserts an instruction that takes two arguments fn insert_instruction_with_double_args( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, lhs: NumericArgument, rhs: NumericArgument, instruction: InstructionWithTwoArgs, @@ -98,79 +94,52 @@ impl BlockContext { (Some(acir_lhs), Some(acir_rhs)) => (acir_lhs, acir_rhs), _ => return, }; - let result = instruction(acir_builder, instr_lhs.clone(), instr_rhs.clone()); - // insert to brillig, assert id of return is the same - assert_eq!(result, instruction(brillig_builder, instr_lhs, instr_rhs)); + let result = instruction(builder, instr_lhs.clone(), instr_rhs.clone()); self.store_variable(&result); } /// Inserts an instruction into both ACIR and Brillig programs - fn insert_instruction( - &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, - instruction: Instruction, - ) { + fn insert_instruction(&mut self, builder: &mut FuzzerBuilder, instruction: Instruction) { match instruction { Instruction::AddChecked { lhs, rhs } => { if !self.options.instruction_options.add_enabled { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_add_instruction_checked(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_add_instruction_checked(lhs, rhs) + }); } Instruction::SubChecked { lhs, rhs } => { if !self.options.instruction_options.sub_enabled { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_sub_instruction_checked(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_sub_instruction_checked(lhs, rhs) + }); } Instruction::MulChecked { lhs, rhs } => { if !self.options.instruction_options.mul_enabled { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_mul_instruction_checked(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_mul_instruction_checked(lhs, rhs) + }); } Instruction::Div { lhs, rhs } => { if !self.options.instruction_options.div_enabled { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_div_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_div_instruction(lhs, rhs) + }); } Instruction::Eq { lhs, rhs } => { if !self.options.instruction_options.eq_enabled { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_eq_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_eq_instruction(lhs, rhs) + }); } Instruction::Cast { lhs, type_ } => { if !self.options.instruction_options.cast_enabled { @@ -181,12 +150,8 @@ impl BlockContext { Some(value) => value, _ => return, }; - let acir_result = acir_builder.insert_cast(value.clone(), Type::Numeric(type_)); - assert_eq!( - acir_result, - brillig_builder.insert_cast(value.clone(), Type::Numeric(type_)) - ); - self.store_variable(&acir_result); + let result = builder.insert_cast(value.clone(), Type::Numeric(type_)); + self.store_variable(&result); } Instruction::Mod { lhs, rhs } => { if !self.options.instruction_options.mod_enabled { @@ -196,13 +161,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_mod_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_mod_instruction(lhs, rhs) + }); } Instruction::Not { lhs } => { if !self.options.instruction_options.not_enabled { @@ -211,12 +172,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_single_arg( - acir_builder, - brillig_builder, - lhs, - |builder, lhs| builder.insert_not_instruction(lhs), - ); + self.insert_instruction_with_single_arg(builder, lhs, |builder, lhs| { + builder.insert_not_instruction(lhs) + }); } Instruction::Shl { lhs, rhs } => { if !self.options.instruction_options.shl_enabled { @@ -226,13 +184,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_shl_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_shl_instruction(lhs, rhs) + }); } Instruction::Shr { lhs, rhs } => { if !self.options.instruction_options.shr_enabled { @@ -242,13 +196,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_shr_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_shr_instruction(lhs, rhs) + }); } Instruction::And { lhs, rhs } => { if !self.options.instruction_options.and_enabled { @@ -258,13 +208,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_and_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_and_instruction(lhs, rhs) + }); } Instruction::Or { lhs, rhs } => { if !self.options.instruction_options.or_enabled { @@ -274,13 +220,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_or_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_or_instruction(lhs, rhs) + }); } Instruction::Xor { lhs, rhs } => { if !self.options.instruction_options.xor_enabled { @@ -290,13 +232,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_xor_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_xor_instruction(lhs, rhs) + }); } Instruction::Lt { lhs, rhs } => { if !self.options.instruction_options.lt_enabled { @@ -306,13 +244,9 @@ impl BlockContext { if lhs.numeric_type == NumericType::Field { return; } - self.insert_instruction_with_double_args( - acir_builder, - brillig_builder, - lhs, - rhs, - |builder, lhs, rhs| builder.insert_lt_instruction(lhs, rhs), - ); + self.insert_instruction_with_double_args(builder, lhs, rhs, |builder, lhs, rhs| { + builder.insert_lt_instruction(lhs, rhs) + }); } Instruction::AddSubConstrain { lhs, rhs } => { @@ -323,29 +257,17 @@ impl BlockContext { (Some(lhs_orig), Some(rhs)) => (lhs_orig, rhs), _ => return, }; - // assert ids of add are the same for both builders let lhs_add_rhs = - acir_builder.insert_add_instruction_checked(lhs_orig.clone(), rhs.clone()); - assert_eq!( - lhs_add_rhs, - brillig_builder.insert_add_instruction_checked(lhs_orig.clone(), rhs.clone()) - ); + builder.insert_add_instruction_checked(lhs_orig.clone(), rhs.clone()); // inserts lhs'' = lhs' - rhs let lhs = lhs_add_rhs; - let morphed = acir_builder.insert_sub_instruction_checked(lhs.clone(), rhs.clone()); - - // assert ids of sub are the same for both builders - assert_eq!( - morphed, - brillig_builder.insert_sub_instruction_checked(lhs.clone(), rhs.clone()) - ); + let morphed = builder.insert_sub_instruction_checked(lhs.clone(), rhs.clone()); if !self.options.constrain_idempotent_enabled { return; } - acir_builder.insert_constrain(lhs_orig.clone(), morphed.clone()); - brillig_builder.insert_constrain(lhs_orig.clone(), morphed.clone()); + builder.insert_constrain(lhs_orig.clone(), morphed.clone()); } Instruction::MulDivConstrain { lhs, rhs } => { let lhs_orig = self.get_stored_variable(&Type::Numeric(NumericType::Field), lhs); @@ -355,27 +277,16 @@ impl BlockContext { _ => return, }; // inserts lhs' = lhs * rhs - // assert ids of mul are the same for both builders let lhs_mul_rhs = - acir_builder.insert_mul_instruction_checked(lhs_orig.clone(), rhs.clone()); - assert_eq!( - lhs_mul_rhs, - brillig_builder.insert_mul_instruction_checked(lhs_orig.clone(), rhs.clone()) - ); + builder.insert_mul_instruction_checked(lhs_orig.clone(), rhs.clone()); // lhs'' = lhs' / rhs let lhs = lhs_mul_rhs; - // insert to both builders, assert ids of div are the same - let morphed = acir_builder.insert_div_instruction(lhs.clone(), rhs.clone()); - assert_eq!( - morphed, - brillig_builder.insert_div_instruction(lhs.clone(), rhs.clone()) - ); + let morphed = builder.insert_div_instruction(lhs.clone(), rhs.clone()); if !self.options.constrain_idempotent_enabled { return; } - acir_builder.insert_constrain(lhs_orig.clone(), morphed.clone()); - brillig_builder.insert_constrain(lhs_orig.clone(), morphed.clone()); + builder.insert_constrain(lhs_orig.clone(), morphed.clone()); } Instruction::AddToMemory { lhs } => { if !self.options.instruction_options.alloc_enabled { @@ -387,8 +298,7 @@ impl BlockContext { _ => return, }; - let addr = acir_builder.insert_add_to_memory(value.clone()); - assert_eq!(addr, brillig_builder.insert_add_to_memory(value.clone())); + let addr = builder.insert_add_to_memory(value.clone()); self.store_variable(&addr); } Instruction::LoadFromMemory { memory_addr } => { @@ -400,8 +310,7 @@ impl BlockContext { return; } let address = addresses[memory_addr.index % addresses.len()].clone(); - let value = acir_builder.insert_load_from_memory(address.clone()); - assert_eq!(value, brillig_builder.insert_load_from_memory(address.clone())); + let value = builder.insert_load_from_memory(address.clone()); self.store_variable(&value); } Instruction::SetToMemory { memory_addr_index, value } => { @@ -414,25 +323,18 @@ impl BlockContext { _ => return, }; let address = if addresses.is_empty() { - let addr = acir_builder.insert_add_to_memory(value.clone()); - assert_eq!(addr, brillig_builder.insert_add_to_memory(value.clone())); + let addr = builder.insert_add_to_memory(value.clone()); self.store_variable(&addr); addr } else { addresses[memory_addr_index % addresses.len()].clone() }; - acir_builder.insert_set_to_memory(address.clone(), value.clone()); - brillig_builder.insert_set_to_memory(address, value); + builder.insert_set_to_memory(address.clone(), value.clone()); } Instruction::CreateArray { elements_indices, element_type } => { // insert to both acir and brillig builders - let array = match self.insert_array( - acir_builder, - brillig_builder, - elements_indices, - element_type, - ) { + let array = match self.insert_array(builder, elements_indices, element_type) { Some(array) => array, _ => return, }; @@ -447,8 +349,7 @@ impl BlockContext { _ => return, }; let value = self.insert_array_get( - acir_builder, - brillig_builder, + builder, array_index, index, /*is constant =*/ false, @@ -472,16 +373,11 @@ impl BlockContext { }; // cast the index to u32 let index_casted = - acir_builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)); - assert_eq!( - index_casted, - brillig_builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)) - ); + builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)); // insert array set to both acir and brillig builders let new_array = self.insert_array_set( - acir_builder, - brillig_builder, + builder, array_index, index_casted, /*index_is_constant =*/ false, @@ -503,11 +399,9 @@ impl BlockContext { } Instruction::ArrayGetWithConstantIndex { array_index, index, safe_index } => { // insert constant index - let index_id = acir_builder.insert_constant(index, NumericType::U32); - assert_eq!(index_id, brillig_builder.insert_constant(index, NumericType::U32)); + let index_id = builder.insert_constant(index, NumericType::U32); let value = self.insert_array_get( - acir_builder, - brillig_builder, + builder, array_index, index_id, /*is constant =*/ true, @@ -524,11 +418,9 @@ impl BlockContext { safe_index, } => { // insert constant index - let index_id = acir_builder.insert_constant(index, NumericType::U32); - assert_eq!(index_id, brillig_builder.insert_constant(index, NumericType::U32)); + let index_id = builder.insert_constant(index, NumericType::U32); let new_array = self.insert_array_set( - acir_builder, - brillig_builder, + builder, array_index, index_id, /*index_is_constant =*/ true, @@ -571,10 +463,8 @@ impl BlockContext { Some(field) => field, _ => return, }; - let bytes = acir_builder.insert_to_le_radix(field.clone(), 256, 32); - assert_eq!(bytes, brillig_builder.insert_to_le_radix(field.clone(), 256, 32)); - let field = acir_builder.insert_from_le_radix(bytes.clone(), 256); - assert_eq!(field, brillig_builder.insert_from_le_radix(bytes.clone(), 256)); + let bytes = builder.insert_to_le_radix(field.clone(), 256, 32); + let field = builder.insert_from_le_radix(bytes.clone(), 256); self.store_variable(&field); } Instruction::Blake2sHash { field_idx, limbs_count } => { @@ -586,15 +476,9 @@ impl BlockContext { if limbs_count == 0 { return; } - let bytes = acir_builder.insert_to_le_radix(input.clone(), 256, limbs_count); - assert_eq!( - bytes, - brillig_builder.insert_to_le_radix(input.clone(), 256, limbs_count) - ); - let hash = acir_builder.insert_blake2s_hash(bytes.clone()); - assert_eq!(hash, brillig_builder.insert_blake2s_hash(bytes.clone())); - let hash_as_field = acir_builder.insert_from_le_radix(hash.clone(), 256); - assert_eq!(hash_as_field, brillig_builder.insert_from_le_radix(hash.clone(), 256)); + let bytes = builder.insert_to_le_radix(input.clone(), 256, limbs_count); + let hash = builder.insert_blake2s_hash(bytes.clone()); + let hash_as_field = builder.insert_from_le_radix(hash.clone(), 256); self.store_variable(&hash_as_field); } Instruction::Blake3Hash { field_idx, limbs_count } => { @@ -606,52 +490,31 @@ impl BlockContext { if limbs_count == 0 { return; } - let bytes = acir_builder.insert_to_le_radix(input.clone(), 256, limbs_count); - assert_eq!( - bytes, - brillig_builder.insert_to_le_radix(input.clone(), 256, limbs_count) - ); - let hash = acir_builder.insert_blake3_hash(bytes.clone()); - assert_eq!(hash, brillig_builder.insert_blake3_hash(bytes.clone())); - let hash_as_field = acir_builder.insert_from_le_radix(hash.clone(), 256); - assert_eq!(hash_as_field, brillig_builder.insert_from_le_radix(hash.clone(), 256)); + let bytes = builder.insert_to_le_radix(input.clone(), 256, limbs_count); + let hash = builder.insert_blake3_hash(bytes.clone()); + let hash_as_field = builder.insert_from_le_radix(hash.clone(), 256); self.store_variable(&hash_as_field); } Instruction::Keccakf1600Hash { u64_indices, load_elements_of_array } => { let input = match self.insert_array( - acir_builder, - brillig_builder, + builder, u64_indices.to_vec(), Type::Numeric(NumericType::U64), ) { Some(input) => input, _ => return, }; - let hash_array_u64 = acir_builder.insert_keccakf1600_permutation(input.clone()); - assert_eq!( - hash_array_u64, - brillig_builder.insert_keccakf1600_permutation(input.clone()) - ); + let hash_array_u64 = builder.insert_keccakf1600_permutation(input.clone()); self.store_variable(&hash_array_u64); if load_elements_of_array { for i in 0..25_u32 { - let index = acir_builder.insert_constant(i, NumericType::U32); - assert_eq!(index, brillig_builder.insert_constant(i, NumericType::U32)); - let value = acir_builder.insert_array_get( + let index = builder.insert_constant(i, NumericType::U32); + let value = builder.insert_array_get( hash_array_u64.clone(), index.clone(), Type::Numeric(NumericType::U64), /*safe_index =*/ false, ); - assert_eq!( - value, - brillig_builder.insert_array_get( - hash_array_u64.clone(), - index.clone(), - Type::Numeric(NumericType::U64), - /*safe_index =*/ false - ) - ); self.store_variable(&value); } } @@ -675,30 +538,15 @@ impl BlockContext { Some(iv) => iv, _ => return, }; - let input_bytes = - acir_builder.insert_to_le_radix(input.clone(), 256, input_limbs_count); - assert_eq!( - input_bytes, - brillig_builder.insert_to_le_radix(input.clone(), 256, input_limbs_count) - ); - let key_bytes = acir_builder.insert_to_le_radix(key.clone(), 256, 16); - assert_eq!(key_bytes, brillig_builder.insert_to_le_radix(key.clone(), 256, 16)); - let iv_bytes = acir_builder.insert_to_le_radix(iv.clone(), 256, 16); - assert_eq!(iv_bytes, brillig_builder.insert_to_le_radix(iv.clone(), 256, 16)); - let encrypted = acir_builder.insert_aes128_encrypt( + let input_bytes = builder.insert_to_le_radix(input.clone(), 256, input_limbs_count); + let key_bytes = builder.insert_to_le_radix(key.clone(), 256, 16); + let iv_bytes = builder.insert_to_le_radix(iv.clone(), 256, 16); + let encrypted = builder.insert_aes128_encrypt( input_bytes.clone(), key_bytes.clone(), iv_bytes.clone(), ); - assert_eq!( - encrypted, - brillig_builder.insert_aes128_encrypt(input_bytes, key_bytes, iv_bytes) - ); - let encrypted_as_field = acir_builder.insert_from_le_radix(encrypted.clone(), 256); - assert_eq!( - encrypted_as_field, - brillig_builder.insert_from_le_radix(encrypted.clone(), 256) - ); + let encrypted_as_field = builder.insert_from_le_radix(encrypted.clone(), 256); self.store_variable(&encrypted_as_field); } Instruction::Sha256Compression { @@ -707,8 +555,7 @@ impl BlockContext { load_elements_of_array, } => { let input = match self.insert_array( - acir_builder, - brillig_builder, + builder, input_indices.to_vec(), Type::Numeric(NumericType::U32), ) { @@ -716,37 +563,24 @@ impl BlockContext { _ => return, }; let state = match self.insert_array( - acir_builder, - brillig_builder, + builder, state_indices.to_vec(), Type::Numeric(NumericType::U32), ) { Some(state) => state, _ => return, }; - let compressed = - acir_builder.insert_sha256_compression(input.clone(), state.clone()); - assert_eq!(compressed, brillig_builder.insert_sha256_compression(input, state)); + let compressed = builder.insert_sha256_compression(input.clone(), state.clone()); self.store_variable(&compressed); if load_elements_of_array { for i in 0..8_u32 { - let index = acir_builder.insert_constant(i, NumericType::U32); - assert_eq!(index, brillig_builder.insert_constant(i, NumericType::U32)); - let value = acir_builder.insert_array_get( + let index = builder.insert_constant(i, NumericType::U32); + let value = builder.insert_array_get( compressed.clone(), index.clone(), Type::Numeric(NumericType::U32), /*safe_index =*/ false, ); - assert_eq!( - value, - brillig_builder.insert_array_get( - compressed.clone(), - index, - Type::Numeric(NumericType::U32), - /*safe_index =*/ false - ) - ); self.store_variable(&value); } } @@ -755,16 +589,14 @@ impl BlockContext { if !self.options.instruction_options.point_add_enabled { return; } - let p1 = self.ssa_point_from_instruction_point(acir_builder, brillig_builder, p1); - let p2 = self.ssa_point_from_instruction_point(acir_builder, brillig_builder, p2); + let p1 = self.ssa_point_from_instruction_point(builder, p1); + let p2 = self.ssa_point_from_instruction_point(builder, p2); if p1.is_none() || p2.is_none() { return; } let p1 = p1.unwrap(); let p2 = p2.unwrap(); - let acir_point = acir_builder.point_add(p1.clone(), p2.clone()); - let brillig_point = brillig_builder.point_add(p1, p2); - assert_eq!(acir_point, brillig_point); + let acir_point = builder.point_add(p1.clone(), p2.clone()); for typed_value in [&acir_point.x, &acir_point.y, &acir_point.is_infinite] { self.store_variable(typed_value); } @@ -776,8 +608,7 @@ impl BlockContext { let mut points_vec = Vec::new(); let mut scalars_vec = Vec::new(); for (p, s) in points_and_scalars.iter() { - let point = - self.ssa_point_from_instruction_point(acir_builder, brillig_builder, *p); + let point = self.ssa_point_from_instruction_point(builder, *p); let scalar = self.ssa_scalar_from_instruction_scalar(*s); if point.is_none() || scalar.is_none() { continue; @@ -791,11 +622,8 @@ impl BlockContext { if points_vec.len() != scalars_vec.len() { unreachable!("points_vec.len() != scalars_vec.len()"); } - let acir_point = - acir_builder.multi_scalar_mul(points_vec.clone(), scalars_vec.clone()); - let brillig_point = brillig_builder.multi_scalar_mul(points_vec, scalars_vec); - assert_eq!(acir_point, brillig_point); - for typed_value in [&acir_point.x, &acir_point.y, &acir_point.is_infinite] { + let point = builder.multi_scalar_mul(points_vec.clone(), scalars_vec.clone()); + for typed_value in [&point.x, &point.y, &point.is_infinite] { self.store_variable(typed_value); } } @@ -817,21 +645,12 @@ impl BlockContext { corrupt_pubkey_y, corrupt_signature, ); - let result = acir_builder.ecdsa_secp256r1( + let result = builder.ecdsa_secp256r1( prepared_signature.public_key_x.clone(), prepared_signature.public_key_y.clone(), prepared_signature.hash.clone(), prepared_signature.signature.clone(), ); - assert_eq!( - result, - brillig_builder.ecdsa_secp256r1( - prepared_signature.public_key_x, - prepared_signature.public_key_y, - prepared_signature.hash, - prepared_signature.signature, - ) - ); self.store_variable(&result); } Instruction::EcdsaSecp256k1 { @@ -852,21 +671,12 @@ impl BlockContext { corrupt_pubkey_y, corrupt_signature, ); - let result = acir_builder.ecdsa_secp256k1( + let result = builder.ecdsa_secp256k1( prepared_signature.public_key_x.clone(), prepared_signature.public_key_y.clone(), prepared_signature.hash.clone(), prepared_signature.signature.clone(), ); - assert_eq!( - result, - brillig_builder.ecdsa_secp256k1( - prepared_signature.public_key_x, - prepared_signature.public_key_y, - prepared_signature.hash, - prepared_signature.signature, - ) - ); self.store_variable(&result); } } @@ -885,38 +695,27 @@ impl BlockContext { /// Takes point from [`super::instruction::Point`] and converts it to [`noir_ssa_fuzzer::typed_value::Point`] fn ssa_point_from_instruction_point( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, point: InstructionPoint, ) -> Option { let scalar = self.ssa_scalar_from_instruction_scalar(point.scalar); scalar.as_ref()?; // wtf clippy forbid me to write if scalar.is_none() {return None} let scalar = scalar.unwrap(); - let is_infinite = acir_builder.insert_constant(point.is_infinite, NumericType::Boolean); - assert_eq!( - is_infinite, - brillig_builder.insert_constant(point.is_infinite, NumericType::Boolean) - ); + let is_infinite = builder.insert_constant(point.is_infinite, NumericType::Boolean); let point = if point.derive_from_scalar_mul { - let acir_point = acir_builder.base_scalar_mul(scalar.clone(), is_infinite.clone()); - let brillig_point = brillig_builder.base_scalar_mul(scalar, is_infinite); - assert_eq!(acir_point, brillig_point); - acir_point + let point = builder.base_scalar_mul(scalar.clone(), is_infinite.clone()); + point } else { - let acir_point = - acir_builder.create_point_from_scalar(scalar.clone(), is_infinite.clone()); - let brillig_point = brillig_builder.create_point_from_scalar(scalar, is_infinite); - assert_eq!(acir_point, brillig_point); - acir_point + let point = builder.create_point_from_scalar(scalar.clone(), is_infinite.clone()); + point }; Some(point) } fn insert_array( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, elements_indices: Vec, element_type: Type, ) -> Option { @@ -935,8 +734,7 @@ impl BlockContext { if elements.is_empty() { return None; } - let array = acir_builder.insert_array(elements.clone()); - assert_eq!(array, brillig_builder.insert_array(elements)); + let array = builder.insert_array(elements.clone()); Some(array) } @@ -954,8 +752,7 @@ impl BlockContext { /// * None if the instruction is not enabled or the array is not stored fn insert_array_get( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, array_index: usize, index: TypedValue, index_is_constant: bool, @@ -983,26 +780,13 @@ impl BlockContext { return None; } // cast the index to u32 - let index_casted = acir_builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)); - assert_eq!( - index_casted, - brillig_builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)) - ); - let value = acir_builder.insert_array_get( + let index_casted = builder.insert_cast(index.clone(), Type::Numeric(NumericType::U32)); + let value = builder.insert_array_get( array.clone(), index_casted.clone(), array.type_of_variable.unwrap_array_element_type(), safe_index, ); - assert_eq!( - value, - brillig_builder.insert_array_get( - array.clone(), - index_casted, - array.type_of_variable.unwrap_array_element_type(), - safe_index - ) - ); Some((value, array.type_of_variable.is_reference())) } @@ -1018,11 +802,9 @@ impl BlockContext { /// # Returns /// * (TypedValue referencing the new array, is_references) /// * None if the instruction is not enabled or the array is not stored - #[allow(clippy::too_many_arguments)] // I don't want this refactoring fn insert_array_set( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, array_index: usize, index: TypedValue, index_is_constant: bool, @@ -1059,22 +841,17 @@ impl BlockContext { _ => return None, }; let new_array = - acir_builder.insert_array_set(array.clone(), index.clone(), value.clone(), safe_index); - assert_eq!( - new_array, - brillig_builder.insert_array_set(array.clone(), index, value, safe_index) - ); + builder.insert_array_set(array.clone(), index.clone(), value.clone(), safe_index); Some((new_array, is_array_of_references)) } pub(crate) fn insert_instructions( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, instructions: &Vec, ) { for instruction in instructions { - self.insert_instruction(acir_builder, brillig_builder, instruction.clone()); + self.insert_instruction(builder, instruction.clone()); } } @@ -1097,8 +874,7 @@ impl BlockContext { /// The only thing we know is that one boolean is defined fn find_values_with_type( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, type_: &Type, index: Option, ) -> TypedValue { @@ -1118,63 +894,38 @@ impl BlockContext { Type::Numeric(_) => { let boolean_value = self.get_stored_variable(&Type::Numeric(NumericType::Boolean), 0).unwrap(); - let acir_value = acir_builder.insert_cast(boolean_value.clone(), type_.clone()); - let brillig_value = brillig_builder.insert_cast(boolean_value, type_.clone()); - assert_eq!(acir_value, brillig_value); + let acir_value = builder.insert_cast(boolean_value.clone(), type_.clone()); self.store_variable(&acir_value); acir_value } // On reference, try to find value with reference type, // allocate and store it in memory Type::Reference(reference_type) => { - let value = self.find_values_with_type( - acir_builder, - brillig_builder, - reference_type.as_ref(), - None, - ); - let acir_value = acir_builder.insert_add_to_memory(value.clone()); - let brillig_value = brillig_builder.insert_add_to_memory(value); - assert_eq!(acir_value, brillig_value); - self.store_variable(&acir_value); - acir_value + let value = self.find_values_with_type(builder, reference_type.as_ref(), None); + let value = builder.insert_add_to_memory(value.clone()); + self.store_variable(&value); + value } Type::Array(array_type, array_size) => { let mut values = Vec::with_capacity((*array_size as usize) * array_type.len()); for _ in 0..*array_size { let value = array_type.iter().map(|element_type| { - self.find_values_with_type( - acir_builder, - brillig_builder, - element_type, - None, - ) + self.find_values_with_type(builder, element_type, None) }); values.extend(value); } - let acir_value = acir_builder.insert_array(values.clone()); - let brillig_value = brillig_builder.insert_array(values); - assert_eq!(acir_value, brillig_value); - self.store_variable(&acir_value); - acir_value + let value = builder.insert_array(values.clone()); + self.store_variable(&value); + value } Type::Slice(slice_type) => { let values = slice_type .iter() - .map(|element_type| { - self.find_values_with_type( - acir_builder, - brillig_builder, - element_type, - None, - ) - }) + .map(|element_type| self.find_values_with_type(builder, element_type, None)) .collect::>(); - let acir_value = acir_builder.insert_slice(values.clone()); - let brillig_value = brillig_builder.insert_slice(values); - assert_eq!(acir_value, brillig_value); - self.store_variable(&acir_value); - acir_value + let value = builder.insert_slice(values.clone()); + self.store_variable(&value); + value } } } @@ -1182,32 +933,26 @@ impl BlockContext { /// Finalizes the function by setting the return value pub(crate) fn finalize_block_with_return( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, return_type: Type, ) { - let return_value = - self.find_values_with_type(acir_builder, brillig_builder, &return_type, None); - acir_builder.finalize_function(&return_value); - brillig_builder.finalize_function(&return_value); + let return_value = self.find_values_with_type(builder, &return_type, None); + builder.finalize_function(&return_value); } pub(crate) fn finalize_block_with_jmp( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, jmp_destination: BasicBlockId, args: Vec, ) { - acir_builder.insert_jmp_instruction(jmp_destination, args.clone()); - brillig_builder.insert_jmp_instruction(jmp_destination, args); + builder.insert_jmp_instruction(jmp_destination, args.clone()); self.children_blocks.push(jmp_destination); } pub(crate) fn finalize_block_with_jmp_if( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, then_destination: BasicBlockId, else_destination: BasicBlockId, ) { @@ -1219,8 +964,7 @@ impl BlockContext { .expect("Should have at least one boolean") .value_id; - acir_builder.insert_jmpif_instruction(condition, then_destination, else_destination); - brillig_builder.insert_jmpif_instruction(condition, then_destination, else_destination); + builder.insert_jmpif_instruction(condition, then_destination, else_destination); self.children_blocks.push(then_destination); self.children_blocks.push(else_destination); } @@ -1228,15 +972,13 @@ impl BlockContext { /// Inserts a function call to the given function with the given arguments and result type pub(crate) fn process_function_call( &mut self, - acir_builder: &mut FuzzerBuilder, - brillig_builder: &mut FuzzerBuilder, + builder: &mut FuzzerBuilder, function_id: Id, function_signature: FunctionInfo, args: &[usize], ) { // On SSA level you cannot just call a function by its id, you need to import it first - let func_as_value_id = acir_builder.insert_import(function_id); - assert_eq!(func_as_value_id, brillig_builder.insert_import(function_id)); + let func_as_value_id = builder.insert_import(function_id); // Get values from stored_values map by indices let mut values = vec![]; @@ -1248,25 +990,13 @@ impl BlockContext { args_to_use.extend(vec![0; function_signature.input_types.len() - args.len()]); } for (value_type, index) in zip(function_signature.input_types, args_to_use) { - let value = - self.find_values_with_type(acir_builder, brillig_builder, &value_type, Some(index)); + let value = self.find_values_with_type(builder, &value_type, Some(index)); values.push(value); } // Insert a call to the function with the given arguments and result type - let ret_val = acir_builder.insert_call( - func_as_value_id, - &values, - function_signature.return_type.clone(), - ); - assert_eq!( - ret_val, - brillig_builder.insert_call( - func_as_value_id, - &values, - function_signature.return_type.clone() - ) - ); + let ret_val = + builder.insert_call(func_as_value_id, &values, function_signature.return_type.clone()); let typed_ret_val = TypedValue { value_id: ret_val, type_of_variable: function_signature.return_type.clone(), diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs index 3704dfd8774..37ff6cf5aa9 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs @@ -99,13 +99,11 @@ pub(crate) struct StoredBlock { /// Main context for the fuzzer containing both ACIR and Brillig builders and their state pub(crate) struct FuzzerFunctionContext<'a> { - /// ACIR builder - acir_builder: &'a mut FuzzerBuilder, - /// Brillig builder - brillig_builder: &'a mut FuzzerBuilder, - /// Current ACIR and Brillig blocks + /// Builder + builder: &'a mut FuzzerBuilder, + /// Current blocks current_block: StoredBlock, - /// Stored ACIR and Brillig blocks that are not terminated + /// Stored blocks that are not terminated not_terminated_blocks: VecDeque, /// Instruction blocks instruction_blocks: &'a Vec, @@ -138,21 +136,18 @@ impl<'a> FuzzerFunctionContext<'a> { context_options: FunctionContextOptions, return_type: Type, defined_functions: BTreeMap, FunctionInfo>, - acir_builder: &'a mut FuzzerBuilder, - brillig_builder: &'a mut FuzzerBuilder, + builder: &'a mut FuzzerBuilder, ) -> Self { - let mut acir_ids = HashMap::new(); + let mut ids = HashMap::new(); for type_ in types { - let acir_id = acir_builder.insert_variable(type_.clone().into()); - let brillig_id = brillig_builder.insert_variable(type_.clone().into()); - assert_eq!(acir_id, brillig_id); - acir_ids.entry(type_.clone()).or_insert(Vec::new()).push(acir_id); + let id = builder.insert_variable(type_.clone().into()); + ids.entry(type_.clone()).or_insert(Vec::new()).push(id); } - let main_block = acir_builder.get_current_block(); + let main_block = builder.get_current_block(); let current_block = StoredBlock { context: BlockContext::new( - acir_ids.clone(), + ids.clone(), VecDeque::new(), SsaBlockOptions::from(context_options.clone()), ), @@ -160,8 +155,7 @@ impl<'a> FuzzerFunctionContext<'a> { }; Self { - acir_builder, - brillig_builder, + builder, current_block, not_terminated_blocks: VecDeque::new(), instruction_blocks, @@ -186,29 +180,21 @@ impl<'a> FuzzerFunctionContext<'a> { context_options: FunctionContextOptions, return_type: Type, defined_functions: BTreeMap, FunctionInfo>, - acir_builder: &'a mut FuzzerBuilder, - brillig_builder: &'a mut FuzzerBuilder, + builder: &'a mut FuzzerBuilder, ) -> Self { - let mut acir_ids = HashMap::new(); - let mut brillig_ids = HashMap::new(); + let mut ids = HashMap::new(); for (value, type_) in values_types.into_iter() { let field_element = value; - acir_ids - .entry(Type::Numeric(type_)) + ids.entry(Type::Numeric(type_)) .or_insert(Vec::new()) - .push(acir_builder.insert_constant(field_element, type_)); - brillig_ids - .entry(Type::Numeric(type_)) - .or_insert(Vec::new()) - .push(brillig_builder.insert_constant(field_element, type_)); - assert_eq!(brillig_ids, acir_ids); + .push(builder.insert_constant(field_element, type_)); } - let main_block = acir_builder.get_current_block(); + let main_block = builder.get_current_block(); let current_block = StoredBlock { context: BlockContext::new( - acir_ids.clone(), + ids.clone(), VecDeque::new(), SsaBlockOptions::from(context_options.clone()), ), @@ -216,8 +202,7 @@ impl<'a> FuzzerFunctionContext<'a> { }; Self { - acir_builder, - brillig_builder, + builder, current_block, not_terminated_blocks: VecDeque::new(), instruction_blocks, @@ -232,36 +217,32 @@ impl<'a> FuzzerFunctionContext<'a> { return_type, } } - /// Inserts a new SSA block into both ACIR and Brillig builders and returns its id + /// Inserts a new SSA block into builder and returns its id fn insert_ssa_block(&mut self) -> BasicBlockId { - let block_id = self.acir_builder.insert_block(); - assert_eq!(block_id, self.brillig_builder.insert_block()); + let block_id = self.builder.insert_block(); block_id } - /// Inserts a new constant into both ACIR and Brillig builders and returns its value + /// Inserts a new constant into builder and returns its value fn insert_constant( &mut self, value: impl Into + Clone, type_: NumericType, ) -> TypedValue { - let typed_value = self.acir_builder.insert_constant(value.clone(), type_); - assert_eq!(typed_value, self.brillig_builder.insert_constant(value, type_)); + let typed_value = self.builder.insert_constant(value.clone(), type_); typed_value } - /// Inserts a new jmp instruction into both ACIR and Brillig builders + /// Inserts a new jmp instruction into builder fn insert_jmp_instruction(&mut self, block_id: BasicBlockId, params: Vec) { - self.acir_builder.insert_jmp_instruction(block_id, params.clone()); - self.brillig_builder.insert_jmp_instruction(block_id, params); + self.builder.insert_jmp_instruction(block_id, params.clone()); } /// Switches to the block /// - /// This function is used to switch to the block in both ACIR and Brillig contexts. + /// This function is used to switch to the block in builder context. fn switch_to_block(&mut self, block_id: BasicBlockId) { - self.acir_builder.switch_to_block(block_id); - self.brillig_builder.switch_to_block(block_id); + self.builder.switch_to_block(block_id); } /// Stores variables of the current block @@ -320,24 +301,17 @@ impl<'a> FuzzerFunctionContext<'a> { // inserts instructions into created blocks self.switch_to_block(block_then_id); - block_then_context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &block_then_instruction_block.instructions, - ); + block_then_context + .insert_instructions(self.builder, &block_then_instruction_block.instructions); self.switch_to_block(block_else_id); - block_else_context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &block_else_instruction_block.instructions, - ); + block_else_context + .insert_instructions(self.builder, &block_else_instruction_block.instructions); // terminates current block with jmp_if self.switch_to_block(self.current_block.block_id); self.current_block.context.finalize_block_with_jmp_if( - self.acir_builder, - self.brillig_builder, + self.builder, block_then_id, block_else_id, ); @@ -420,17 +394,12 @@ impl<'a> FuzzerFunctionContext<'a> { }; // inserts instructions into the new block - destination_block_context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &block.instructions, - ); + destination_block_context.insert_instructions(self.builder, &block.instructions); // switches to the current block and terminates it with jmp self.switch_to_block(self.current_block.block_id); self.current_block.context.finalize_block_with_jmp( - self.acir_builder, - self.brillig_builder, + self.builder, destination_block_id, vec![], ); @@ -527,35 +496,19 @@ impl<'a> FuzzerFunctionContext<'a> { self.switch_to_block(block_if_id); // create iter let real_iter_id = - self.acir_builder.add_block_parameter(block_if_id, Type::Numeric(NumericType::U32)); - assert_eq!( - real_iter_id, - self.brillig_builder.add_block_parameter(block_if_id, Type::Numeric(NumericType::U32)) - ); + self.builder.add_block_parameter(block_if_id, Type::Numeric(NumericType::U32)); // condition = iter < end let condition = - self.acir_builder.insert_lt_instruction(real_iter_id.clone(), end_id.clone()).value_id; - assert_eq!( - condition, - self.brillig_builder - .insert_lt_instruction(real_iter_id.clone(), end_id.clone()) - .value_id - ); + self.builder.insert_lt_instruction(real_iter_id.clone(), end_id.clone()).value_id; // jmpif condition then: block_body, else: block_end - self.acir_builder.insert_jmpif_instruction(condition, block_body_id, block_end_id); - self.brillig_builder.insert_jmpif_instruction(condition, block_body_id, block_end_id); + self.builder.insert_jmpif_instruction(condition, block_body_id, block_end_id); // create iter block let block_iter_id = self.insert_ssa_block(); self.switch_to_block(block_iter_id); // j = iter + 1 let iterator_plus_one = - self.acir_builder.insert_add_instruction_checked(real_iter_id.clone(), one_id.clone()); - assert_eq!( - iterator_plus_one, - self.brillig_builder - .insert_add_instruction_checked(real_iter_id.clone(), one_id.clone()) - ); + self.builder.insert_add_instruction_checked(real_iter_id.clone(), one_id.clone()); // jump to the "if_block" with j = iter + 1 self.insert_jmp_instruction(block_if_id, vec![iterator_plus_one.clone()]); @@ -567,11 +520,7 @@ impl<'a> FuzzerFunctionContext<'a> { let mut block_body_context = BlockContext { children_blocks: vec![], ..self.current_block.context.clone() }; self.switch_to_block(block_body_id); - block_body_context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &block_body.instructions, - ); + block_body_context.insert_instructions(self.builder, &block_body.instructions); let end_context = if self.cycle_bodies_to_iters_ids.contains_key(&self.current_block.block_id) { @@ -614,11 +563,9 @@ impl<'a> FuzzerFunctionContext<'a> { { return; } - self.current_block.context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &instruction_block.instructions, - ); + self.current_block + .context + .insert_instructions(self.builder, &instruction_block.instructions); self.inserted_instructions_count += instruction_block.instructions.len(); } FuzzerFunctionCommand::InsertJmpIfBlock { block_then_idx, block_else_idx } => { @@ -678,8 +625,7 @@ impl<'a> FuzzerFunctionContext<'a> { self.inserted_instructions_count += unrolled_size; self.current_block.context.process_function_call( - self.acir_builder, - self.brillig_builder, + self.builder, function_id, function_info, args, @@ -712,21 +658,11 @@ impl<'a> FuzzerFunctionContext<'a> { ..closest_parent_block.context.clone() }; self.switch_to_block(first_block.block_id); - first_block.context.finalize_block_with_jmp( - self.acir_builder, - self.brillig_builder, - merged_block_id, - vec![], - ); + first_block.context.finalize_block_with_jmp(self.builder, merged_block_id, vec![]); self.stored_blocks.insert(first_block.block_id, first_block.clone()); self.switch_to_block(second_block.block_id); - second_block.context.finalize_block_with_jmp( - self.acir_builder, - self.brillig_builder, - merged_block_id, - vec![], - ); + second_block.context.finalize_block_with_jmp(self.builder, merged_block_id, vec![]); self.stored_blocks.insert(second_block.block_id, second_block.clone()); let merged_block = StoredBlock { context: merged_block_context, block_id: merged_block_id }; @@ -893,12 +829,7 @@ impl<'a> FuzzerFunctionContext<'a> { // finalize last block with jmp to return block let mut last_block = self.merge_main_block(); self.switch_to_block(last_block.block_id); - last_block.context.finalize_block_with_jmp( - self.acir_builder, - self.brillig_builder, - return_block_id, - vec![], - ); + last_block.context.finalize_block_with_jmp(self.builder, return_block_id, vec![]); // add instructions to the return block self.switch_to_block(return_block_id); @@ -907,16 +838,9 @@ impl<'a> FuzzerFunctionContext<'a> { parent_blocks_history: VecDeque::new(), ..last_block.context.clone() }; - return_block_context.insert_instructions( - self.acir_builder, - self.brillig_builder, - &return_instruction_block.instructions, - ); + return_block_context + .insert_instructions(self.builder, &return_instruction_block.instructions); - return_block_context.finalize_block_with_return( - self.acir_builder, - self.brillig_builder, - self.return_type.clone(), - ); + return_block_context.finalize_block_with_return(self.builder, self.return_type.clone()); } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs index 027b1f74956..18ba420275e 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs @@ -1,9 +1,11 @@ use super::{ - fuzzer::{Fuzzer, FuzzerData, FuzzerOutput}, + fuzzer::{CompareResults, Fuzzer, FuzzerData, FuzzerOutput}, initial_witness::{ensure_boolean_defined_in_all_functions, initialize_witness_map}, options::FuzzerOptions, }; +use acvm::acir::native_types::WitnessStack; use noir_ssa_fuzzer::typed_value::Type; +use noirc_evaluator::ssa::ir::function::RuntimeType; fn type_contains_slice_or_reference(type_: &Type) -> bool { match type_ { @@ -14,31 +16,90 @@ fn type_contains_slice_or_reference(type_: &Type) -> bool { } } -/// Creates ACIR and Brillig programs from the data, runs and compares them -pub(crate) fn fuzz_target(data: FuzzerData, options: FuzzerOptions) -> Option { - if data.instruction_blocks.is_empty() { - return None; - } - if data.functions.is_empty() { - return None; - } +/// Creates programs from the data and provided runtimes, runs and compares them +/// Returns [`FuzzerOutput`] of the first runtime provided +/// Panics if the runtimes disagree on the return values +pub(crate) fn fuzz_target( + data: FuzzerData, + runtimes: Vec, + options: FuzzerOptions, +) -> FuzzerOutput { + assert!(!runtimes.is_empty(), "No runtimes provided"); log::debug!("instruction_blocks: {:?}", data.instruction_blocks); log::debug!("initial_witness: {:?}", data.initial_witness); let (witness_map, values, types) = initialize_witness_map(&data.initial_witness); let mut data = data; data.functions[0].input_types = types; ensure_boolean_defined_in_all_functions(&mut data); + if data.instruction_blocks.is_empty() { + return FuzzerOutput { witness_stack: WitnessStack::from(witness_map), program: None }; + } + if data.functions.is_empty() { + return FuzzerOutput { witness_stack: WitnessStack::from(witness_map), program: None }; + } if type_contains_slice_or_reference(&data.functions[0].return_type) { // main cannot return a reference data.functions[0].return_type = Type::default(); } + let mut fuzzer_outputs = Vec::new(); + for runtime in runtimes.clone() { + let mut fuzzer = + Fuzzer::new(runtime, data.instruction_blocks.clone(), values.clone(), options.clone()); + for func in data.functions.clone() { + log::debug!("commands: {:?}", func.commands); + log::debug!("input_types: {:?}", func.input_types); + fuzzer.process_function(func.clone(), func.input_types.clone()); + } + fuzzer_outputs.push(fuzzer.finalize_and_run(witness_map.clone())); + } - let mut fuzzer = Fuzzer::new(data.instruction_blocks, values, options); - for func in data.functions { - log::debug!("commands: {:?}", func.commands); - log::debug!("input_types: {:?}", func.input_types); - fuzzer.process_function(func.clone(), func.input_types.clone()); + for i in 0..fuzzer_outputs.len() { + for j in i + 1..fuzzer_outputs.len() { + let result = fuzzer_outputs[i].compare_results(&fuzzer_outputs[j]); + match result { + CompareResults::Agree(_witness_stack) => { + // thats fine + } + CompareResults::Disagree(witness_stack_1, witness_stack_2) => { + panic!( + "Fuzzer runtimes {} and {} disagree on the return values: {:?} and {:?}", + runtimes[i], runtimes[j], witness_stack_1, witness_stack_2 + ); + } + CompareResults::LeftCompilationFailed => { + panic!( + "Fuzzer runtime {} failed to compile, other returned {:?}", + runtimes[i], + fuzzer_outputs[j].get_return_witnesses() + ); + } + CompareResults::RightCompilationFailed => { + panic!( + "Fuzzer runtime {} failed to compile, other returned {:?}", + runtimes[j], + fuzzer_outputs[i].get_return_witnesses() + ); + } + CompareResults::LeftExecutionFailed => { + panic!( + "Fuzzer runtime {} failed to execute, other returned {:?}", + runtimes[i], + fuzzer_outputs[j].get_return_witnesses() + ); + } + CompareResults::RightExecutionFailed => { + panic!( + "Fuzzer runtime {} failed to execute, other returned {:?}", + runtimes[j], + fuzzer_outputs[i].get_return_witnesses() + ); + } + CompareResults::BothFailed => { + // thats fine + } + } + } } - fuzzer.finalize_and_run(witness_map) + fuzzer_outputs[0].clone() } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs index 37cf322de5b..a2ad8f270cd 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs @@ -23,11 +23,9 @@ use super::{ use acvm::FieldElement; use acvm::acir::native_types::{WitnessMap, WitnessStack}; use noir_ssa_executor::runner::execute_single; -use noir_ssa_fuzzer::{ - runner::{CompareResults, run_and_compare}, - typed_value::Type, -}; +use noir_ssa_fuzzer::{runner::execute, typed_value::Type}; use noirc_driver::CompiledProgram; +use noirc_evaluator::ssa::ir::function::RuntimeType; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; @@ -54,45 +52,85 @@ pub(crate) struct Fuzzer { #[derive(Clone, Debug)] pub(crate) struct FuzzerOutput { - pub(crate) witness_stack_acir: WitnessStack, - pub(crate) witness_stack_brillig: WitnessStack, - pub(crate) acir_program: CompiledProgram, - pub(crate) brillig_program: CompiledProgram, + pub(crate) witness_stack: WitnessStack, + // None if the program failed to compile + pub(crate) program: Option, +} + +pub(crate) enum CompareResults { + Agree(Vec), + Disagree(Vec, Vec), + LeftCompilationFailed, + RightCompilationFailed, + LeftExecutionFailed, + RightExecutionFailed, + BothFailed, } // TODO(sn): https://github.com/noir-lang/noir/issues/9743 impl FuzzerOutput { - fn get_return_witnesses( - &self, - program: &CompiledProgram, - witness_stack: &WitnessStack, - ) -> Vec { - let return_witnesses = &program.program.functions[0].return_values.0; - let witness_vec = &witness_stack.peek().unwrap().witness; + pub(crate) fn get_return_witnesses(&self) -> Vec { + // program failed to compile + if self.program.is_none() { + return vec![]; + } + let return_witnesses = &self.program.as_ref().unwrap().program.functions[0].return_values.0; + let max_return_witness_index = return_witnesses.iter().max().unwrap(); + let witness_vec = &self.witness_stack.peek().unwrap().witness; + + // program failed to execute + if !witness_vec.contains_key(max_return_witness_index) { + return vec![]; + } return_witnesses.iter().map(|witness| witness_vec[witness]).collect() } - pub(crate) fn get_return_values_acir(&self) -> Vec { - self.get_return_witnesses(&self.acir_program, &self.witness_stack_acir) + pub(crate) fn get_input_witnesses(&self) -> Vec { + // program failed to compile + if self.program.is_none() { + return vec![]; + } + let input_witnesses = + &self.program.as_ref().unwrap().program.functions[0].private_parameters; + let witness_vec = &self.witness_stack.peek().unwrap().witness; + input_witnesses.iter().map(|witness| witness_vec[witness]).collect() } - // TODO(sn): https://github.com/noir-lang/noir/issues/9743 - #[allow(dead_code)] - pub(crate) fn get_return_values_brillig(&self) -> Vec { - self.get_return_witnesses(&self.brillig_program, &self.witness_stack_brillig) + pub(crate) fn compare_results(&self, other: &Self) -> CompareResults { + match (self.is_program_compiled(), other.is_program_compiled()) { + (true, true) => return CompareResults::BothFailed, + (true, false) => return CompareResults::LeftCompilationFailed, + (false, true) => return CompareResults::RightCompilationFailed, + (false, false) => { + // both programs compiled successfully + let left_return_witnesses = self.get_return_witnesses(); + let right_return_witnesses = other.get_return_witnesses(); + match (left_return_witnesses.is_empty(), right_return_witnesses.is_empty()) { + (true, true) => return CompareResults::BothFailed, + (true, false) => return CompareResults::LeftExecutionFailed, + (false, true) => return CompareResults::RightExecutionFailed, + (false, false) => { + if left_return_witnesses != right_return_witnesses { + return CompareResults::Disagree( + left_return_witnesses, + right_return_witnesses, + ); + } + CompareResults::Agree(left_return_witnesses) + } + } + } + } } - // TODO(sn): https://github.com/noir-lang/noir/issues/9743 - #[allow(dead_code)] - pub(crate) fn get_input_values_brillig(&self) -> Vec { - let input_witnesses = &self.acir_program.program.functions[0].private_parameters; - let witness_vec = &self.witness_stack_brillig.peek().unwrap().witness; - input_witnesses.iter().map(|witness| witness_vec[witness]).collect() + pub(crate) fn is_program_compiled(&self) -> bool { + self.program.is_some() } } impl Fuzzer { pub(crate) fn new( + runtime: RuntimeType, instruction_blocks: Vec, values: Vec, options: FuzzerOptions, @@ -101,6 +139,7 @@ impl Fuzzer { for mode in &options.modes { contexts.push(program_context_by_mode( mode.clone(), + runtime, instruction_blocks.clone(), values.clone(), options.clone(), @@ -119,8 +158,8 @@ impl Fuzzer { pub(crate) fn finalize_and_run( self, initial_witness: WitnessMap, - ) -> Option { - let mut execution_results: HashMap> = HashMap::new(); + ) -> FuzzerOutput { + let mut execution_results: HashMap = HashMap::new(); for mut context in self.contexts { context.finalize_program(); execution_results.insert( @@ -130,19 +169,15 @@ impl Fuzzer { } let results_set = execution_results .values() - .map(|result| -> Option> { - result.as_ref().map(|r| r.get_return_values_acir()) - }) + .map(|result| result.get_return_witnesses()) .collect::>(); if results_set.len() != 1 { let mut panic_string = String::new(); for (mode, result) in execution_results { - if let Some(result) = result { - panic_string.push_str(&format!( - "Mode {mode:?}: {:?}\n", - result.get_return_values_acir() - )); + if !result.get_return_witnesses().is_empty() { + panic_string + .push_str(&format!("Mode {mode:?}: {:?}\n", result.get_return_witnesses())); } else { panic_string.push_str(&format!("Mode {mode:?} failed\n")); } @@ -155,101 +190,19 @@ impl Fuzzer { fn execute_and_compare( context: FuzzerProgramContext, initial_witness: WitnessMap, - ) -> Option { - let (acir_program, brillig_program) = context.get_programs(); - let (acir_program, brillig_program) = match (acir_program, brillig_program) { - (Ok(acir), Ok(brillig)) => (acir, brillig), - (Err(acir_error), Err(brillig_error)) => { - log::debug!("ACIR compilation error: {acir_error:?}"); - log::debug!("Brillig compilation error: {brillig_error:?}"); - log::debug!("ACIR and Brillig compilation failed"); - return None; - } - (Ok(acir), Err(brillig_error)) => { - let acir_result = execute_single(&acir.program, initial_witness); - match acir_result { - Ok(acir_result) => { - let acir_return_witness = - acir.program.functions[0].return_values.0.first().unwrap(); - panic!( - "ACIR compiled and successfully executed, \ - but brillig compilation failed. Execution result of \ - acir only {:?}. Brillig compilation failed with: {:?}", - acir_result.peek().unwrap().witness[acir_return_witness], - brillig_error - ); - } - Err(acir_error) => { - log::debug!("ACIR execution error: {acir_error:?}"); - log::debug!("Brillig compilation error: {brillig_error:?}"); - return None; - } - } - } - (Err(acir_error), Ok(brillig)) => { - let brillig_result = execute_single(&brillig.program, initial_witness); - match brillig_result { - Ok(brillig_result) => { - let brillig_return_witness = - brillig.program.functions[0].return_values.0.first().unwrap(); - panic!( - "Brillig compiled and successfully executed, \ - but ACIR compilation failed. Execution result of \ - brillig only {:?}. ACIR compilation failed with: {:?}", - brillig_result.peek().unwrap().witness[brillig_return_witness], - acir_error - ); - } - Err(brillig_error) => { - log::debug!("Brillig execution error: {brillig_error:?}"); - log::debug!("ACIR compilation error: {acir_error:?}"); - return None; - } - } - } - }; - let comparison_result = - run_and_compare(&acir_program.program, &brillig_program.program, initial_witness); - log::debug!("Comparison result: {comparison_result:?}"); - match comparison_result { - CompareResults::Agree(acir_result, brillig_result) => Some(FuzzerOutput { - witness_stack_acir: acir_result, - witness_stack_brillig: brillig_result, - acir_program, - brillig_program, - }), - CompareResults::Disagree(acir_return_value, brillig_return_value) => { - let acir_return_values = acir_program.program.functions[0].return_values.0.clone(); - let brillig_return_values = - brillig_program.program.functions[0].return_values.0.clone(); - let acir_return_values: Vec = acir_return_values - .iter() - .map(|witness| acir_return_value.peek().unwrap().witness[witness]) - .collect(); - let brillig_return_values: Vec = brillig_return_values - .iter() - .map(|witness| brillig_return_value.peek().unwrap().witness[witness]) - .collect(); - panic!( - "ACIR and Brillig programs returned different results: \ - ACIR returned {acir_return_values:?}, Brillig returned {brillig_return_values:?}" - ); - } - CompareResults::AcirFailed(acir_error, brillig_return_value) => { - panic!( - "ACIR execution failed with error: {acir_error:?}, Brillig returned {brillig_return_value:?}" - ); - } - CompareResults::BrilligFailed(brillig_error, acir_return_value) => { - panic!( - "Brillig execution failed with error: {brillig_error:?}, ACIR returned {acir_return_value:?}" - ); - } - CompareResults::BothFailed(acir_error, brillig_error) => { - log::debug!("ACIR execution error: {acir_error:?}"); - log::debug!("Brillig execution error: {brillig_error:?}"); - None - } + ) -> FuzzerOutput { + let program = context.get_program(); + let input_witness_stack = WitnessStack::from(initial_witness.clone()); + if program.is_err() { + return FuzzerOutput { witness_stack: input_witness_stack, program: None }; + } + let witness_stack = execute(&program.as_ref().unwrap().program, initial_witness); + if witness_stack.is_err() { + return FuzzerOutput { + witness_stack: input_witness_stack, + program: Some(program.unwrap()), + }; } + FuzzerOutput { witness_stack: witness_stack.unwrap(), program: Some(program.unwrap()) } } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/options.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/options.rs index 1c7e4caaf39..c0809ed4173 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/options.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/options.rs @@ -159,7 +159,7 @@ impl Default for FuzzerOptions { fn default() -> Self { Self { compile_options: CompileOptions { - show_ssa: true, + show_ssa: false, show_ssa_pass: vec![], ..Default::default() }, diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/program_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/program_context.rs index 442504b918d..605594ce810 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/program_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/program_context.rs @@ -9,7 +9,10 @@ use noir_ssa_fuzzer::{ typed_value::Type, }; use noirc_driver::CompiledProgram; -use noirc_evaluator::ssa::ir::{function::Function, map::Id}; +use noirc_evaluator::ssa::ir::{ + function::{Function, RuntimeType}, + map::Id, +}; use std::collections::BTreeMap; struct StoredFunction { @@ -20,10 +23,8 @@ struct StoredFunction { /// FuzzerProgramContext is a context for storing and processing SSA functions pub(crate) struct FuzzerProgramContext { - /// Builder for ACIR program - acir_builder: FuzzerBuilder, - /// Builder for Brillig program - brillig_builder: FuzzerBuilder, + /// Builder for the program + builder: FuzzerBuilder, /// Options for the program context program_context_options: FunctionContextOptions, // TODO /// Whether the program is executed in constants @@ -50,16 +51,15 @@ impl FuzzerProgramContext { /// Creates a new FuzzerProgramContext fn new( program_context_options: FunctionContextOptions, + runtime: RuntimeType, instruction_blocks: Vec, values: Vec, mode: FuzzerMode, ) -> Self { - let acir_builder = FuzzerBuilder::new_acir(program_context_options.simplifying_enabled); - let brillig_builder = - FuzzerBuilder::new_brillig(program_context_options.simplifying_enabled); + let builder = + FuzzerBuilder::new_by_runtime(runtime, program_context_options.simplifying_enabled); Self { - acir_builder, - brillig_builder, + builder, program_context_options, is_constant: false, function_information: BTreeMap::new(), @@ -75,16 +75,15 @@ impl FuzzerProgramContext { /// Creates a new FuzzerProgramContext where all inputs are constants fn new_constant_context( program_context_options: FunctionContextOptions, + runtime: RuntimeType, instruction_blocks: Vec, values: Vec, mode: FuzzerMode, ) -> Self { - let acir_builder = FuzzerBuilder::new_acir(program_context_options.simplifying_enabled); - let brillig_builder = - FuzzerBuilder::new_brillig(program_context_options.simplifying_enabled); + let builder = + FuzzerBuilder::new_by_runtime(runtime, program_context_options.simplifying_enabled); Self { - acir_builder, - brillig_builder, + builder, program_context_options, is_constant: true, function_information: BTreeMap::new(), @@ -241,8 +240,7 @@ impl FuzzerProgramContext { self.program_context_options.clone(), stored_function.function.return_type.clone(), defined_functions, - &mut self.acir_builder, - &mut self.brillig_builder, + &mut self.builder, ) } else { FuzzerFunctionContext::new( @@ -251,8 +249,7 @@ impl FuzzerProgramContext { self.program_context_options.clone(), stored_function.function.return_type.clone(), defined_functions, - &mut self.acir_builder, - &mut self.brillig_builder, + &mut self.builder, ) }; self.is_main_initialized = true; @@ -264,21 +261,14 @@ impl FuzzerProgramContext { if i != self.stored_functions.len() - 1 { let current_id = stored_function.id; let new_id = Id::::new(current_id.to_u32() + 1); - self.acir_builder.new_acir_function(format!("f{}", new_id.to_u32()), new_id); - self.brillig_builder.new_brillig_function(format!("f{}", new_id.to_u32()), new_id); + self.builder.new_function(format!("f{}", new_id.to_u32()), new_id); } } } - /// Returns programs for ACIR and Brillig - pub(crate) fn get_programs( - self, - ) -> (Result, Result) - { - ( - self.acir_builder.compile(self.program_context_options.compile_options.clone()), - self.brillig_builder.compile(self.program_context_options.compile_options), - ) + /// Returns program compiled from the builder + pub(crate) fn get_program(self) -> Result { + self.builder.compile(self.program_context_options.compile_options.clone()) } pub(crate) fn get_mode(&self) -> FuzzerMode { @@ -286,9 +276,10 @@ impl FuzzerProgramContext { } } -/// Creates [`FuzzerProgramContext`] from [`FuzzerMode`] +/// Creates [`FuzzerProgramContext`] from [`FuzzerMode`] and [`RuntimeType`] pub(crate) fn program_context_by_mode( mode: FuzzerMode, + runtime: RuntimeType, instruction_blocks: Vec, values: Vec, options: FuzzerOptions, @@ -299,6 +290,7 @@ pub(crate) fn program_context_by_mode( idempotent_morphing_enabled: false, ..FunctionContextOptions::from(&options) }, + runtime, instruction_blocks, values, mode, @@ -308,6 +300,7 @@ pub(crate) fn program_context_by_mode( idempotent_morphing_enabled: false, ..FunctionContextOptions::from(&options) }, + runtime, instruction_blocks, values, mode, @@ -317,6 +310,7 @@ pub(crate) fn program_context_by_mode( idempotent_morphing_enabled: true, ..FunctionContextOptions::from(&options) }, + runtime, instruction_blocks, values, mode, @@ -330,6 +324,7 @@ pub(crate) fn program_context_by_mode( idempotent_morphing_enabled: true, ..FunctionContextOptions::from(&options) }, + runtime, instruction_blocks, values, mode, @@ -340,6 +335,7 @@ pub(crate) fn program_context_by_mode( options.simplifying_enabled = false; FuzzerProgramContext::new( FunctionContextOptions::from(&options), + runtime, instruction_blocks, values, mode, diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs index afc59be613f..812eeadebde 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/advanced_references.rs @@ -5,7 +5,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Argument, Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; use std::sync::Arc; @@ -74,14 +74,14 @@ fn test_other_function_mutates_reference() { instruction_blocks, }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); - } - None => { + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { panic!("Program failed to execute"); } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } } @@ -160,13 +160,13 @@ fn test_reference_to_reference() { initial_witness: default_witness(), instruction_blocks, }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); - } - None => { + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { panic!("Program failed to execute"); } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs index 848c6a316c7..d992ec7738b 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/arrays.rs @@ -7,7 +7,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Argument, Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; use std::sync::Arc; @@ -69,10 +69,14 @@ fn array_get_and_set() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(4_u32)); + } } } @@ -159,10 +163,14 @@ fn test_reference_in_array() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } } @@ -237,10 +245,14 @@ fn regression_fuzzer_generated_wrong_arrays() { functions: vec![main_func, func_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(0_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(0_u32)); + } } } @@ -282,9 +294,13 @@ fn test_create_array_of_arrays() { }; let expected_return_value = (0..3).map(|i| FieldElement::from(i as u32)).collect::>().repeat(2); - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir(), expected_return_value), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses(), expected_return_value); + } } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs index ccb1230a176..7e54986a4f2 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_tests.rs @@ -9,7 +9,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Argument, Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; use std::sync::Arc; @@ -44,20 +44,22 @@ fn test_field_addition_zero_plus_one() { }; // Execute the fuzzer - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); // Verify the result - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); println!( "✓ Test passed: field_0 + field_1 = {} + {} = {}", 0, 1, - result.get_return_values_acir()[0] + result.get_return_witnesses()[0] ); } - None => panic!("Program failed to execute"), } } @@ -93,11 +95,15 @@ fn test_jmp_if() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); // we expect that this program executed successfully - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), - None => panic!("Program failed to execute"), + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } let arg_0_boolean = NumericArgument { index: 0, numeric_type: NumericType::Boolean }; @@ -119,11 +125,10 @@ fn test_jmp_if() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); // we expect that this program failed to execute - if let Some(result) = result { - panic!("Program executed successfully with result: {:?}", result.get_return_values_acir()); - } + assert!(result.is_program_compiled()); + assert!(result.get_return_witnesses().is_empty()); } /// fn main f0 { @@ -187,10 +192,14 @@ fn test_mutable_variable() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(4_u32)); + } } } @@ -214,10 +223,14 @@ fn smoke_test_field_to_bytes_to_field() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } } @@ -246,17 +259,19 @@ fn test_function_can_return_array() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { assert!( result - .get_return_values_acir() + .get_return_witnesses() .iter() .enumerate() .all(|(i, v)| v == &FieldElement::from(i as u32)) ); } - None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs index 32e90cfb9e1..0716ca00333 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/basic_unsigned_test.rs @@ -18,7 +18,7 @@ use crate::fuzzer::FuzzerData; use crate::initial_witness::{WitnessValue, WitnessValueNumeric}; use crate::instruction::{Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::default_input_types; +use crate::tests::common::{default_input_types, default_runtimes}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; @@ -77,7 +77,7 @@ fn test_op_u64(op: UnsignedOp) -> FieldElement { }], initial_witness: default_unsigned_witness(), }; - fuzz_target(data, FuzzerOptions::default()).unwrap().get_return_values_acir()[0] + fuzz_target(data, default_runtimes(), FuzzerOptions::default()).get_return_witnesses()[0] } #[test] diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/common.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/common.rs index 3dd93232ff0..453b2c1b225 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/common.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/common.rs @@ -1,5 +1,7 @@ use crate::initial_witness::{FieldRepresentation, WitnessValue, WitnessValueNumeric}; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; +use noirc_evaluator::ssa::ir::function::RuntimeType; +use noirc_frontend::monomorphization::ast::InlineType as FrontendInlineType; /// Creates default witness values for testing /// Returns [Field(0), Field(1), Field(2), Field(3), Field(4)] @@ -16,3 +18,10 @@ pub(crate) fn default_witness() -> Vec { pub(crate) fn default_input_types() -> Vec { vec![Type::Numeric(NumericType::Field); 5] } + +pub(crate) fn default_runtimes() -> Vec { + vec![ + RuntimeType::Brillig(FrontendInlineType::default()), + RuntimeType::Acir(FrontendInlineType::default()), + ] +} diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs index aff91f4b0a8..54693ed7cae 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/ecdsa.rs @@ -3,7 +3,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Instruction, InstructionBlock}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::AcirField; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; @@ -32,8 +32,8 @@ fn test_valid_ecdsa_signature_secp256r1() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); - assert_eq!(result.get_return_values_acir()[0], FieldElement::one()); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + assert_eq!(result.get_return_witnesses()[0], FieldElement::one()); } #[test] @@ -60,8 +60,8 @@ fn test_valid_ecdsa_signature_secp256k1() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); - assert_eq!(result.get_return_values_acir()[0], FieldElement::one()); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + assert_eq!(result.get_return_witnesses()[0], FieldElement::one()); } #[test] @@ -89,12 +89,14 @@ fn test_corrupted_ecdsa_signature_secp256r1() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(res) => { - panic!("Programs executed with the Result: {:?}", res.get_return_values_acir()) + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + // thats okay + } + false => { + panic!("Programs executed with the Result: {:?}", result.get_return_witnesses()) } - None => println!("Error. As expected"), } } @@ -123,11 +125,13 @@ fn test_corrupted_ecdsa_signature_secp256k1() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(res) => { - panic!("Programs executed with the Result: {:?}", res.get_return_values_acir()) + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + // thats okay + } + false => { + panic!("Programs executed with the Result: {:?}", result.get_return_witnesses()) } - None => println!("Error. As expected"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs index d9cc862d930..f918b018975 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/embedded_curve_ops.rs @@ -3,7 +3,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Instruction, InstructionBlock, Point, Scalar}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; @@ -45,9 +45,9 @@ fn smoke_test_embedded_curve_add() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); assert_eq!( - result.get_return_values_acir()[0], + result.get_return_witnesses()[0], FieldElement::try_from_str( "8902249110305491597038405103722863701255802573786510474664632793109847672620" ) @@ -90,9 +90,9 @@ fn smoke_test_embedded_multi_scalar_mul() { functions: vec![function], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()).unwrap(); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); assert_eq!( - result.get_return_values_acir()[0], + result.get_return_witnesses()[0], FieldElement::try_from_str( "-3851299760922698091325321774664553326049887197487063802849283717866939395465" ) diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs index 9bb6a057717..96ffe55fb11 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/function_calls.rs @@ -8,7 +8,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Argument, Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::AcirField; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; @@ -55,10 +55,14 @@ fn simple_function_call() { ], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(4_u32)); + } } } @@ -135,10 +139,14 @@ fn several_functions_several_calls() { functions: vec![main_func, f1_func, f2_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(12_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(12_u32)); + } } } @@ -239,11 +247,16 @@ fn call_in_if_else() { functions: vec![main_func, f1_func.clone(), f2_func.clone()], initial_witness: default_witness(), }, + default_runtimes(), FuzzerOptions::default(), ); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4_u32)), - None => panic!("Program failed to execute"), + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(4_u32)); + } } let arg_0_boolean = NumericArgument { index: 0, numeric_type: NumericType::Boolean }; @@ -272,10 +285,14 @@ fn call_in_if_else() { functions: vec![main_func, f1_func, f2_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(6_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(6_u32)); + } } } @@ -360,24 +377,28 @@ fn test_does_not_insert_too_many_instructions_with_function_calls() { }; // with max 100 instructions only second function should be executed let options = FuzzerOptions { max_instructions_num: 100, ..FuzzerOptions::default() }; - let result = fuzz_target(data.clone(), options); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1024_u32)); + let result = fuzz_target(data.clone(), default_runtimes(), options); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1024_u32)); } - None => panic!("Program failed to execute"), } // with max 1000 instructions both functions should be executed // and the result should be the output of the first function let options = FuzzerOptions { max_instructions_num: 1000, ..FuzzerOptions::default() }; - let result = fuzz_target(data.clone(), options); - match result { - Some(result) => { + let result = fuzz_target(data.clone(), default_runtimes(), options); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { assert_eq!( - result.get_return_values_acir()[0], + result.get_return_witnesses()[0], FieldElement::from(2_u32).pow(&FieldElement::from(200_u32)) // 2^200 ); } - None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs index d4738dbffcc..5601a1c23ee 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/hash_tests.rs @@ -9,7 +9,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::NumericType; use noir_ssa_fuzzer::typed_value::Type; @@ -41,16 +41,20 @@ fn smoke_test_blake2s_hash() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!( - result.get_return_values_acir()[0], - FieldElement::try_from_str( - "-9211429028062209127175291049466917975585300944217240748738694765619842249938" - ) - .unwrap() - ), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!( + result.get_return_witnesses()[0], + FieldElement::try_from_str( + "-9211429028062209127175291049466917975585300944217240748738694765619842249938" + ) + .unwrap() + ); + } } } @@ -81,16 +85,20 @@ fn smoke_test_blake3_hash() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!( - result.get_return_values_acir()[0], - FieldElement::try_from_str( - "11496696481601359239189947342432058980836600577383371976100559912527609453094" - ) - .unwrap() - ), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!( + result.get_return_witnesses()[0], + FieldElement::try_from_str( + "11496696481601359239189947342432058980836600577383371976100559912527609453094" + ) + .unwrap() + ); + } } } @@ -126,16 +134,20 @@ fn smoke_test_aes128_encrypt() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!( - result.get_return_values_acir()[0], - FieldElement::try_from_str( - "7228449286344697221705732525592563926191809635549234005020486075743434697058" - ) - .unwrap() - ), - None => panic!("Program failed to execute"), + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!( + result.get_return_witnesses()[0], + FieldElement::try_from_str( + "7228449286344697221705732525592563926191809635549234005020486075743434697058" + ) + .unwrap() + ); + } } } @@ -176,15 +188,17 @@ fn smoke_test_keccakf1600() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => { + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { assert_eq!( - result.get_return_values_acir()[0], + result.get_return_witnesses()[0], FieldElement::from(16929593379567477321_u64) ); } - None => panic!("Program failed to execute"), } } @@ -223,11 +237,13 @@ fn smoke_test_sha256_compression() { functions: vec![main_func], initial_witness: default_witness(), }; - let result = fuzz_target(fuzzer_data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(3205228454_u32)); + let result = fuzz_target(fuzzer_data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(3205228454_u32)); } - None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs index f305947c6f8..4e299f8cac0 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/loops.rs @@ -8,7 +8,7 @@ use crate::fuzz_target_lib::fuzz_target; use crate::fuzzer::FuzzerData; use crate::instruction::{Argument, Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; -use crate::tests::common::{default_input_types, default_witness}; +use crate::tests::common::{default_input_types, default_runtimes, default_witness}; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; @@ -58,12 +58,14 @@ fn test_simple_loop() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1024_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1024_u32)); } - None => panic!("Program failed to execute"), } } @@ -131,12 +133,14 @@ fn test_nested_loop() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(131072_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(131072_u32)); } - None => panic!("Program failed to execute"), } } @@ -206,12 +210,14 @@ fn test_loop_broken_with_jmp() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(4096_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(4096_u32)); } - None => panic!("Program failed to execute"), } } @@ -281,10 +287,14 @@ fn test_jmp_if_in_cycle() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(22_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(22_u32)); + } } let arg_0_boolean = NumericArgument { index: 0, numeric_type: NumericType::Boolean }; @@ -317,11 +327,13 @@ fn test_jmp_if_in_cycle() { }], initial_witness: default_witness(), }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(2048_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(2048_u32)); } - None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs index 1469b295da3..b2be26b387b 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/tests/witness.rs @@ -8,6 +8,7 @@ use crate::fuzzer::FuzzerData; use crate::initial_witness::{FieldRepresentation, WitnessValue, WitnessValueNumeric}; use crate::instruction::{Instruction, InstructionBlock, NumericArgument}; use crate::options::FuzzerOptions; +use crate::tests::common::default_runtimes; use acvm::FieldElement; use noir_ssa_fuzzer::typed_value::{NumericType, Type}; use std::sync::Arc; @@ -52,10 +53,14 @@ fn test_array_as_initial_witness() { initial_witness: vec![array_witness.clone(), index_witness_0], functions: vec![main_function.clone()], }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + } } let data = FuzzerData { @@ -63,10 +68,14 @@ fn test_array_as_initial_witness() { initial_witness: vec![array_witness, index_witness_1], functions: vec![main_function], }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => assert_eq!(result.get_return_values_acir()[0], FieldElement::from(2_u32)), - None => panic!("Program failed to execute"), + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(2_u32)); + } } } @@ -110,13 +119,15 @@ fn test_array_of_arrays_as_initial_witness() { initial_witness: vec![array_witness.clone(), index_witness_0], functions: vec![main_function.clone()], }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(1_u32)); - assert_eq!(result.get_return_values_acir()[1], FieldElement::from(2_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(1_u32)); + assert_eq!(result.get_return_witnesses()[1], FieldElement::from(2_u32)); } - None => panic!("Program failed to execute"), } let data = FuzzerData { @@ -124,12 +135,14 @@ fn test_array_of_arrays_as_initial_witness() { initial_witness: vec![array_witness, index_witness_1], functions: vec![main_function], }; - let result = fuzz_target(data, FuzzerOptions::default()); - match result { - Some(result) => { - assert_eq!(result.get_return_values_acir()[0], FieldElement::from(3_u32)); - assert_eq!(result.get_return_values_acir()[1], FieldElement::from(4_u32)); + let result = fuzz_target(data, default_runtimes(), FuzzerOptions::default()); + match result.get_return_witnesses().is_empty() { + true => { + panic!("Program failed to execute"); + } + false => { + assert_eq!(result.get_return_witnesses()[0], FieldElement::from(3_u32)); + assert_eq!(result.get_return_witnesses()[1], FieldElement::from(4_u32)); } - None => panic!("Program failed to execute"), } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs index 0208c4808ad..0e09ee66a6d 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs @@ -1,6 +1,4 @@ -#[cfg(feature = "redis-support")] pub(crate) mod redis; - use crate::fuzz_lib::fuzzer::FuzzerOutput; use base64::{Engine as _, engine::general_purpose}; @@ -8,59 +6,42 @@ use base64::{Engine as _, engine::general_purpose}; // TODO(sn): legacy for https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg/security/ssa_fuzzer_programs_proving // "program" field -> "acir_program"; witness_stack -> acir_witness_stack pub(crate) fn fuzzer_output_to_json(fuzzer_output: FuzzerOutput) -> String { - let acir_program = &fuzzer_output.acir_program; - let acir_program_json = serde_json::to_string(acir_program).unwrap(); - let mut acir_program_json: serde_json::Value = - serde_json::from_str(&acir_program_json).unwrap(); - - let brillig_program = &fuzzer_output.brillig_program; - let brillig_program_json = serde_json::to_string(brillig_program).unwrap(); - let mut brillig_program_json: serde_json::Value = - serde_json::from_str(&brillig_program_json).unwrap(); + let program = &fuzzer_output.program; + let program_json = serde_json::to_string(program).unwrap(); + let mut program_json: serde_json::Value = serde_json::from_str(&program_json).unwrap(); // Noir program compiles into json, storing bytecode of the program // to "bytecode" field, but default `CompiledProgram` serializer // serializes it to "program" field. - if let Some(acir_program_value) = acir_program_json.get("program").cloned() { - acir_program_json.as_object_mut().unwrap().remove("program"); - acir_program_json - .as_object_mut() - .unwrap() - .insert("bytecode".to_string(), acir_program_value); + if let Some(acir_program_value) = program_json.get("program").cloned() { + program_json.as_object_mut().unwrap().remove("program"); + program_json.as_object_mut().unwrap().insert("bytecode".to_string(), acir_program_value); } - if let Some(brillig_program_value) = brillig_program_json.get("program").cloned() { - brillig_program_json.as_object_mut().unwrap().remove("program"); - brillig_program_json - .as_object_mut() - .unwrap() - .insert("bytecode".to_string(), brillig_program_value); - } - let witness_map_bytes = fuzzer_output.witness_stack_acir.serialize().unwrap(); + + let witness_map_bytes = fuzzer_output.witness_stack.serialize().unwrap(); let witness_map_b64 = general_purpose::STANDARD.encode(&witness_map_bytes); - let brillig_inputs = fuzzer_output.get_input_values_brillig(); - let brillig_outputs = fuzzer_output.get_return_values_brillig(); + let inputs = fuzzer_output.get_input_witnesses(); + let outputs = fuzzer_output.get_return_witnesses(); let mut output_json = serde_json::Map::new(); - output_json.insert("program".to_string(), acir_program_json.clone()); - output_json.insert("brillig_program".to_string(), brillig_program_json.clone()); + output_json.insert("program".to_string(), program_json.clone()); output_json.insert( - "brillig_inputs".to_string(), + "inputs".to_string(), serde_json::Value::Array( - brillig_inputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), + inputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), ), ); output_json.insert( - "brillig_outputs".to_string(), + "outputs".to_string(), serde_json::Value::Array( - brillig_outputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), + outputs.iter().map(|x| serde_json::Value::String(x.to_string())).collect(), ), ); output_json.insert("witness_map_b64".to_string(), serde_json::Value::String(witness_map_b64)); serde_json::to_string(&output_json).unwrap() } -#[cfg(feature = "redis-support")] pub(crate) fn push_fuzzer_output_to_redis_queue( queue_name: &str, test_id: String, diff --git a/tooling/ssa_fuzzer/src/builder.rs b/tooling/ssa_fuzzer/src/builder.rs index 5bebe405344..3ee3eb5a3eb 100644 --- a/tooling/ssa_fuzzer/src/builder.rs +++ b/tooling/ssa_fuzzer/src/builder.rs @@ -34,6 +34,7 @@ pub type InstructionWithOneArg = fn(&mut FuzzerBuilder, TypedValue) -> TypedValu /// Contains a FunctionBuilder and tracks the current numeric type being used pub struct FuzzerBuilder { pub(crate) builder: FunctionBuilder, + pub(crate) runtime: RuntimeType, } impl FuzzerBuilder { @@ -43,7 +44,7 @@ impl FuzzerBuilder { let mut builder = FunctionBuilder::new("main".into(), main_id); builder.set_runtime(RuntimeType::Acir(FrontendInlineType::default())); builder.simplify = simplifying_enabled; - Self { builder } + Self { builder, runtime: RuntimeType::Acir(FrontendInlineType::default()) } } /// Creates a new FuzzerBuilder in Brillig context @@ -52,7 +53,15 @@ impl FuzzerBuilder { let mut builder = FunctionBuilder::new("main".into(), main_id); builder.set_runtime(RuntimeType::Brillig(FrontendInlineType::default())); builder.simplify = simplifying_enabled; - Self { builder } + Self { builder, runtime: RuntimeType::Brillig(FrontendInlineType::default()) } + } + + pub fn new_by_runtime(runtime: RuntimeType, simplifying_enabled: bool) -> Self { + let main_id: Id = Id::new(0); + let mut builder = FunctionBuilder::new("main".into(), main_id); + builder.set_runtime(runtime); + builder.simplify = simplifying_enabled; + Self { builder, runtime } } /// Compiles the built function into a CompiledProgram, to run it with nargo execute @@ -332,15 +341,18 @@ impl FuzzerBuilder { self.builder.insert_store(memory_addr.value_id, value.value_id); } - /// Creates a new ACIR function with the given name and id with inline type InlineType::Inline - pub fn new_acir_function(&mut self, name: String, function_id: Id) { + /// Creates a new function with the given name and id with inline type InlineType::Inline + /// Sets the same runtime as the builder + pub fn new_function(&mut self, name: String, function_id: Id) { // maybe use different inline type - self.builder.new_function(name, function_id, InlineType::Inline); - } - - /// Creates a new Brillig function with the given name and id with inline type InlineType::Inline - pub fn new_brillig_function(&mut self, name: String, function_id: Id) { - self.builder.new_brillig_function(name, function_id, InlineType::Inline); + match self.runtime { + RuntimeType::Acir(inline_type) => { + self.builder.new_function(name, function_id, inline_type); + } + RuntimeType::Brillig(inline_type) => { + self.builder.new_brillig_function(name, function_id, inline_type); + } + } } /// Inserts an import function with the given function id diff --git a/tooling/ssa_fuzzer/src/runner.rs b/tooling/ssa_fuzzer/src/runner.rs index 7c451cdec7c..379bd28740c 100644 --- a/tooling/ssa_fuzzer/src/runner.rs +++ b/tooling/ssa_fuzzer/src/runner.rs @@ -5,7 +5,7 @@ use acvm::{ native_types::{Witness, WitnessMap, WitnessStack}, }, }; -use noir_ssa_executor::runner::execute_single; +use noir_ssa_executor::{runner::SsaExecutionError, runner::execute_single}; use std::collections::BTreeSet; #[derive(Debug)] @@ -17,6 +17,13 @@ pub enum CompareResults { BrilligFailed(String, WitnessStack), } +pub fn execute( + program: &Program, + initial_witness: WitnessMap, +) -> Result, SsaExecutionError> { + execute_single(program, initial_witness) +} + /// High level function to execute the given ACIR and Brillig programs with the given initial witness /// It returns a tuple with a boolean indicating if the programs succeeded, /// and the results of the ACIR and Brillig programs From 9a05d23119ac797c86c45cbf620c4c27c1f74600 Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Mon, 8 Sep 2025 12:03:10 +0000 Subject: [PATCH 4/6] forgor cargo --- Cargo.lock | 1 + tooling/ssa_fuzzer/fuzzer/Cargo.toml | 14 +++++--------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 179b37ac389..fffeb41b2dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5633,6 +5633,7 @@ dependencies = [ "noir_ssa_fuzzer", "noirc_driver", "noirc_evaluator", + "noirc_frontend", "p256", "rand 0.8.5", "redis", diff --git a/tooling/ssa_fuzzer/fuzzer/Cargo.toml b/tooling/ssa_fuzzer/fuzzer/Cargo.toml index 4207f38623c..488baf8c574 100644 --- a/tooling/ssa_fuzzer/fuzzer/Cargo.toml +++ b/tooling/ssa_fuzzer/fuzzer/Cargo.toml @@ -11,14 +11,11 @@ cargo-fuzz = true [lints] workspace = true -[features] -default = [] -redis-support = ["dep:redis", "dep:lazy_static"] - [dependencies] libfuzzer-sys = { version = "0.4.0", features = ["arbitrary-derive"] } noirc_evaluator.workspace = true noirc_driver.workspace = true +noirc_frontend.workspace = true acvm.workspace = true noir_ssa_executor.workspace = true log.workspace = true @@ -29,8 +26,8 @@ serde.workspace = true serde_json.workspace = true base64.workspace = true sha1 = "0.10.6" -redis = { version = "0.26", optional = true } -lazy_static = { version = "1.4", optional = true } +redis = { version = "0.26"} +lazy_static = { version = "1.4" } strum_macros = "0.24" strum = "0.24" sha2.workspace = true @@ -46,11 +43,10 @@ path = "src/acir_vs_brillig.rs" test = false doc = false bench = false -required-features = ["redis-support"] [[bin]] -name = "ssa_fuzzer" -path = "src/fuzzer.rs" +name = "brillig" +path = "src/brillig.rs" test = false doc = false bench = false From 6c536c66470cd56d9238d5b36fd6f778218f7590 Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Mon, 8 Sep 2025 12:33:19 +0000 Subject: [PATCH 5/6] a --- .../fuzzer/src/fuzz_lib/block_context.rs | 6 ++---- .../fuzzer/src/fuzz_lib/function_context.rs | 6 ++---- .../ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs | 21 +++++++++++-------- tooling/ssa_fuzzer/src/builder.rs | 1 - 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs index d313442c26a..2d117e7e16b 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/block_context.rs @@ -704,11 +704,9 @@ impl BlockContext { let is_infinite = builder.insert_constant(point.is_infinite, NumericType::Boolean); let point = if point.derive_from_scalar_mul { - let point = builder.base_scalar_mul(scalar.clone(), is_infinite.clone()); - point + builder.base_scalar_mul(scalar.clone(), is_infinite.clone()) } else { - let point = builder.create_point_from_scalar(scalar.clone(), is_infinite.clone()); - point + builder.create_point_from_scalar(scalar.clone(), is_infinite.clone()) }; Some(point) } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs index 37ff6cf5aa9..b9ca04731b4 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/function_context.rs @@ -219,8 +219,7 @@ impl<'a> FuzzerFunctionContext<'a> { } /// Inserts a new SSA block into builder and returns its id fn insert_ssa_block(&mut self) -> BasicBlockId { - let block_id = self.builder.insert_block(); - block_id + self.builder.insert_block() } /// Inserts a new constant into builder and returns its value @@ -229,8 +228,7 @@ impl<'a> FuzzerFunctionContext<'a> { value: impl Into + Clone, type_: NumericType, ) -> TypedValue { - let typed_value = self.builder.insert_constant(value.clone(), type_); - typed_value + self.builder.insert_constant(value.clone(), type_) } /// Inserts a new jmp instruction into builder diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs index a2ad8f270cd..aeca6cc20c8 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs @@ -22,7 +22,6 @@ use super::{ }; use acvm::FieldElement; use acvm::acir::native_types::{WitnessMap, WitnessStack}; -use noir_ssa_executor::runner::execute_single; use noir_ssa_fuzzer::{runner::execute, typed_value::Type}; use noirc_driver::CompiledProgram; use noirc_evaluator::ssa::ir::function::RuntimeType; @@ -75,6 +74,9 @@ impl FuzzerOutput { return vec![]; } let return_witnesses = &self.program.as_ref().unwrap().program.functions[0].return_values.0; + if return_witnesses.is_empty() { + return vec![]; + } let max_return_witness_index = return_witnesses.iter().max().unwrap(); let witness_vec = &self.witness_stack.peek().unwrap().witness; @@ -85,6 +87,7 @@ impl FuzzerOutput { return_witnesses.iter().map(|witness| witness_vec[witness]).collect() } + #[allow(dead_code)] // TODO(sn): used in fuzzer_output_to_json pub(crate) fn get_input_witnesses(&self) -> Vec { // program failed to compile if self.program.is_none() { @@ -98,22 +101,22 @@ impl FuzzerOutput { pub(crate) fn compare_results(&self, other: &Self) -> CompareResults { match (self.is_program_compiled(), other.is_program_compiled()) { - (true, true) => return CompareResults::BothFailed, - (true, false) => return CompareResults::LeftCompilationFailed, - (false, true) => return CompareResults::RightCompilationFailed, + (true, true) => CompareResults::BothFailed, + (true, false) => CompareResults::LeftCompilationFailed, + (false, true) => CompareResults::RightCompilationFailed, (false, false) => { // both programs compiled successfully let left_return_witnesses = self.get_return_witnesses(); let right_return_witnesses = other.get_return_witnesses(); match (left_return_witnesses.is_empty(), right_return_witnesses.is_empty()) { - (true, true) => return CompareResults::BothFailed, - (true, false) => return CompareResults::LeftExecutionFailed, - (false, true) => return CompareResults::RightExecutionFailed, + (true, true) => CompareResults::BothFailed, + (true, false) => CompareResults::LeftExecutionFailed, + (false, true) => CompareResults::RightExecutionFailed, (false, false) => { if left_return_witnesses != right_return_witnesses { return CompareResults::Disagree( - left_return_witnesses, - right_return_witnesses, + left_return_witnesses.clone(), + right_return_witnesses.clone(), ); } CompareResults::Agree(left_return_witnesses) diff --git a/tooling/ssa_fuzzer/src/builder.rs b/tooling/ssa_fuzzer/src/builder.rs index 3ee3eb5a3eb..856aed38897 100644 --- a/tooling/ssa_fuzzer/src/builder.rs +++ b/tooling/ssa_fuzzer/src/builder.rs @@ -10,7 +10,6 @@ use noirc_evaluator::ssa::ir::instruction::BinaryOp; use noirc_evaluator::ssa::ir::map::Id; use noirc_evaluator::ssa::ir::types::Type as SsaType; use noirc_evaluator::ssa::ir::value::Value; -use noirc_frontend::monomorphization::ast::InlineType; use noirc_frontend::monomorphization::ast::InlineType as FrontendInlineType; use std::panic::AssertUnwindSafe; use std::sync::Arc; From fb33d2d5bb1f0ff0c38a59a998f4ba7505b42bf3 Mon Sep 17 00:00:00 2001 From: jewelofchaos9 Date: Wed, 10 Sep 2025 08:00:33 +0000 Subject: [PATCH 6/6] kesha + clean --- tooling/ssa_fuzzer/fuzzer/src/brillig.rs | 8 +++++++- tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs | 6 ++++++ tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs | 4 ++-- tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs | 2 -- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tooling/ssa_fuzzer/fuzzer/src/brillig.rs b/tooling/ssa_fuzzer/fuzzer/src/brillig.rs index 2869d1b1a2d..8d821d0fa0c 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/brillig.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/brillig.rs @@ -46,8 +46,14 @@ libfuzzer_sys::fuzz_target!(|data: &[u8]| -> Corpus { } // You can disable some instructions with bugs that are not fixed yet - let instruction_options = InstructionOptions { ..InstructionOptions::default() }; let modes = vec![FuzzerMode::NonConstant]; + let instruction_options = InstructionOptions { + array_get_enabled: false, + array_set_enabled: false, + ecdsa_secp256k1_enabled: false, + ecdsa_secp256r1_enabled: false, + ..InstructionOptions::default() + }; let fuzzer_command_options = FuzzerCommandOptions { loops_enabled: false, ..FuzzerCommandOptions::default() }; let options = FuzzerOptions { diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs index 18ba420275e..eb7abb96efb 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzz_target_lib.rs @@ -60,6 +60,11 @@ pub(crate) fn fuzz_target( match result { CompareResults::Agree(_witness_stack) => { // thats fine + log::debug!( + "Fuzzer runtimes {} and {} agree on the return values", + runtimes[i], + runtimes[j] + ); } CompareResults::Disagree(witness_stack_1, witness_stack_2) => { panic!( @@ -97,6 +102,7 @@ pub(crate) fn fuzz_target( } CompareResults::BothFailed => { // thats fine + log::debug!("Fuzzer runtimes {} and {} both failed", runtimes[i], runtimes[j]); } } } diff --git a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs index aeca6cc20c8..3ad3e8f7a96 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/fuzz_lib/fuzzer.rs @@ -101,10 +101,10 @@ impl FuzzerOutput { pub(crate) fn compare_results(&self, other: &Self) -> CompareResults { match (self.is_program_compiled(), other.is_program_compiled()) { - (true, true) => CompareResults::BothFailed, + (false, false) => CompareResults::BothFailed, (true, false) => CompareResults::LeftCompilationFailed, (false, true) => CompareResults::RightCompilationFailed, - (false, false) => { + (true, true) => { // both programs compiled successfully let left_return_witnesses = self.get_return_witnesses(); let right_return_witnesses = other.get_return_witnesses(); diff --git a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs index 0e09ee66a6d..8c6e3bbaaf2 100644 --- a/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs +++ b/tooling/ssa_fuzzer/fuzzer/src/utils/mod.rs @@ -3,8 +3,6 @@ use crate::fuzz_lib::fuzzer::FuzzerOutput; use base64::{Engine as _, engine::general_purpose}; // TODO(sn): change to impl Serialize for FuzzerOutput with brillig inputs and outputs -// TODO(sn): legacy for https://github.com/AztecProtocol/aztec-packages/tree/next/barretenberg/security/ssa_fuzzer_programs_proving -// "program" field -> "acir_program"; witness_stack -> acir_witness_stack pub(crate) fn fuzzer_output_to_json(fuzzer_output: FuzzerOutput) -> String { let program = &fuzzer_output.program; let program_json = serde_json::to_string(program).unwrap();