crypto: scalar_t::get_bits + test + performance test + cn_hash performance test
This commit is contained in:
parent
ee3570b6dd
commit
77d6f94280
3 changed files with 138 additions and 1 deletions
|
|
@ -517,6 +517,24 @@ namespace crypto
|
|||
m_u64[bit_index >> 6] &= ~(1ull << (bit_index & 63));
|
||||
}
|
||||
|
||||
// the result is guaranteed to be within [ 0; 2 ^ bits_count )
|
||||
uint64_t get_bits(uint8_t bit_index_first, uint8_t bits_count) const
|
||||
{
|
||||
if (bits_count == 0 || bits_count > 64)
|
||||
return 0;
|
||||
uint8_t bits_count_m_1 = bits_count - 1;
|
||||
unsigned int bit_index_last = bit_index_first + bits_count_m_1;
|
||||
if (bit_index_last > 255)
|
||||
bit_index_last = 255;
|
||||
|
||||
uint64_t result = m_u64[bit_index_first >> 6] >> (bit_index_first & 63);
|
||||
if (bits_count_m_1 > (bit_index_last & 63))
|
||||
result |= m_u64[bit_index_last >> 6] << (bits_count_m_1 - (bit_index_last & 63));
|
||||
|
||||
uint64_t result_mask = ((1ull << bits_count_m_1) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect)
|
||||
return result & result_mask;
|
||||
}
|
||||
|
||||
// does not reduce
|
||||
static scalar_t power_of_2(uint8_t exponent)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1651,6 +1651,49 @@ TEST(crypto, point_negation)
|
|||
}
|
||||
|
||||
|
||||
TEST(crypto, scalar_get_bits)
|
||||
{
|
||||
scalar_t x = scalar_t::random();
|
||||
for(size_t i = 0; i < 256; ++i)
|
||||
ASSERT_EQ(x.get_bits(i, 0), 0);
|
||||
for(size_t i = 0; i < 256; ++i)
|
||||
ASSERT_EQ(x.get_bits(i, std::min(255ull, i + 65)), 0);
|
||||
|
||||
ASSERT_EQ(x.get_bits(0, 64), x.m_u64[0]);
|
||||
ASSERT_EQ(x.get_bits(64, 64), x.m_u64[1]);
|
||||
ASSERT_EQ(x.get_bits(128, 64), x.m_u64[2]);
|
||||
ASSERT_EQ(x.get_bits(192, 64), x.m_u64[3]);
|
||||
|
||||
uint64_t high_32_bits = x.m_u64[3] >> 32;
|
||||
ASSERT_EQ(x.get_bits(192+32, 32), high_32_bits);
|
||||
|
||||
for(size_t i = 33; i <= 64; ++i)
|
||||
ASSERT_EQ(x.get_bits(192+32, i), high_32_bits);
|
||||
|
||||
for(size_t i = 0; i < 10000; ++i)
|
||||
{
|
||||
scalar_t b = scalar_t::random();
|
||||
scalar_t x = scalar_t::random();
|
||||
size_t bit_index_from = b.m_s[5];
|
||||
size_t bits_count = b.m_s[6] % 65; // [0; 64] are allowed
|
||||
|
||||
uint64_t extracted_bits = 0;
|
||||
for(size_t j = 0; j < bits_count; ++j)
|
||||
{
|
||||
if (bit_index_from + j <= 255 && x.get_bit(bit_index_from + j))
|
||||
extracted_bits |= 1ull << j;
|
||||
}
|
||||
|
||||
if (extracted_bits != x.get_bits(bit_index_from, bits_count))
|
||||
{
|
||||
std::cout << "i: " << i << ", bit_index_from: " << bit_index_from << ", bits_count: " << bits_count << ENDL
|
||||
<< "extracted_bits: " << extracted_bits << ", get_bits(): " << x.get_bits(bit_index_from, bits_count);
|
||||
ASSERT_TRUE(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// test's runner
|
||||
//
|
||||
|
|
|
|||
|
|
@ -3,7 +3,45 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
||||
TEST(crypto, primitives)
|
||||
|
||||
uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_count)
|
||||
{
|
||||
if (bits_count == 0 || bits_count > 64)
|
||||
return 0;
|
||||
unsigned int bit_index_last = bit_index_first + bits_count - 1;
|
||||
if (bit_index_last > 255)
|
||||
bit_index_last = 255;
|
||||
uint64_t result_mask = ((1ull << (bits_count - 1)) - 1) << 1 | 1; // (just because 1ull << 64 in undefined behaviour, not a 0 as one would expect)
|
||||
|
||||
uint64_t result = s.m_u64[bit_index_first >> 6] >> (bit_index_first & 63);
|
||||
if (bits_count > (bit_index_last & 63) + 1)
|
||||
result |= s.m_u64[bit_index_last >> 6] << (bits_count - (bit_index_last & 63) - 1);
|
||||
return result & result_mask;
|
||||
}
|
||||
|
||||
|
||||
inline std::ostream &operator <<(std::ostream &o, const crypto::ge_precomp v)
|
||||
{
|
||||
o << "{{";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yplusx[i] << ", ";
|
||||
|
||||
o << v.yplusx[9] << "},\n {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.yminusx[i] << ", ";
|
||||
|
||||
o << v.yminusx[9] << "},\n {";
|
||||
|
||||
for(size_t i = 0; i < 9; ++i)
|
||||
o << v.xy2d[i] << ", ";
|
||||
|
||||
o << v.xy2d[9] << "}}\n";
|
||||
return o;
|
||||
}
|
||||
|
||||
TEST(perf, primitives)
|
||||
{
|
||||
struct helper
|
||||
{
|
||||
|
|
@ -46,6 +84,44 @@ TEST(crypto, primitives)
|
|||
|
||||
#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 << "hash functions:");
|
||||
|
||||
struct run_cn_fash_hash
|
||||
{
|
||||
static uint64_t run(timer_t& t, size_t rounds, size_t data_size)
|
||||
{
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
struct bytes64
|
||||
{
|
||||
unsigned char b[64];
|
||||
};
|
||||
|
||||
std::vector<bytes64> scalars_64(rounds);
|
||||
for (size_t i = 0; i < scalars_64.size(); ++i)
|
||||
crypto::generate_random_bytes(sizeof(bytes64), scalars_64[i].b);
|
||||
|
||||
std::vector<hash> results(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
results[i] = cn_fast_hash(scalars_64[rnd_indecies[i]].b, 64);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(results);
|
||||
};
|
||||
};
|
||||
|
||||
run("cn_fast_hash(64 bytes)", 1000, [](timer_t& t, size_t rounds) {
|
||||
return run_cn_fash_hash::run(t, rounds, 64ull);
|
||||
});
|
||||
|
||||
run("cn_fast_hash(2048 bytes)", 1000, [](timer_t& t, size_t rounds) {
|
||||
return run_cn_fash_hash::run(t, rounds, 2048ull);
|
||||
});
|
||||
|
||||
LOG_PRINT_L0(ENDL << "native crypto primitives:");
|
||||
|
||||
run("sc_reduce", 30000, [](timer_t& t, size_t rounds) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue