From 281b0ce2bdb34df82fef2f2b99ff20603021d178 Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 18 Nov 2024 18:13:54 +0000 Subject: [PATCH 1/3] feat: simplify constant MSM calls in SSA --- .../src/embedded_curve_ops.rs | 1 - .../src/ssa/ir/instruction/call.rs | 4 +- .../src/ssa/ir/instruction/call/blackbox.rs | 54 +++++++++++++++++++ .../Nargo.toml | 6 +++ .../Prover.toml | 3 ++ .../src/main.nr | 12 +++++ 6 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml create mode 100644 test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml create mode 100644 test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr diff --git a/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs index 35cc68051d7..a02711fda1e 100644 --- a/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs +++ b/acvm-repo/bn254_blackbox_solver/src/embedded_curve_ops.rs @@ -16,7 +16,6 @@ pub fn multi_scalar_mul( scalars_hi: &[FieldElement], ) -> Result<(FieldElement, FieldElement, FieldElement), BlackBoxResolutionError> { if points.len() != 3 * scalars_lo.len() || scalars_lo.len() != scalars_hi.len() { - dbg!(&points.len(), &scalars_lo.len(), &scalars_hi.len()); return Err(BlackBoxResolutionError::Failed( BlackBoxFunc::MultiScalarMul, "Points and scalars must have the same length".to_string(), diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs index 5f0626b7ee8..e1e967b9a43 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call.rs @@ -572,7 +572,9 @@ fn simplify_black_box_func( acvm::blackbox_solver::ecdsa_secp256r1_verify, ), - BlackBoxFunc::MultiScalarMul => SimplifyResult::None, + BlackBoxFunc::MultiScalarMul => { + blackbox::simplify_msm(dfg, solver, arguments, block, call_stack) + } BlackBoxFunc::EmbeddedCurveAdd => { blackbox::simplify_ec_add(dfg, solver, arguments, block, call_stack) } diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs index 75405a87181..d5dcc94007a 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs @@ -63,6 +63,60 @@ pub(super) fn simplify_ec_add( } } +pub(super) fn simplify_msm( + dfg: &mut DataFlowGraph, + solver: impl BlackBoxFunctionSolver, + arguments: &[ValueId], + block: BasicBlockId, + call_stack: &CallStack, +) -> SimplifyResult { + // TODO: Handle MSMs where a subset of the terms are constant. + match (dfg.get_array_constant(arguments[0]), dfg.get_array_constant(arguments[1])) { + (Some((points, _)), Some((scalars, _))) => { + let points: Vec = points + .into_iter() + .map(|id| { + dfg.get_numeric_constant(id) + .expect("value id from array should point at constant") + }) + .collect(); + + let scalars = scalars.into_iter().map(|id| { + dfg.get_numeric_constant(id).expect("value id from array should point at constant") + }); + + let mut scalars_lo = Vec::new(); + let mut scalars_hi = Vec::new(); + for (i, scalar) in scalars.enumerate() { + if i % 2 == 0 { + scalars_lo.push(scalar); + } else { + scalars_hi.push(scalar); + } + } + + let Ok((result_x, result_y, result_is_infinity)) = + solver.multi_scalar_mul(&points, &scalars_lo, &scalars_hi) + else { + return SimplifyResult::None; + }; + + let result_x = dfg.make_constant(result_x, Type::field()); + let result_y = dfg.make_constant(result_y, Type::field()); + let result_is_infinity = dfg.make_constant(result_is_infinity, Type::bool()); + + let elements = im::vector![result_x, result_y, result_is_infinity]; + let typ = Type::Array(Arc::new(vec![Type::field()]), 3); + let instruction = Instruction::MakeArray { elements, typ }; + let result_array = + dfg.insert_instruction_and_results(instruction, block, None, call_stack.clone()); + + SimplifyResult::SimplifiedTo(result_array.first()) + } + _ => SimplifyResult::None, + } +} + pub(super) fn simplify_poseidon2_permutation( dfg: &mut DataFlowGraph, solver: impl BlackBoxFunctionSolver, diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml new file mode 100644 index 00000000000..9c9bd8de04a --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Nargo.toml @@ -0,0 +1,6 @@ +[package] +name = "embedded_curve_msm_simplification" +type = "bin" +authors = [""] + +[dependencies] diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml new file mode 100644 index 00000000000..7113b9cd038 --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml @@ -0,0 +1,3 @@ +priv_key = "1" +pub_x = "0x0000000000000000000000000000000000000000000000000000000000000001" +pub_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" \ No newline at end of file diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr b/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr new file mode 100644 index 00000000000..e5aaa0f4d15 --- /dev/null +++ b/test_programs/compile_success_empty/embedded_curve_msm_simplification/src/main.nr @@ -0,0 +1,12 @@ +fn main() { + let pub_x = 0x0000000000000000000000000000000000000000000000000000000000000001; + let pub_y = 0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c; + + let g1_y = 17631683881184975370165255887551781615748388533673675138860; + let g1 = std::embedded_curve_ops::EmbeddedCurvePoint { x: 1, y: g1_y, is_infinite: false }; + let scalar = std::embedded_curve_ops::EmbeddedCurveScalar { lo: 1, hi: 0 }; + // Test that multi_scalar_mul correctly derives the public key + let res = std::embedded_curve_ops::multi_scalar_mul([g1], [scalar]); + assert(res.x == pub_x); + assert(res.y == pub_y); +} From 8c0f0b1defd013a9e33e24f3fb285bf7f7cfdbfa Mon Sep 17 00:00:00 2001 From: Tom French Date: Mon, 18 Nov 2024 19:01:29 +0000 Subject: [PATCH 2/3] fix: handle non-constant terms of array constants --- .../src/ssa/ir/instruction/call/blackbox.rs | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs b/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs index d5dcc94007a..4f2a31e2fb0 100644 --- a/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs +++ b/compiler/noirc_evaluator/src/ssa/ir/instruction/call/blackbox.rs @@ -73,21 +73,25 @@ pub(super) fn simplify_msm( // TODO: Handle MSMs where a subset of the terms are constant. match (dfg.get_array_constant(arguments[0]), dfg.get_array_constant(arguments[1])) { (Some((points, _)), Some((scalars, _))) => { - let points: Vec = points + let Some(points) = points .into_iter() - .map(|id| { - dfg.get_numeric_constant(id) - .expect("value id from array should point at constant") - }) - .collect(); + .map(|id| dfg.get_numeric_constant(id)) + .collect::>>() + else { + return SimplifyResult::None; + }; - let scalars = scalars.into_iter().map(|id| { - dfg.get_numeric_constant(id).expect("value id from array should point at constant") - }); + let Some(scalars) = scalars + .into_iter() + .map(|id| dfg.get_numeric_constant(id)) + .collect::>>() + else { + return SimplifyResult::None; + }; let mut scalars_lo = Vec::new(); let mut scalars_hi = Vec::new(); - for (i, scalar) in scalars.enumerate() { + for (i, scalar) in scalars.into_iter().enumerate() { if i % 2 == 0 { scalars_lo.push(scalar); } else { From a3a29a064b6fbb1c2bf25e46f6966246b6123852 Mon Sep 17 00:00:00 2001 From: Tom French <15848336+TomAFrench@users.noreply.github.com> Date: Mon, 18 Nov 2024 19:06:59 +0000 Subject: [PATCH 3/3] Delete test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml --- .../embedded_curve_msm_simplification/Prover.toml | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml diff --git a/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml b/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml deleted file mode 100644 index 7113b9cd038..00000000000 --- a/test_programs/compile_success_empty/embedded_curve_msm_simplification/Prover.toml +++ /dev/null @@ -1,3 +0,0 @@ -priv_key = "1" -pub_x = "0x0000000000000000000000000000000000000000000000000000000000000001" -pub_y = "0x0000000000000002cf135e7506a45d632d270d45f1181294833fc48d823f272c" \ No newline at end of file