Skip to content

Commit

Permalink
montgomery conversion G1
Browse files Browse the repository at this point in the history
  • Loading branch information
yshekel committed Jun 6, 2024
1 parent c4957fd commit 641c4ea
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 13 deletions.
17 changes: 8 additions & 9 deletions icicle_v3/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,19 @@ target_link_libraries(icicle_device PUBLIC dl)
target_include_directories(icicle_device PUBLIC include)

if((DEFINED CURVE) AND (DEFINED FIELD))
message( FATAL_ERROR "CURVE and FIELD cannot be defined at the same time" )
endif ()

# field library
if(FIELD)
check_field()
setup_field_target()
if(NOT ("${CURVE}" STREQUAL "${FIELD}"))
message(FATAL_ERROR "CURVE and FIELD should be defined at the same time unless they are equal")
endif()
endif()

# curve is building the scalar field too
if(CURVE)
check_curve()
setup_curve_target()
endif ()

elseif(FIELD)
check_field()
setup_field_target()
endif()

if (BUILD_CPU_BE)
add_subdirectory(backend/cpu)
Expand Down
5 changes: 4 additions & 1 deletion icicle_v3/backend/cpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ set_target_properties(icicle_cpu_field PROPERTIES OUTPUT_NAME "icicle_cpu_field_

# curve API library
if (CURVE)
add_library(icicle_cpu_curve SHARED src/curve/cpu_msm.cpp)
add_library(icicle_cpu_curve SHARED
src/curve/cpu_msm.cpp
src/curve/cpu_mont_conversion.cpp
)
target_link_libraries(icicle_cpu_curve PUBLIC icicle_device icicle_curve)
set_target_properties(icicle_cpu_curve PROPERTIES OUTPUT_NAME "icicle_cpu_curve_${CURVE}")
endif()
23 changes: 23 additions & 0 deletions icicle_v3/backend/cpu/src/curve/cpu_mont_conversion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

#include "icicle/curves/montgomery_conversion.h"
#include "icicle/errors.h"
#include "icicle/runtime.h"
#include "icicle/utils/log.h"

#include "icicle/curves/curve_config.h"

using namespace curve_config;
using namespace icicle;

template <typename T>
eIcicleError cpu_convert_mont(
const Device& device, const T* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, T* output)
{
for (size_t i = 0; i < n; ++i) {
output[i] = is_into ? T::to_montgomery(input[i]) : T::from_montgomery(input[i]);
}
return eIcicleError::SUCCESS;
}

REGISTER_AFFINE_CONVERT_MONTGOMERY_BACKEND("CPU", cpu_convert_mont<affine_t>);
REGISTER_PROJECTIVE_CONVERT_MONTGOMERY_BACKEND("CPU", cpu_convert_mont<projective_t>);
2 changes: 1 addition & 1 deletion icicle_v3/backend/cuda/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ include(cmake/Common.cmake)
set_env()
set_gpu_env()

find_package(CUDA REQUIRED)
find_package(CUDAToolkit REQUIRED)

# device API library
add_library(icicle_cuda_device SHARED src/cuda_device_api.cu)
Expand Down
1 change: 1 addition & 0 deletions icicle_v3/cmake/curve.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ function(setup_curve_target)
add_library(icicle_curve SHARED
src/msm.cpp
src/curves/ffi_extern.cpp
src/curves/montgomery_conversion.cpp
)
target_link_libraries(icicle_curve PUBLIC icicle_device) # for thread local device
set_target_properties(icicle_curve PROPERTIES OUTPUT_NAME "icicle_curve_${CURVE}")
Expand Down
5 changes: 5 additions & 0 deletions icicle_v3/include/icicle/curves/affine.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class Affine
return (xs.x == ys.x) && (xs.y == ys.y);
}

friend HOST_DEVICE_INLINE bool operator!=(const Affine& xs, const Affine& ys)
{
return !(xs==ys);
}

friend HOST_INLINE std::ostream& operator<<(std::ostream& os, const Affine& point)
{
os << "x: " << point.x << "; y: " << point.y;
Expand Down
83 changes: 83 additions & 0 deletions icicle_v3/include/icicle/curves/montgomery_conversion.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#pragma once

#include <functional>

#include "icicle/errors.h"
#include "icicle/runtime.h"
#include "icicle/utils/utils.h"
#include "icicle/config_extension.h"

#include "icicle/curves/affine.h"
#include "icicle/curves/projective.h"
#include "icicle/fields/field.h"
#include "icicle/curves/curve_config.h"

using namespace curve_config;

namespace icicle {

/*************************** Frontend APIs ***************************/

struct ConvertMontgomeryConfig {
icicleStreamHandle stream; /**< stream for async execution. */
bool is_input_on_device;
bool is_output_on_device;
bool is_async;

ConfigExtension ext; /** backend specific extensions*/
};

static ConvertMontgomeryConfig default_convert_montgomery_config()
{
ConvertMontgomeryConfig config = {
nullptr, // stream
false, // is_input_on_device
false, // is_output_on_device
false, // is_async
};
return config;
}

template <typename T>
eIcicleError
points_convert_montgomery(const T* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, T* output);

/*************************** Backend registration ***************************/

using AffineConvertMontImpl = std::function<eIcicleError(
const Device& device,
const affine_t* input,
size_t n,
bool is_into,
const ConvertMontgomeryConfig& config,
affine_t* output)>;

void register_affine_convert_montgomery(const std::string& deviceType, AffineConvertMontImpl);

#define REGISTER_AFFINE_CONVERT_MONTGOMERY_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
static bool UNIQUE(_reg_affine_convert_mont) = []() -> bool { \
register_affine_convert_montgomery(DEVICE_TYPE, FUNC); \
return true; \
}(); \
}

using ProjectiveConvertMontImpl = std::function<eIcicleError(
const Device& device,
const projective_t* input,
size_t n,
bool is_into,
const ConvertMontgomeryConfig& config,
projective_t* output)>;

void register_projective_convert_montgomery(const std::string& deviceType, ProjectiveConvertMontImpl);

#define REGISTER_PROJECTIVE_CONVERT_MONTGOMERY_BACKEND(DEVICE_TYPE, FUNC) \
namespace { \
static bool UNIQUE(_reg_projective_convert_mont) = []() -> bool { \
register_projective_convert_montgomery(DEVICE_TYPE, FUNC); \
return true; \
}(); \
}

}; // namespace icicle
1 change: 1 addition & 0 deletions icicle_v3/include/icicle/curves/projective.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class Projective
FF denom = FF::inverse(point.z);
return {point.x * denom, point.y * denom};
}
HOST_DEVICE_INLINE Affine<FF> to_affine() { return to_affine(*this); }

static HOST_DEVICE_INLINE Projective from_affine(const Affine<FF>& point)
{
Expand Down
22 changes: 21 additions & 1 deletion icicle_v3/include/icicle/utils/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ class Log
public:
enum eLogLevel { Debug, Info, Warning, Error };

Log(eLogLevel level) : level(level) {}
Log(eLogLevel level) : level{level}
{
if (level >= s_min_log_level) { oss << "[" << logLevelToString(level) << "] "; }
}

~Log()
{
Expand All @@ -34,6 +37,23 @@ class Log
eLogLevel level;
std::ostringstream oss;

// Convert log level to string
const char* logLevelToString(eLogLevel level) const
{
switch (level) {
case Debug:
return "DEBUG";
case Info:
return "INFO";
case Warning:
return "WARNING";
case Error:
return "ERROR";
default:
return "";
}
}

// logging message with level>=s_min_log_level
#if defined(NDEBUG)
static inline eLogLevel s_min_log_level = eLogLevel::Info;
Expand Down
40 changes: 40 additions & 0 deletions icicle_v3/src/curves/montgomery_conversion.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "icicle/curves/montgomery_conversion.h"
#include "icicle/dispatcher.h"
#include "icicle/curves/curve_config.h"

using namespace curve_config;

namespace icicle {

/*************************** AFFINE CONVERT MONTGOMERY ***************************/
ICICLE_DISPATCHER_INST(AffineConvertMont, affine_convert_montgomery, AffineConvertMontImpl);

extern "C" eIcicleError CONCAT_EXPAND(CURVE, affine_convert_montgomery)(
const affine_t* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, affine_t* output)
{
return AffineConvertMont::execute(input, n, is_into, config, output);
}

template <>
eIcicleError points_convert_montgomery(
const affine_t* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, affine_t* output)
{
return CONCAT_EXPAND(CURVE, affine_convert_montgomery)(input, n, is_into, config, output);
}

/*************************** PROJECTIVE CONVERT MONTGOMERY ***************************/
ICICLE_DISPATCHER_INST(ProjectiveConvertMont, projective_convert_montgomery, ProjectiveConvertMontImpl);

extern "C" eIcicleError CONCAT_EXPAND(CURVE, projective_convert_montgomery)(
const projective_t* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, projective_t* output)
{
return ProjectiveConvertMont::execute(input, n, is_into, config, output);
}

template <>
eIcicleError points_convert_montgomery(
const projective_t* input, size_t n, bool is_into, const ConvertMontgomeryConfig& config, projective_t* output)
{
return CONCAT_EXPAND(CURVE, projective_convert_montgomery)(input, n, is_into, config, output);
}
} // namespace icicle
2 changes: 1 addition & 1 deletion icicle_v3/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ include(GoogleTest)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.zip
URL https://github.com/google/googletest/archive/refs/tags/v1.13.0.zip
)

# For Windows: Prevent overriding the parent project's compiler/linker settings
Expand Down
29 changes: 29 additions & 0 deletions icicle_v3/tests/test_curve_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "icicle/runtime.h"
#include "icicle/msm.h"
#include "icicle/vec_ops.h"
#include "icicle/curves/montgomery_conversion.h"
#include "icicle/curves/curve_config.h"

using namespace curve_config;
Expand Down Expand Up @@ -70,6 +71,34 @@ TEST_F(CurveApiTest, MSM)
// TODO test something
}

TEST_F(CurveApiTest, MontConversion)
{
// Note: this test doesn't really test correct mont conversion (since there is no arithmetic in mont) but checks that
// it does some conversion and back to original
affine_t affine_point, affine_point_converted;
projective_t projective_point, projective_point_converted;

projective_point = projective_t::rand_host();
affine_point = projective_point.to_affine();

icicle_set_device({"CPU", 0});

// (1) converting to mont and check not equal to original
auto config = default_convert_montgomery_config();
points_convert_montgomery(&affine_point, 1, true /*into mont*/, config, &affine_point_converted);
points_convert_montgomery(&projective_point, 1, true /*into mont*/, config, &projective_point_converted);

ASSERT_NE(affine_point, affine_point_converted); // check that it was converted to mont
ASSERT_NE(projective_point.x, projective_point_converted.x); // check that it was converted to mont

// (2) converting back from mont and check equal
points_convert_montgomery(&projective_point_converted, 1, false /*from mont*/, config, &projective_point_converted);
points_convert_montgomery(&affine_point_converted, 1, false /*from mont*/, config, &affine_point_converted);

ASSERT_EQ(affine_point, affine_point_converted);
ASSERT_EQ(projective_point, projective_point_converted);
}

int main(int argc, char** argv)
{
::testing::InitGoogleTest(&argc, argv);
Expand Down

0 comments on commit 641c4ea

Please sign in to comment.