From c3bcd9af5af89e4f6373b1c5f4ecd790b753df01 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 8 Sep 2023 22:16:43 +0000 Subject: [PATCH 1/3] refactor method to use the high limb --- .../dsl/acir_format/fixed_base_scalar_mul.cpp | 25 +++- .../fixed_base_scalar_mul.test.cpp | 134 ++++++++++++++++++ 2 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.test.cpp diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp index d54f8a33c986..211377345f24 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp @@ -1,17 +1,34 @@ #include "fixed_base_scalar_mul.hpp" +#include "barretenberg/dsl/types.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/proof_system/arithmetization/gate_data.hpp" namespace acir_format { void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& input) { + // Computes low * G + high * 2^128 * G + // + // Low and high need to be less than 2^128 field_ct low_as_field = field_ct::from_witness_index(&builder, input.low); field_ct high_as_field = field_ct::from_witness_index(&builder, input.high); - (void)high_as_field; - auto public_key = group_ct::fixed_base_scalar_mul_g1<254>(low_as_field); - builder.assert_equal(public_key.x.witness_index, input.pub_key_x); - builder.assert_equal(public_key.y.witness_index, input.pub_key_y); + low_as_field.create_range_constraint(128); + high_as_field.create_range_constraint(128); + + field_ct pow128 = field_ct(2).pow(128); + + field_ct high_times_pow128 = high_as_field * pow128; + + auto low_point = group_ct::fixed_base_scalar_mul_g1<128>(low_as_field); + auto high_point = group_ct::fixed_base_scalar_mul_g1<254>(high_times_pow128); + + auto result = low_point + high_point; + + builder.assert_equal(result.x.witness_index, input.pub_key_x); + builder.assert_equal(result.y.witness_index, input.pub_key_y); } } // namespace acir_format diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.test.cpp new file mode 100644 index 000000000000..3bda4b65befd --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.test.cpp @@ -0,0 +1,134 @@ +#include "acir_format.hpp" +#include "barretenberg/crypto/ecdsa/ecdsa.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/plonk/proof_system/types/proof.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" +#include "fixed_base_scalar_mul.hpp" + +#include +#include +#include + +namespace acir_format::tests { +using group_ct = proof_system::plonk::stdlib::group; + +size_t generate_scalar_mul_constraints(FixedBaseScalarMul& scalar_mul_constraint, + WitnessVector& witness_values, + uint256_t low_value, + uint256_t high_value, + grumpkin::g1::affine_element expected) +{ + uint32_t offset = 1; + + uint32_t low_index = offset; + witness_values.emplace_back(low_value); + offset += 1; + + uint32_t high_index = offset; + witness_values.emplace_back(high_value); + offset += 1; + + uint32_t pub_key_x_index = offset; + witness_values.emplace_back(expected.x); + offset += 1; + + uint32_t pub_key_y_index = offset; + witness_values.emplace_back(expected.y); + offset += 1; + + scalar_mul_constraint = FixedBaseScalarMul{ + .low = low_index, + .high = high_index, + .pub_key_x = pub_key_x_index, + .pub_key_y = pub_key_y_index, + }; + + return offset; +} + +size_t generate_fixed_base_scalar_mul_fixtures(FixedBaseScalarMul& scalar_mul_constraint, + WitnessVector& witness_values, + grumpkin::fr low, + grumpkin::fr high) +{ + + auto two_pow_128 = grumpkin::fr(2).pow(128); + grumpkin::g1::element expected_projective = (grumpkin::g1::one * low) + grumpkin::g1::one * (high * two_pow_128); + grumpkin::g1::affine_element expected = expected_projective.normalize(); + return generate_scalar_mul_constraints(scalar_mul_constraint, witness_values, low, high, expected); +} + +TEST(FixedBaseScalarMul, TestSimpleScalarMul) +{ + FixedBaseScalarMul scalar_mul_constraint; + WitnessVector witness_values; + auto low = grumpkin::fr(1); + auto high = grumpkin::fr(2); + size_t num_variables = generate_fixed_base_scalar_mul_fixtures(scalar_mul_constraint, witness_values, low, high); + acir_format constraint_system{ + .varnum = static_cast(num_variables), + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .pedersen_constraints = {}, + .hash_to_field_constraints = {}, + .fixed_base_scalar_mul_constraints = { scalar_mul_constraint }, + .recursion_constraints = {}, + .constraints = {}, + .block_constraints = {}, + }; + + auto builder = create_circuit_with_witness(constraint_system, witness_values); + + auto composer = Composer(); + auto prover = composer.create_prover(builder); + + auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(builder); + EXPECT_EQ(verifier.verify_proof(proof), true); +} +TEST(FixedBaseScalarMul, TestLimbLargerThan2Pow128) +{ + FixedBaseScalarMul scalar_mul_constraint; + WitnessVector witness_values; + grumpkin::fr low = grumpkin::fr(2).pow(129); + grumpkin::fr high = 1; + size_t num_variables = generate_fixed_base_scalar_mul_fixtures(scalar_mul_constraint, witness_values, low, high); + acir_format constraint_system{ + .varnum = static_cast(num_variables), + .public_inputs = {}, + .logic_constraints = {}, + .range_constraints = {}, + .sha256_constraints = {}, + .schnorr_constraints = {}, + .ecdsa_k1_constraints = {}, + .ecdsa_r1_constraints = {}, + .blake2s_constraints = {}, + .keccak_constraints = {}, + .keccak_var_constraints = {}, + .pedersen_constraints = {}, + .hash_to_field_constraints = {}, + .fixed_base_scalar_mul_constraints = { scalar_mul_constraint }, + .recursion_constraints = {}, + .constraints = {}, + .block_constraints = {}, + }; + + auto builder = create_circuit_with_witness(constraint_system, witness_values); + + auto composer = Composer(); + auto prover = composer.create_prover(builder); + + auto proof = prover.construct_proof(); + auto verifier = composer.create_verifier(builder); + EXPECT_EQ(verifier.verify_proof(proof), false); +} + +} // namespace acir_format::tests From 34911accf60e20b229547c5d19b3df18af9605f6 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 8 Sep 2023 22:34:31 +0000 Subject: [PATCH 2/3] unsecure out of circuit version --- .../dsl/acir_format/fixed_base_scalar_mul.cpp | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp index 211377345f24..20c211194c7d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp @@ -15,20 +15,25 @@ void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& in field_ct low_as_field = field_ct::from_witness_index(&builder, input.low); field_ct high_as_field = field_ct::from_witness_index(&builder, input.high); - low_as_field.create_range_constraint(128); - high_as_field.create_range_constraint(128); - - field_ct pow128 = field_ct(2).pow(128); - - field_ct high_times_pow128 = high_as_field * pow128; - - auto low_point = group_ct::fixed_base_scalar_mul_g1<128>(low_as_field); - auto high_point = group_ct::fixed_base_scalar_mul_g1<254>(high_times_pow128); - - auto result = low_point + high_point; - - builder.assert_equal(result.x.witness_index, input.pub_key_x); - builder.assert_equal(result.y.witness_index, input.pub_key_y); + auto low_value = grumpkin::fr(low_as_field.get_value()); + auto high_value = grumpkin::fr(high_as_field.get_value()); + auto pow_128 = grumpkin::fr(2).pow(128); + + grumpkin::g1::element result = grumpkin::g1::one * low_value + grumpkin::g1::one * (high_value * pow_128); + grumpkin::g1::affine_element result_affine = result.normalize(); + + auto x_var = builder.add_variable(result_affine.x); + auto y_var = builder.add_variable(result_affine.y); + builder.create_add_gate({ x_var, + y_var, + x_var, + barretenberg::fr::zero(), + barretenberg::fr::zero(), + barretenberg::fr::zero(), + barretenberg::fr::zero() }); + + builder.assert_equal(x_var, input.pub_key_x); + builder.assert_equal(y_var, input.pub_key_y); } } // namespace acir_format From 1ef3cb19e79afc69ec1d4e17f649dfd704885d4c Mon Sep 17 00:00:00 2001 From: kevaundray Date: Fri, 8 Sep 2023 22:55:11 +0000 Subject: [PATCH 3/3] add range constraint to limbs --- .../src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp index 20c211194c7d..68895c7c6e2b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/dsl/acir_format/fixed_base_scalar_mul.cpp @@ -15,6 +15,9 @@ void create_fixed_base_constraint(Builder& builder, const FixedBaseScalarMul& in field_ct low_as_field = field_ct::from_witness_index(&builder, input.low); field_ct high_as_field = field_ct::from_witness_index(&builder, input.high); + low_as_field.create_range_constraint(128); + high_as_field.create_range_constraint(128); + auto low_value = grumpkin::fr(low_as_field.get_value()); auto high_value = grumpkin::fr(high_as_field.get_value()); auto pow_128 = grumpkin::fr(2).pow(128);