Skip to content

Commit

Permalink
fix: Refactor constraints in scalar mul to use the high limb (#2161)
Browse files Browse the repository at this point in the history
See noir-lang/noir#2588 for more details

# Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if
the PR is ready to merge.
- [ ] If the pull request requires a cryptography review (e.g.
cryptographic algorithm implementations) I have added the 'crypto' tag.
- [ ] I have reviewed my diff in github, line by line and removed
unexpected formatting changes, testing logs, or commented-out code.
- [ ] Every change is related to the PR description.
- [ ] I have
[linked](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)
this pull request to relevant issues (if any exist).
  • Loading branch information
kevaundray authored Sep 12, 2023
1 parent c743cf8 commit 1d0e25d
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -1,17 +1,42 @@
#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);

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
Original file line number Diff line number Diff line change
@@ -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 <cstdint>
#include <gtest/gtest.h>
#include <vector>

namespace acir_format::tests {
using group_ct = proof_system::plonk::stdlib::group<Builder>;

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<uint32_t>(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<uint32_t>(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

0 comments on commit 1d0e25d

Please sign in to comment.