From 5eef9e5bc778f6bbb5fc7837cf19df7372ceca1a Mon Sep 17 00:00:00 2001 From: sowle Date: Tue, 2 Mar 2021 00:49:17 +0300 Subject: [PATCH] experimental crypto: added test crypto_primitives --- tests/functional_tests/crypto_tests.cpp | 446 ++++++++++++++++++++++++ 1 file changed, 446 insertions(+) diff --git a/tests/functional_tests/crypto_tests.cpp b/tests/functional_tests/crypto_tests.cpp index 2f1f3f4e..bcdbe4d1 100644 --- a/tests/functional_tests/crypto_tests.cpp +++ b/tests/functional_tests/crypto_tests.cpp @@ -9,6 +9,7 @@ #include "epee/include/profile_tools.h" #include "include_base_utils.h" #include "common/crypto_stream_operators.h" +#include "currency_core/difficulty.h" extern "C" { @@ -967,6 +968,451 @@ struct test_keeper_t // Tests // +TEST(crypto, primitives) +{ + struct helper + { + static void make_rnd_indicies(std::vector& v, size_t size) + { + v.resize(size); + for (size_t i = 0; i < size; ++i) + v[i] = i; + std::shuffle(v.begin(), v.end(), crypto::uniform_random_bit_generator()); + }; + }; + + struct timer_t + { + std::chrono::high_resolution_clock::time_point m_tp{}; + uint64_t m_t{}; + uint64_t m_div_coeff{ 1 }; + void start(uint64_t div_coeff = 1) { m_tp = std::chrono::high_resolution_clock::now(); m_div_coeff = div_coeff; } + void stop() { m_t = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - m_tp).count(); } + uint64_t get_time_mcs() { return m_div_coeff == 1 ? m_t : m_t / m_div_coeff; } + }; + + typedef uint64_t(*run_func_t)(timer_t& t, size_t rounds); + + + + auto run = [](const std::string& title, size_t rounds, run_func_t cb) + { + uint64_t result; + timer_t t_warmup, t, t_total; + t_total.start(); + result = cb(t_warmup, rounds); + result += cb(t, rounds); + t_total.stop(); + double run_time_mcs_x_100 = double(uint64_t(t.get_time_mcs() / (rounds / 100))); + LOG_PRINT_L0(std::left << std::setw(50) << title << std::setw(7) << rounds << " rnds -> " + << std::right << std::setw(7) << std::fixed << std::setprecision(2) << run_time_mcs_x_100 / 100.0 << " mcs avg. (gross: " + << std::fixed << std::setprecision(2) << double(t_total.get_time_mcs()) / 1000.0 << " ms), result hash: " << result); + }; + +#define HASH_64_VEC(vec_var_name) hash_64(vec_var_name.data(), vec_var_name.size() * sizeof(vec_var_name[0])) + + LOG_PRINT_L0(ENDL << "native crypto primitives:"); + + run("ge_p3_to_cached(p3)", 10000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector points_p3(rounds); + ge_scalarmult_base(&points_p3[0], c_scalar_1.data()); + for (size_t i = 1; i < points_p3.size(); ++i) + ge_bytes_hash_to_ec(&points_p3[i], (const unsigned char*)&points_p3[i - 1].X); // P_{i+1} = Hp(P_i.X) + + std::vector points_cached(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_p3_to_cached(&points_cached[i], &points_p3[rnd_indecies[i]]); + } + t.stop(); + + return HASH_64_VEC(points_cached); + }); + + run("ge_add(p3 + p3)", 50000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + std::vector points_cached(rounds); + point_t p = scalar_t::random() * c_point_G; + for (size_t i = 0; i < rnd_indecies.size(); ++i) + { + ge_p3_to_cached(&points_cached[i], &p.m_p3); + p = p + p; + } + ge_p3 Q; + ge_scalarmult_base(&Q, &scalar_t::random().m_s[0]); + std::vector results(rnd_indecies.size()); + + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_add(&results[i], &Q, &points_cached[rnd_indecies[i]]); + } + t.stop(); + + return HASH_64_VEC(results); + }); + + run("ge_p1p1_to_p3(p1p1)", 50000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + ge_cached G; + ge_p3_to_cached(&G, &c_point_G.m_p3); + + std::vector points_p1p1(rounds); + ge_add(&points_p1p1[0], &c_point_G.m_p3, &G); + for (size_t i = 1; i < points_p1p1.size(); ++i) + { + ge_p3 p3; + ge_p1p1_to_p3(&p3, &points_p1p1[i - 1]); + ge_add(&points_p1p1[i], &p3, &G); + } + + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_p1p1_to_p3(&points_p3[i], &points_p1p1[rnd_indecies[i]]); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult()", 5000, [](timer_t& t, size_t rounds) { + //rounds -= rounds % 8; + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + //scalar_t x = x + x + x; + scalar_t x; + x.make_random(); + memcpy(&scalars[i].data, x.data(), 32); + } + + point_t p = scalar_t::random() * c_point_G; + + //std::vector points_p2(rounds); + std::vector points_p3(rounds); + + // warmup round + //for (size_t i = 0; i < rounds; ++i) + // ge_scalarmult((ge_p2*)&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult((ge_p2*)&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 3], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 3]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 0], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 0]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 1], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 1]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 2], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 2]], &p.m_p3); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult() (2)", 5000, [](timer_t& t, size_t rounds) { + //rounds -= rounds % 8; + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + //scalar_t x = x + x + x; + scalar_t x; + x.make_random(); + memcpy(&scalars[i].data, x.data(), 32); + } + + point_t p = scalar_t::random() * c_point_G; + + //std::vector points_p2(rounds); + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult((ge_p2*)&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 3], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 3]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 0], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 0]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 1], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 1]], &p.m_p3); + //ge_scalarmult(&points_p2[i * 4 + 2], (const unsigned char*)&scalars[rnd_indecies[i * 4 + 2]], &p.m_p3); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult_p3()", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + //scalar_t x = x + x + x; + scalar_t x; + x.make_random(); + memcpy(&scalars[i].data, x.data(), 32); + } + + point_t p = scalar_t::random() * c_point_G; + + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult_p3(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult_vartime_p3()", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + //scalar_t x = x + x + x; + scalar_t x; + x.make_random(); + memcpy(&scalars[i].data, x.data(), 32); + } + + point_t p = scalar_t::random() * c_point_G; + + //memcpy(&scalars[rnd_indecies[0]], scalar_t(1).data(), 32); + + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult_vartime_p3(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult_vartime_p3_v2()", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + //scalar_t x = x + x + x; + scalar_t x; + x.make_random(); + memcpy(&scalars[i].data, x.data(), 32); + } + + point_t p = scalar_t::random() * c_point_G; + + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult_vartime_p3_v2(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]], &p.m_p3); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + run("ge_scalarmult_base()", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + scalar_t x; + x.make_random(); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + { + scalar_t x = x + x + x; + memcpy(&scalars[i].data, x.data(), 32); + } + + std::vector points_p3(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + ge_scalarmult_base(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]]); + } + t.stop(); + + return HASH_64_VEC(points_p3); + }); + + + + LOG_PRINT_L0(ENDL << "new primitives:"); + + run("point_t + point_t", 50000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector points(rounds); + point_t p = c_point_G; + for (size_t i = 0; i < rounds; ++i) + { + points[i] = p; + p = p + p; + } + + std::vector result(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = points[rnd_indecies[i]] + p; + } + t.stop(); + + return HASH_64_VEC(result); + }); + + run("sclar_t * point_t", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + scalars[i].make_random(); + + point_t p = scalar_t::random() * c_point_G; + + std::vector result(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = scalars[rnd_indecies[i]] * p; + } + t.stop(); + + return HASH_64_VEC(result); + }); + + run("sclar_t * point_g_t", 5000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + scalars[i].make_random(); + + std::vector result(rounds); + t.start(); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = scalars[rnd_indecies[i]] * c_point_G; + } + t.stop(); + + return HASH_64_VEC(result); + }); + + run("sclar_t * scalar_t", 50000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + scalars[i].make_random(); + + scalar_t s = scalar_t::random(); + + std::vector result(rounds); + t.start(4); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = scalars[rnd_indecies[i]] * s * s * s * s; + } + t.stop(); + + return HASH_64_VEC(result); + }); + + run("sclar_t / scalar_t", 10000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector scalars(rounds); + for (size_t i = 0; i < rounds; ++i) + scalars[i].make_random(); + + scalar_t s = scalar_t::random(); + + std::vector result(rounds); + t.start(2); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = scalars[rnd_indecies[i]] / s / s; + } + t.stop(); + + return HASH_64_VEC(result); + }); + + run("mul_plus_G", 2000, [](timer_t& t, size_t rounds) { + std::vector rnd_indecies; + helper::make_rnd_indicies(rnd_indecies, rounds); + + std::vector points(rounds); + point_t p = c_point_G; + for (size_t i = 0; i < rounds; ++i) + { + points[i] = p; + p = p + p; + } + + scalar_t a, b; + a.make_random(); + b.make_random(); + + std::vector result(rounds); + t.start(2); + for (size_t i = 0; i < rounds; ++i) + { + result[i] = points[rnd_indecies[i]].mul_plus_G(a, b).mul_plus_G(a, b); + } + t.stop(); + + return HASH_64_VEC(result); + }); + + return true; +} +// test crypto_primitives + struct sig_check_t { crypto::hash prefix_hash;