Skip to content

Commit

Permalink
Refactor make_point
Browse files Browse the repository at this point in the history
Added point type template argument.
  • Loading branch information
smlu committed Dec 22, 2023
1 parent 1a365e6 commit 2ff9849
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 32 deletions.
70 changes: 38 additions & 32 deletions include/ack/ec.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -828,10 +828,6 @@ namespace ack {
[[nodiscard]] ec_point_fp_proj doubled() const
{
const auto& p = *this;
if ( p.is_identity() ) {
return p;
}

if ( p.is_identity() || p.y == 0 ) {
return ec_point_fp_proj(); // identity
}
Expand Down Expand Up @@ -1482,11 +1478,11 @@ namespace ack {
* @param verify if true, the point is verified to be valid point on the curve created by the curve generator point g.
* @return curve point
*/
template<typename IntT = int_type>
[[nodiscard]] inline constexpr point_type make_point(IntT x, IntT y, bool verify = false) const
template<typename PointU = point_type, typename IntT = int_type>
[[nodiscard]] inline constexpr PointU make_point(IntT x, IntT y, bool verify = false) const
{
return static_cast<const CurveT&>( *this )
.make_point( std::move(x), std::move(y), verify );
.template make_point<PointU>( std::move(x), std::move(y), verify );
}

/**
Expand Down Expand Up @@ -1633,63 +1629,61 @@ namespace ack {
}

/**
* Creates a point from a given pair of integers x & y.
* Creates a point from provided affine coordinates x & y.
* @warning Returned point stores pointer to curve prime.
* The curve must outlive the point.
* @note Expects x|y >= 0 and x|y < p
* @note The returned point can be invalid, since the function allows
* creating points that were not generated with the generator point.
*
* @tparam PointU - point type to make. Default affine point_type.
*
* @param x - point x coordinate
* @param y - point y coordinate
* @param verify - If true, the point is verified to be valid point on the curve created by the curve generator point g.
* Default is false. Slow operation, can be be performed also with call to point.is_valid() function.
* @return Curve point
*/
[[nodiscard]] constexpr point_type make_point(IntT&& x, IntT&& y, bool verify = false) const
template<typename PointU = point_type>
[[nodiscard]] constexpr PointU make_point(IntT&& x, IntT&& y, bool verify = false) const
{
check_integer( x, "Invalid point x coordinate" );
check_integer( y, "Invalid point y coordinate" );
auto p = point_type {
*this,
auto point = make_point<PointU>(
make_field_element( std::move(x) ),
make_field_element( std::move(y) )
};

if ( verify ) {
check( p.is_valid(), "Invalid point" );
}
return p;
make_field_element( std::move(y) ),
verify
);
return point;
}

/**
* Creates a point from a given pair of integers x & y.
* Creates a point from provided affine coordinates x & y.
* @warning Returned point stores pointer to curve prime.
* The curve must outlive the point.
* @note Expects x|y >= 0 and x|y < p
* @note The returned point can be invalid, since the function allows
* creating points that were not generated with the generator point.
*
* @tparam PointU - point type to make. Default affine point_type.
*
* @param x - point x coordinate
* @param y - point y coordinate
* @param verify - If true, the point is verified to be valid point on the curve created by the curve generator point g.
* Default is false. Slow operation, can be be performed also with call to point.is_valid() function.
* @return Curve point
*/
[[nodiscard]] constexpr point_type make_point(const IntT& x, const IntT& y, bool verify = false) const
template<typename PointU = point_type>
[[nodiscard]] constexpr PointU make_point(const IntT& x, const IntT& y, bool verify = false) const
{
check_integer( x, "Invalid point x coordinate" );
check_integer( y, "Invalid point y coordinate" );
auto p = point_type {
*this,
auto point = make_point<PointU>(
make_field_element( x, /*verify=*/ false ),
make_field_element( y, /*verify=*/ false )
};

if ( verify ) {
check( p.is_valid(), "Invalid point" );
}
return p;
make_field_element( y, /*verify=*/ false ),
verify
);
return point;
}

/**
Expand Down Expand Up @@ -1723,9 +1717,6 @@ namespace ack {
auto afe = make_field_element( a, /*verify =*/ false );
auto bfe = make_field_element( b, /*verify =*/ false );
auto y2 = 4 * afe.sqr() * afe + 27 * bfe.sqr();
if ( y2 == 0 ) {
return false;
}

// check that discriminant is nonzero. If zero, the curve is singular.
if ( ( -16 * y2 ) == 0) {
Expand Down Expand Up @@ -1781,6 +1772,21 @@ namespace ack {
}
return field_element_type( x, p );
}

template<typename PointU>
[[nodiscard]] constexpr PointU make_point(field_element_type x, field_element_type y, bool verify = false) const
{
auto point = PointU{ point_type {
*this,
std::move( x ),
std::move( y )
}};

if ( verify ) {
check( point.is_valid(), "Invalid point" );
}
return point;
}
};

/**
Expand Down
20 changes: 20 additions & 0 deletions tests/include/ack/tests/ec_test.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,17 @@ namespace ack::tests {
REQUIRE_EQUAL( p1.is_valid() , false )

auto p1_proj = ec_point_fp_proj( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y, /*verify=*/ false ), p1_proj )
REQUIRE_EQUAL( ( p1_proj.x == 0 ) && ( p1_proj.y == 1 ) && ( p1_proj.z == 0 ), true )
REQUIRE_EQUAL( p1_proj.is_identity(), true )
REQUIRE_EQUAL( p1_proj.is_on_curve(), true )
REQUIRE_EQUAL( p1_proj.is_valid() , false )
REQUIRE_EQUAL( p1_proj.to_affine() , p1 )

auto p1_jacobi = ec_point_fp_jacobi( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y ), p1_jacobi )
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y, /*verify=*/ false ), p1_jacobi )
REQUIRE_EQUAL( ( p1_jacobi.x == 0 ) && ( p1_jacobi.y == 1 ) && ( p1_jacobi.z == 0 ), true )
REQUIRE_EQUAL( p1_jacobi.is_identity(), true )
REQUIRE_EQUAL( p1_jacobi.is_on_curve(), true )
Expand Down Expand Up @@ -176,13 +180,17 @@ namespace ack::tests {
REQUIRE_EQUAL( p1.is_valid() , false )

auto p1_proj = ec_point_fp_proj( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y, /*verify=*/ false ) , p1_proj )
REQUIRE_EQUAL( ( p1_proj.x == 3 ) && ( p1_proj.y == 7 ) && ( p1_proj.z == 1 ), true )
REQUIRE_EQUAL( p1_proj.is_identity(), false )
REQUIRE_EQUAL( p1_proj.is_on_curve(), false )
REQUIRE_EQUAL( p1_proj.is_valid() , false )
REQUIRE_EQUAL( p1_proj.to_affine() , p1 )

auto p1_jacobi = ec_point_fp_jacobi( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y ), p1_jacobi )
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y, /*verify=*/ false ), p1_jacobi )
REQUIRE_EQUAL( ( p1_jacobi.x == 3 ) && ( p1_jacobi.y == 7 ) && ( p1_jacobi.z == 1 ), true )
REQUIRE_EQUAL( p1_jacobi.is_identity(), false )
REQUIRE_EQUAL( p1_jacobi.is_on_curve(), false )
Expand Down Expand Up @@ -210,13 +218,17 @@ namespace ack::tests {
REQUIRE_EQUAL( p1.is_valid() , false ) // point not generated by base point

auto p1_proj = ec_point_fp_proj( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( ( p1_proj.x == 3 ) && ( p1_proj.y == 10 ) && ( p1_proj.z == 1 ), true )
REQUIRE_EQUAL( p1_proj.is_identity(), false )
REQUIRE_EQUAL( p1_proj.is_on_curve(), true )
REQUIRE_EQUAL( p1_proj.is_valid() , false ) // point not generated by base point
REQUIRE_EQUAL( p1_proj.to_affine() , p1 )

auto p1_jacobi = ec_point_fp_jacobi( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y ), p1_jacobi )
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y ), p1_jacobi )
REQUIRE_EQUAL( ( p1_jacobi.x == 3 ) && ( p1_jacobi.y == 10 ) && ( p1_jacobi.z == 1 ), true )
REQUIRE_EQUAL( p1_jacobi.is_identity(), false )
REQUIRE_EQUAL( p1_jacobi.is_on_curve(), true )
Expand Down Expand Up @@ -244,13 +256,17 @@ namespace ack::tests {
REQUIRE_EQUAL( p1.is_valid() , false )

auto p1_proj = ec_point_fp_proj( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y, /*verify=*/ false ), p1_proj )
REQUIRE_EQUAL( ( p1_proj.x == 22 ) && ( p1_proj.y == 22 ) && ( p1_proj.z == 1 ), true )
REQUIRE_EQUAL( p1_proj.is_identity(), false )
REQUIRE_EQUAL( p1_proj.is_on_curve(), false )
REQUIRE_EQUAL( p1_proj.is_valid() , false )
REQUIRE_EQUAL( p1_proj.to_affine() , p1 )

auto p1_jacobi = ec_point_fp_jacobi( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y ), p1_jacobi )
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y, /*verify=*/ false ), p1_jacobi )
REQUIRE_EQUAL( ( p1_jacobi.x == 22 ) && ( p1_jacobi.y == 22 ) && ( p1_jacobi.z == 1 ), true )
REQUIRE_EQUAL( p1_jacobi.is_identity(), false )
REQUIRE_EQUAL( p1_jacobi.is_on_curve(), false )
Expand Down Expand Up @@ -278,12 +294,16 @@ namespace ack::tests {
REQUIRE_EQUAL( p1.is_valid() , true )

auto p1_proj = ec_point_fp_proj( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y ), p1_proj )
REQUIRE_EQUAL( c23.make_point<c23_point_proj>( x, y, /*verify=*/ true ), p1_proj )
REQUIRE_EQUAL( ( p1_proj.x == 5 ) && ( p1_proj.y == 4 ) && ( p1_proj.z == 1 ), true )
REQUIRE_EQUAL( p1_proj.is_identity(), false )
REQUIRE_EQUAL( p1_proj.is_on_curve(), true )
REQUIRE_EQUAL( p1_proj.is_valid() , true )

auto p1_jacobi = ec_point_fp_jacobi( p1 );
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y, /*verify=*/ false ), p1_jacobi )
REQUIRE_EQUAL( c23.make_point<c23_point_jacobi>( x, y, /*verify=*/ true ), p1_jacobi )
REQUIRE_EQUAL( ( p1_jacobi.x == 5 ) && ( p1_jacobi.y == 4 ) && ( p1_jacobi.z == 1 ), true )
REQUIRE_EQUAL( p1_jacobi.is_identity(), false )
REQUIRE_EQUAL( p1_jacobi.is_on_curve(), true )
Expand Down

0 comments on commit 2ff9849

Please sign in to comment.