Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 27 additions & 26 deletions barretenberg/cpp/pil/vm2/sha256.pil
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ namespace sha256;
// We perform a compression operation if we are not at a latched row, or there is not an err
pol commit perform_round;
perform_round = (1 - LATCH_CONDITION) * SEL_NO_ERR;
pol LAST = SEL_NO_ERR * latch;
pol commit last;
last = SEL_NO_ERR * latch;

// Counter
pol NUM_ROUNDS = 64;
Expand Down Expand Up @@ -494,84 +495,84 @@ namespace sha256;

// TODO: These constraints could be better - we might have to reverse the order of the rounds
pol OUT_A = a + init_a;
LAST * (OUT_A - (output_a_lhs * 2**32 + output_a_rhs)) = 0;
last * (OUT_A - (output_a_lhs * 2**32 + output_a_rhs)) = 0;
pol OUT_B = b + init_b;
LAST * (OUT_B - (output_b_lhs * 2**32 + output_b_rhs)) = 0;
last * (OUT_B - (output_b_lhs * 2**32 + output_b_rhs)) = 0;
pol OUT_C = c + init_c;
LAST * (OUT_C - (output_c_lhs * 2**32 + output_c_rhs)) = 0;
last * (OUT_C - (output_c_lhs * 2**32 + output_c_rhs)) = 0;
pol OUT_D = d + init_d;
LAST * (OUT_D - (output_d_lhs * 2**32 + output_d_rhs)) = 0;
last * (OUT_D - (output_d_lhs * 2**32 + output_d_rhs)) = 0;
pol OUT_E = e + init_e;
LAST * (OUT_E - (output_e_lhs * 2**32 + output_e_rhs)) = 0;
last * (OUT_E - (output_e_lhs * 2**32 + output_e_rhs)) = 0;
pol OUT_F = f + init_f;
LAST * (OUT_F - (output_f_lhs * 2**32 + output_f_rhs)) = 0;
last * (OUT_F - (output_f_lhs * 2**32 + output_f_rhs)) = 0;
pol OUT_G = g + init_g;
LAST * (OUT_G - (output_g_lhs * 2**32 + output_g_rhs)) = 0;
last * (OUT_G - (output_g_lhs * 2**32 + output_g_rhs)) = 0;
pol OUT_H = h + init_h;
LAST * (OUT_H - (output_h_lhs * 2**32 + output_h_rhs)) = 0;
last * (OUT_H - (output_h_lhs * 2**32 + output_h_rhs)) = 0;

// Check Modulo Add Operation
// Check Modulo Add Operation for final outputs
#[RANGE_COMP_A_LHS]
perform_round { two_pow_32, output_a_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_a_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_A_RHS]
perform_round { two_pow_32, output_a_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_a_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_B_LHS]
perform_round { two_pow_32, output_b_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_b_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_B_RHS]
perform_round { two_pow_32, output_b_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_b_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_C_LHS]
perform_round { two_pow_32, output_c_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_c_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_C_RHS]
perform_round { two_pow_32, output_c_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_c_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_D_LHS]
perform_round { two_pow_32, output_d_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_d_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_D_RHS]
perform_round { two_pow_32, output_d_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_d_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_E_LHS]
perform_round { two_pow_32, output_e_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_e_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_E_RHS]
perform_round { two_pow_32, output_e_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_e_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_F_LHS]
perform_round { two_pow_32, output_f_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_f_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_F_RHS]
perform_round { two_pow_32, output_f_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_f_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_G_LHS]
perform_round { two_pow_32, output_g_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_g_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_G_RHS]
perform_round { two_pow_32, output_g_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_g_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_H_LHS]
perform_round { two_pow_32, output_h_lhs, /*result = 1*/ perform_round }
last { two_pow_32, output_h_lhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
#[RANGE_COMP_H_RHS]
perform_round { two_pow_32, output_h_rhs, /*result = 1*/ perform_round }
last { two_pow_32, output_h_rhs, /*result = 1*/ last }
in
gt.sel_sha256 { gt.input_a, gt.input_b, gt.res };
Original file line number Diff line number Diff line change
Expand Up @@ -21,40 +21,63 @@ template <typename AffinePoint> class StandardAffinePoint {

constexpr StandardAffinePoint(AffinePoint val) noexcept
: point(val)
, x_coord(val.x)
, y_coord(val.y)
{}

constexpr StandardAffinePoint(BaseField x, BaseField y, bool is_infinity) noexcept
: point(is_infinity ? AffinePoint::infinity() : AffinePoint(x, y))
, x_coord(x)
, y_coord(y)
{}

constexpr StandardAffinePoint operator+(const StandardAffinePoint& other) const noexcept
{
return StandardAffinePoint(point + other.point);
AffinePoint result = point + other.point;
if (result.is_point_at_infinity()) {
// If the result is infinity, we need to normalise it to (0,0) to match noir outputs.
return StandardAffinePoint::infinity();
}
return StandardAffinePoint(result);
}

constexpr StandardAffinePoint operator*(const ScalarField& exponent) const noexcept
{
return StandardAffinePoint(point * exponent);
AffinePoint result = point * exponent;
if (result.is_point_at_infinity()) {
// If the result is infinity, we need to normalise it to (0,0) to match noir outputs.
return StandardAffinePoint::infinity();
}
return StandardAffinePoint(result);
}

constexpr bool operator==(const StandardAffinePoint& other) const noexcept
{
return (this == &other || point == other.point);
}

constexpr StandardAffinePoint operator-() const noexcept { return StandardAffinePoint(-point); }
constexpr StandardAffinePoint operator-() const noexcept
{
// Negating infinity returns itself, preserving raw coordinates.
if (point.is_point_at_infinity()) {
return *this;
}
return StandardAffinePoint(-point);
}

[[nodiscard]] constexpr bool is_infinity() const noexcept { return point.is_point_at_infinity(); }

[[nodiscard]] constexpr bool on_curve() const noexcept { return point.on_curve(); }

constexpr const BaseField& x() const noexcept { return point.is_point_at_infinity() ? zero : point.x; }
// Always returns the raw coordinates, when an operation results in infinity these will be (0,0).
// If a point at infinity is constructed with non-zero coordinates, we likely want to preserve those.
constexpr const BaseField& x() const noexcept { return x_coord; }

constexpr const BaseField& y() const noexcept { return point.is_point_at_infinity() ? zero : point.y; }
constexpr const BaseField& y() const noexcept { return y_coord; }

static const StandardAffinePoint& infinity()
{
static auto infinity = StandardAffinePoint(AffinePoint::infinity());
static auto infinity = StandardAffinePoint(zero, zero, true);
return infinity;
}

Expand All @@ -65,7 +88,13 @@ template <typename AffinePoint> class StandardAffinePoint {
}

private:
// The affine point for operations, this will always match the raw coordinates unless the point is infinity.
// In that case, the point will be set to barretenberg's infinity representation - which is not (0,0).
AffinePoint point;
// These are the raw x and y coordinates, that are set when constructing the point. When an operation results
// in infinity, these will be set to (0,0) to match noir's expected representation.
BaseField x_coord = zero;
BaseField y_coord = zero;
static constexpr const auto zero = BaseField::zero();
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
#include <gtest/gtest.h>

#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
#include "barretenberg/vm2/common/standard_affine_point.hpp"

namespace bb::avm2 {
namespace {

using EmbeddedCurvePoint = StandardAffinePoint<grumpkin::g1::affine_element>;
using Fr = grumpkin::fr;
using Fq = grumpkin::fq;

TEST(StandardAffinePointTest, InfinityPreservesRawCoordinates)
{
// When constructing an infinity point with non-zero coordinates,
// x() and y() should return the raw coordinates
Fq raw_x = 1;
Fq raw_y = 2;

EmbeddedCurvePoint point(raw_x, raw_y, /*is_infinity=*/true);

EXPECT_TRUE(point.is_infinity());
EXPECT_EQ(point.x(), raw_x);
EXPECT_EQ(point.y(), raw_y);
}

TEST(StandardAffinePointTest, NormalPointCoordinates)
{
// Normal (non-infinity) points should return their coordinates
auto one = EmbeddedCurvePoint::one();
EXPECT_FALSE(one.is_infinity());
EXPECT_FALSE(one.x().is_zero());
EXPECT_FALSE(one.y().is_zero());
}

TEST(StandardAffinePointTest, AdditionResultingInInfinityNormalized)
{
// When addition produces infinity, result should have (0,0) coordinates
auto p = EmbeddedCurvePoint::one();
auto neg_p = -p;

auto inf_result = p + neg_p;

EXPECT_TRUE(inf_result.is_infinity());
EXPECT_TRUE(inf_result.x().is_zero());
EXPECT_TRUE(inf_result.y().is_zero());
}

TEST(StandardAffinePointTest, SubtractingInfinityNormalized)
{
// Subtracting a point from itself should yield infinity with (0,0) coordinates
auto p = EmbeddedCurvePoint::one();
auto inf = EmbeddedCurvePoint::infinity();

auto result = p + (-inf);

EXPECT_EQ(result, p);
}

TEST(StandardAffinePointTest, ScalarMultiplicationResultingInInfinityNormalized)
{
// When scalar multiplication produces infinity, result should have (0,0) coordinates
auto p = EmbeddedCurvePoint::one();
Fr zero_scalar = Fr::zero();

auto inf_result = p * zero_scalar;

EXPECT_TRUE(inf_result.is_infinity());
EXPECT_TRUE(inf_result.x().is_zero());
EXPECT_TRUE(inf_result.y().is_zero());
}

TEST(StandardAffinePointTest, StaticInfinityHasZeroCoordinates)
{
// The static infinity() method should return (0,0,true)
auto& inf = EmbeddedCurvePoint::infinity();

EXPECT_TRUE(inf.is_infinity());
EXPECT_TRUE(inf.x().is_zero());
EXPECT_TRUE(inf.y().is_zero());
}

TEST(StandardAffinePointTest, NegatingInfinityPreservesRawCoordinates)
{
// Negating an infinity point should preserve its raw coordinates
Fq raw_x = 1;
Fq raw_y = 2;
EmbeddedCurvePoint inf(raw_x, raw_y, /*is_infinity=*/true);

auto neg_inf = -inf;

EXPECT_TRUE(neg_inf.is_infinity());
EXPECT_EQ(neg_inf.x(), raw_x);
EXPECT_EQ(neg_inf.y(), raw_y);
}

} // namespace
} // namespace bb::avm2
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ TEST_F(AvmRecursionConstraintTest, GateCountAndVKCheck)
using ProverInstance = ProverInstance_<UltraRollupFlavor>;

static constexpr FF EXPECTED_OUTER_VK_HASH =
FF("0x2db814b00aa8881bf5701dc7f203e4c7c7c976cfff151d8bfe477779c75bd96c");
FF("0x0c17c44b4c643765ef2ffc77cb6b77104910b0d4fc38de7ea0115301346e2b51");

AcirConstraint constraint;
WitnessVector witness;
Expand Down Expand Up @@ -167,7 +167,7 @@ class AvmRecursionInnerCircuitTests : public ::testing::Test {
using FF = Builder::FF;

static constexpr FF EXPECTED_INNER_VK_HASH =
FF("0x2370e99c105d4dd689b626c376de4ee5f257ed99163094d57720159ac1e96881");
FF("0x0822fef4f7d002ccf7f18512598d0fc1a6b8b13143221330bcb1ce0990eba291");

static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); }

Expand Down
10 changes: 5 additions & 5 deletions barretenberg/cpp/src/barretenberg/vm2/generated/columns.hpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ namespace bb::avm2 {

struct AvmFlavorVariables {
static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 124;
static constexpr size_t NUM_WITNESS_ENTITIES = 3061;
static constexpr size_t NUM_WITNESS_ENTITIES = 3062;
static constexpr size_t NUM_SHIFTED_ENTITIES = 344;
static constexpr size_t NUM_WIRES = 2595;
static constexpr size_t NUM_ALL_ENTITIES = 3529;
static constexpr size_t NUM_WIRES = 2596;
static constexpr size_t NUM_ALL_ENTITIES = 3530;

// Need to be templated for recursive verifier
template <typename FF_>
Expand Down
Loading
Loading