1
0
Fork 0
forked from lthn/blockchain

Merge branch 'add_block_performance_mes' into decoy_selection

This commit is contained in:
sowle 2024-01-28 16:01:02 +01:00
commit 27bb395542
No known key found for this signature in database
GPG key ID: C07A24B2D89D49FC
9 changed files with 2907 additions and 56 deletions

View file

@ -307,26 +307,25 @@ namespace misc_utils
/************************************************************************/
/* */
/************************************************************************/
template<class type_vec_type>
type_vec_type median(std::vector<type_vec_type> &v)
template<typename container_t>
typename container_t::value_type median(container_t &v)
{
//CRITICAL_REGION_LOCAL(m_lock);
typename container_t::value_type median{};
if(v.empty())
return boost::value_initialized<type_vec_type>();
return median;
if(v.size() == 1)
return v[0];
size_t n = (v.size()) / 2;
std::sort(v.begin(), v.end());
//nth_element(v.begin(), v.begin()+n-1, v.end());
if(v.size()%2)
{//1, 3, 5...
return v[n];
}else
{//2, 4, 6...
return (v[n-1] + v[n])/2;
auto median_it = v.begin() + v.size() / 2;
std::nth_element(v.begin(), median_it, v.end());
median = *median_it;
if (v.size() % 2 == 0)
{
auto max_it = std::max_element(v.begin(), median_it); // it's garanteed that after nth_element() the necessary element is in this interval
median = (median + *max_it) / 2; // average of [size/2-1] and [size/2] elements
}
return median;
}
/************************************************************************/

View file

@ -40,7 +40,6 @@ DISABLE_VS_WARNINGS(4146 4244)
void fe_mul(fe, const fe, const fe);
void fe_sq(fe, const fe);
void fe_tobytes(unsigned char *, const fe);
static void ge_madd(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
static void ge_msub(ge_p1p1 *, const ge_p3 *, const ge_precomp *);
static void ge_p2_0(ge_p2 *);
static void ge_p3_dbl(ge_p1p1 *, const ge_p3 *);
@ -119,7 +118,7 @@ Postconditions:
|h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static void fe_add(fe h, const fe f, const fe g) {
void fe_add(fe h, const fe f, const fe g) {
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
@ -1425,7 +1424,7 @@ int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) {
r = p + q
*/
static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
@ -4314,3 +4313,171 @@ void ge_cached_to_p2(ge_p2 *r, const ge_cached *c)
fe_copy(r->Z, c->Z);
}
///////////////////////////
// EXPERIMENTAL
//
// With these select_vartime/ge_scalarmult_base_vartime I got ~25% speed up comparing to the select/ge_scalarmult_base -- sowle
static void select_vartime(ge_precomp *t, int pos, signed char b)
{
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
const ge_precomp* base;
if (babs == 0)
{
ge_precomp_0(t);
}
else if (bnegative == 0)
{
base = &ge_base[pos][babs - 1];
fe_copy(t->yplusx, base->yplusx);
fe_copy(t->yminusx, base->yminusx);
fe_copy(t->xy2d, base->xy2d);
}
else
{
base = &ge_base[pos][babs - 1];
fe_copy(t->yplusx, base->yminusx);
fe_copy(t->yminusx, base->yplusx);
fe_neg(t->xy2d, base->xy2d);
}
}
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a)
{
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select_vartime(&t, i / 2, e[i]);
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select_vartime(&t, i / 2, e[i]);
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
}
}
static void select_custom_precomp_vartime(ge_precomp *t, const precomp_data_t base_precomp, int pos, signed char b)
{
unsigned char bnegative = negative(b);
unsigned char babs = b - (((-bnegative) & b) << 1);
const ge_precomp* base;
if (babs == 0)
{
ge_precomp_0(t);
}
else if (bnegative == 0)
{
base = &base_precomp[pos][babs - 1];
fe_copy(t->yplusx, base->yplusx);
fe_copy(t->yminusx, base->yminusx);
fe_copy(t->xy2d, base->xy2d);
}
else
{
base = &base_precomp[pos][babs - 1];
fe_copy(t->yplusx, base->yminusx);
fe_copy(t->yminusx, base->yplusx);
fe_neg(t->xy2d, base->xy2d);
}
}
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a)
{
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s); ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
select_custom_precomp_vartime(&t, base_precomp, i / 2, e[i]);
ge_madd(&r, h, &t); ge_p1p1_to_p3(h, &r);
}
}
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p)
{
fe recip;
fe x;
fe y;
//unsigned char s[32];
fe_invert(recip, p->Z);
fe_mul(x, p->X, recip);
fe_mul(y, p->Y, recip);
fe_sub(r->yminusx, y, x);
fe_add(r->yplusx, y, x);
fe_mul(r->xy2d, x, y);
fe_mul(r->xy2d, r->xy2d, fe_d2);
// to get canonical representation and obtain the very same beautiful numbers for ge_base in crypto-ops-data.c (maybe unnecessary, TODO -- sowle)
//fe_tobytes(s, r->yminusx); fe_frombytes(r->yminusx, s);
//fe_tobytes(s, r->yplusx); fe_frombytes(r->yplusx, s);
//fe_tobytes(s, r->xy2d); fe_frombytes(r->xy2d, s);
}

View file

@ -60,6 +60,7 @@ void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_
extern const fe fe_sqrtm1;
extern const fe fe_d;
extern const fe fe_d2;
int ge_frombytes_vartime(ge_p3 *, const unsigned char *);
/* From ge_p1p1_to_p2.c */
@ -112,12 +113,19 @@ void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t);
void ge_bytes_hash_to_ec(ge_p3 *, const void *, size_t);
void ge_bytes_hash_to_ec_32(ge_p3 *, const unsigned char *);
void ge_cached_to_p2(ge_p2 *r, const ge_cached *c);
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q);
void ge_p3_0(ge_p3 *h);
void ge_sub(ge_p1p1 *, const ge_p3 *, const ge_cached *);
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b);
void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A);
void ge_scalarmult_base_vartime(ge_p3 *h, const unsigned char *a);
/* precomp_data[i][j] = (j + 1) * 256^i * G */
typedef ge_precomp (precomp_data_t)[32][8];
void ge_scalarmult_precomp_vartime(ge_p3 *h, const precomp_data_t base_precomp, const unsigned char *a);
void ge_p3_to_precomp(ge_precomp *r, const ge_p3* p);
extern const fe fe_ma2;
extern const fe fe_ma;
@ -139,6 +147,7 @@ void sc_invert(unsigned char*, const unsigned char*);
void fe_sq(fe h, const fe f);
int fe_isnonzero(const fe f);
void fe_add(fe h, const fe f, const fe g);
void fe_sub(fe h, const fe f, const fe g);
void fe_mul(fe, const fe, const fe);
void fe_frombytes(fe h, const unsigned char *s);

File diff suppressed because it is too large Load diff

View file

@ -729,14 +729,15 @@ namespace crypto
friend point_t operator*(const scalar_t& lhs, const point_t& rhs)
{
point_t result;
ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
//ge_scalarmult_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
ge_scalarmult_vartime_p3(&result.m_p3, lhs.m_s, &rhs.m_p3);
return result;
}
point_t& operator*=(const scalar_t& rhs)
{
// TODO: ge_scalarmult_vartime_p3
ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
//ge_scalarmult_p3(&m_p3, rhs.m_s, &m_p3);
ge_scalarmult_vartime_p3(&m_p3, rhs.m_s, &m_p3);
return *this;
}
@ -745,7 +746,8 @@ namespace crypto
point_t result;
scalar_t reciprocal;
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
//ge_scalarmult_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
ge_scalarmult_vartime_p3(&result.m_p3, &reciprocal.m_s[0], &lhs.m_p3);
return result;
}
@ -907,7 +909,8 @@ namespace crypto
friend point_t operator*(const scalar_t& lhs, const point_g_t&)
{
point_t result;
ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
//ge_scalarmult_base(&result.m_p3, &lhs.m_s[0]);
ge_scalarmult_base_vartime(&result.m_p3, &lhs.m_s[0]);
return result;
}
@ -916,7 +919,8 @@ namespace crypto
point_t result;
scalar_t reciprocal;
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
//ge_scalarmult_base(&result.m_p3, &reciprocal.m_s[0]);
ge_scalarmult_base_vartime(&result.m_p3, &reciprocal.m_s[0]);
return result;
}
@ -925,6 +929,42 @@ namespace crypto
}; // struct point_g_t
void construct_precomp_data(precomp_data_t precomp_data, const point_t& point);
//
// point_pc_t -- point with 30kB of precomputed data, which make possible to do very fast single scalar multiplication
//
struct point_pc_t : public point_t
{
constexpr point_pc_t(const int32_t(&v)[40], const precomp_data_t* precomp_data_p)
: point_t(v)
, m_precomp_data_p(precomp_data_p)
{
//construct_precomp_data(m_precomp_data, *this);
}
friend point_t operator*(const scalar_t& lhs, const point_pc_t& self)
{
point_t result;
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &lhs.m_s[0]);
return result;
}
friend point_t operator/(const point_pc_t& self, const scalar_t& rhs)
{
point_t result;
scalar_t reciprocal;
sc_invert(&reciprocal.m_s[0], &rhs.m_s[0]);
ge_scalarmult_precomp_vartime(&result.m_p3, *self.m_precomp_data_p, &reciprocal.m_s[0]);
return result;
}
static_assert(sizeof(crypto::public_key) == 32, "size error");
const precomp_data_t* m_precomp_data_p;
}; // struct point_pc_t
//
// vector of scalars
//
@ -1082,18 +1122,30 @@ namespace crypto
//
// Global constants (checked in crypto_constants test)
// Global constants (checked in crypto_constants and crypto_generators_precomp tests)
//
static constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
static constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }};
static constexpr point_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }};
static constexpr point_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }};
static constexpr point_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }};
static constexpr point_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }};
static constexpr point_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }};
static constexpr point_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }};
namespace xdetails
{
extern const precomp_data_t c_point_H_precomp_data;
extern const precomp_data_t c_point_H2_precomp_data;
extern const precomp_data_t c_point_U_precomp_data;
extern const precomp_data_t c_point_X_precomp_data;
extern const precomp_data_t c_point_H_plus_G_precomp_data;
extern const precomp_data_t c_point_H_minus_G_precomp_data;
};
inline constexpr point_t c_point_0 {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
inline constexpr point_g_t c_point_G {{ 25485296, 5318399, 8791791, -8299916, -14349720, 6939349, -3324311, -7717049, 7287234, -6577708, -758052, -1832720, 13046421, -4857925, 6576754, 14371947, -13139572, 6845540, -2198883, -4003719, -947565, 6097708, -469190, 10704810, -8556274, -15589498, -16424464, -16608899, 14028613, -5004649, 6966464, -2456167, 7033433, 6781840, 28785542, 12262365, -2659449, 13959020, -21013759, -5262166 }};
inline constexpr point_pc_t c_point_H {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }, &xdetails::c_point_H_precomp_data };
inline constexpr point_pc_t c_point_H2 {{ 1318371, 14804112, 12545972, -13482561, -12089798, -16020744, -21221907, -8410994, -33080606, 11275578, 3807637, 11185450, -23227561, -12892068, 1356866, -1025012, -8022738, -8139671, -20315029, -13916324, -6475650, -7025596, 12403179, -5139984, -12068178, 10445584, -14826705, -4927780, 13964546, 12525942, -2314107, -10566315, 32243863, 15603849, 5154154, 4276633, -20918372, -15718796, -26386151, 8434696 }, &xdetails::c_point_H2_precomp_data };
inline constexpr point_pc_t c_point_U {{ 30807552, 984924, 23426137, -5598760, 7545909, 16325843, 993742, 2594106, -31962071, -959867, 16454190, -4091093, 1197656, 13586872, -9269020, -14133290, 1869274, 13360979, -24627258, -10663086, 2212027, 1198856, 20515811, 15870563, -23833732, 9839517, -19416306, 11567295, -4212053, 348531, -2671541, 484270, -19128078, 1236698, -16002690, 9321345, 9776066, 10711838, 11187722, -16371275 }, &xdetails::c_point_U_precomp_data };
inline constexpr point_pc_t c_point_X {{ 25635916, -5459446, 5768861, 5666160, -6357364, -12939311, 29490001, -4543704, -31266450, -2582476, 23705213, 9562626, -716512, 16560168, 7947407, 2039790, -2752711, 4742449, 3356761, 16338966, 17303421, -5790717, -5684800, 12062431, -3307947, 8139265, -26544839, 12058874, 3452748, 3359034, 26514848, -6060876, 31255039, 11154418, -21741975, -3782423, -19871841, 5729859, 21754676, -12454027 }, &xdetails::c_point_X_precomp_data };
inline constexpr point_pc_t c_point_H_plus_G {{ 12291435, 3330843, -3390294, 13894858, -1099584, -6848191, 12040668, -15950068, -7494633, 12566672, -5526901, -16645799, -31081168, -1095427, -13082463, 4573480, -11255691, 4344628, 33477173, 11137213, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -6229107, -9324867, 558657, 6493750, 4895261, 12642545, 9549220, 696086, 21894285, -10521807 }, &xdetails::c_point_H_plus_G_precomp_data };
inline constexpr point_pc_t c_point_H_minus_G {{ -28347682, 3523701, -3380175, -14453727, 4238027, -6032522, 20235758, 4091609, 12557126, -8064113, 4212476, -13419094, -114185, -7650727, -24238, 16663404, 23676363, -6819610, 18286466, 8714527, -3837023, -12436594, -8471924, -814016, 10785607, 9492721, 10992667, 7406385, -5687296, -127915, -20450317, 13815641, -11604061, -447489, 27380225, 9400847, -8551293, -1173627, -28110171, 14241295 }, &xdetails::c_point_H_minus_G_precomp_data };
//
// hash functions' helper
//

View file

@ -6012,6 +6012,7 @@ bool blockchain_storage::validate_pos_block(const block& b,
CHECK_AND_ASSERT_MES(b.miner_tx.signatures.size() == 1, false, "incorrect number of stake input signatures: " << b.miner_tx.signatures.size());
CHECK_AND_ASSERT_MES(b.miner_tx.signatures[0].type() == typeid(zarcanum_sig), false, "incorrect sig 0 type: " << b.miner_tx.signatures[0].type().name());
//std::stringstream ss;
if (!for_altchain)
{
TIME_MEASURE_START_PD(pos_validate_get_out_keys_for_inputs);
@ -6023,6 +6024,18 @@ bool blockchain_storage::validate_pos_block(const block& b,
uint64_t dummy_source_max_unlock_time_for_pos_coinbase_dummy = 0; // won't be used
scan_for_keys_context scan_contex = AUTO_VAL_INIT(scan_contex);
r = get_output_keys_for_input_with_checks(b.miner_tx, stake_input, dummy_output_keys, max_related_block_height, dummy_source_max_unlock_time_for_pos_coinbase_dummy, scan_contex);
//#define ADD_ITEM_TO_SS(item) ss << " " #item ": " << m_performance_data.item.get_last_val() << ENDL
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_get_item_size);
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_relative_to_absolute);
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop);
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_iteration);
// ss << " tx_check_inputs_loop_scan_outputkeys_loop_iteration (avg): " << m_performance_data.tx_check_inputs_loop_scan_outputkeys_loop_iteration.get_avg() << ENDL;
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_get_subitem);
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_find_tx);
// ADD_ITEM_TO_SS(tx_check_inputs_loop_scan_outputkeys_loop_handle_output);
//#undef ADD_ITEM_TO_SS
CHECK_AND_ASSERT_MES(r, false, "get_output_keys_for_input_with_checks failed for stake input");
CHECK_AND_ASSERT_MES(scan_contex.zc_outs.size() == stake_input.key_offsets.size(), false, "incorrect number of referenced outputs found: " << scan_contex.zc_outs.size() << ", while " << stake_input.key_offsets.size() << " is expected.");
// make sure that all referring inputs are either older then, or the same age as, the most resent PoW block.
@ -6043,6 +6056,8 @@ bool blockchain_storage::validate_pos_block(const block& b,
r = crypto::zarcanum_verify_proof(id, kernel_hash, ring, last_pow_block_id_hashed, stake_input.k_image, basic_diff, sig, &err);
TIME_MEASURE_FINISH_PD(pos_validate_zvp);
CHECK_AND_ASSERT_MES(r, false, "zarcanum_verify_proof failed with code " << (int)err);
//std::stringstream ss;
//std::cout << " validate_pos_block > get_output_keys_for_input_with_checks: " << ENDL << ss.str();
}
return true;
@ -6746,6 +6761,23 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
<< ")"
<< "))");
{
static epee::math_helper::average<uint64_t, 30> blocks_processing_time_avg_pos, blocks_processing_time_avg_pow;
(is_pos_bl ? blocks_processing_time_avg_pos : blocks_processing_time_avg_pow).push(block_processing_time_0_ms);
static std::deque<uint64_t> blocks_processing_time_median_pos, blocks_processing_time_median_pow;
std::deque<uint64_t>& d = (is_pos_bl ? blocks_processing_time_median_pos : blocks_processing_time_median_pow);
d.push_back(block_processing_time_0_ms);
if (d.size() > 200)
d.pop_front();
uint64_t median_pow = epee::misc_utils::median(blocks_processing_time_median_pow);
uint64_t median_pos = epee::misc_utils::median(blocks_processing_time_median_pos);
LOG_PRINT_YELLOW("last 30 blocks of type processing time (ms): PoW: " << std::setw(3) << (uint64_t)blocks_processing_time_avg_pow.get_avg() << ", PoS: " << (uint64_t)blocks_processing_time_avg_pos.get_avg(), LOG_LEVEL_1);
LOG_PRINT_YELLOW("last 200 blocks of type processing time (median, ms): PoW: " << std::setw(3) << median_pow << ", PoS: " << median_pos, LOG_LEVEL_1);
}
on_block_added(bei, id, block_summary_kimages);
bvc.m_added_to_main_chain = true;

View file

@ -60,7 +60,7 @@ namespace currency
// Using C++17 extended aggregate initialization (P0017R1). C++17, finally! -- sowle
const static crypto::public_key native_coin_asset_id = {{'\xd6', '\x32', '\x9b', '\x5b', '\x1f', '\x7c', '\x08', '\x05', '\xb5', '\xc3', '\x45', '\xf4', '\x95', '\x75', '\x54', '\x00', '\x2a', '\x2f', '\x55', '\x78', '\x45', '\xf6', '\x4d', '\x76', '\x45', '\xda', '\xe0', '\xe0', '\x51', '\xa6', '\x49', '\x8a'}}; // == crypto::c_point_H, checked in crypto_constants
const static crypto::public_key native_coin_asset_id_1div8 = {{'\x74', '\xc3', '\x2d', '\x3e', '\xaa', '\xfa', '\xfc', '\x62', '\x3b', '\xf4', '\x83', '\xe8', '\x58', '\xd4', '\x2e', '\x8b', '\xf4', '\xec', '\x7d', '\xf0', '\x64', '\xad', '\xa2', '\xe3', '\x49', '\x34', '\x46', '\x9c', '\xff', '\x6b', '\x62', '\x68'}}; // == 1/8 * crypto::c_point_H, checked in crypto_constants
const static crypto::point_t native_coin_asset_id_pt = crypto::c_point_H;
const static crypto::point_t native_coin_asset_id_pt {{ 20574939, 16670001, -29137604, 14614582, 24883426, 3503293, 2667523, 420631, 2267646, -4769165, -11764015, -12206428, -14187565, -2328122, -16242653, -788308, -12595746, -8251557, -10110987, 853396, -4982135, 6035602, -21214320, 16156349, 977218, 2807645, 31002271, 5694305, -16054128, 5644146, -15047429, -568775, -22568195, -8089957, -27721961, -10101877, -29459620, -13359100, -31515170, -6994674 }}; // c_point_H
const static wide_difficulty_type global_difficulty_pow_starter = DIFFICULTY_POW_STARTER;
const static wide_difficulty_type global_difficulty_pos_starter = DIFFICULTY_POS_STARTER;

View file

@ -1658,7 +1658,7 @@ TEST(crypto, scalar_get_bits)
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(i, std::min((size_t)255, 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]);
@ -1695,6 +1695,32 @@ TEST(crypto, scalar_get_bits)
return true;
}
TEST(crypto, scalarmult_base_vartime)
{
auto check_for_x = [&](const scalar_t& x) -> bool {
point_t P, P2;
ge_scalarmult_base_vartime(&P.m_p3, x.m_s);
ge_scalarmult_base(&P2.m_p3, x.m_s);
return (P - P2).is_zero();
};
ASSERT_TRUE(check_for_x(c_scalar_0));
ASSERT_TRUE(check_for_x(c_scalar_1));
ASSERT_TRUE(check_for_x(c_scalar_1div8));
ASSERT_TRUE(check_for_x(c_scalar_Lm1));
ASSERT_TRUE(check_for_x(c_scalar_L));
for(size_t i = 0; i < 1000; ++i)
{
scalar_t x = scalar_t::random();
ASSERT_TRUE(check_for_x(x));
}
return true;
}
template<typename CT>
bool crypto_msm_runner(size_t N, size_t low_bits_to_clear, size_t high_bits_to_clear)
{
@ -1762,6 +1788,116 @@ TEST(crypto, msm)
}
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] << "}, {";
for(size_t i = 0; i < 9; ++i)
o << v.yminusx[i] << ", ";
o << v.yminusx[9] << "}, {";
for(size_t i = 0; i < 9; ++i)
o << v.xy2d[i] << ", ";
o << v.xy2d[9] << "}}";
return o;
}
bool calc_and_print_generator_precomp(const point_pc_t& generator, const char* generator_var_name)
{
precomp_data_t precomp_data = {};
construct_precomp_data(precomp_data, generator);
std::cout << " const precomp_data_t " << generator_var_name << "_precomp_data = {" << ENDL;
for(size_t i = 0; i < 32; ++i)
{
std::cout << " {" << ENDL;
for(size_t j = 0; j < 8; ++j)
std::cout << " " << precomp_data[i][j] << (j != 7 ? "," : "" ) << ENDL;
std::cout << " }" << (i != 31 ? "," : "" ) << ENDL;
}
std::cout << " };" << ENDL;
return true;
}
TEST(print, generators_precomp)
{
#define CALC_PRECOMP(G) calc_and_print_generator_precomp(G, #G)
CALC_PRECOMP(c_point_H);
CALC_PRECOMP(c_point_H2);
CALC_PRECOMP(c_point_U);
CALC_PRECOMP(c_point_X);
CALC_PRECOMP(c_point_H_plus_G);
CALC_PRECOMP(c_point_H_minus_G);
return true;
#undef CALC_PRECOMP
}
bool check_generator_precomp(const point_pc_t& generator, const char* generator_var_name)
{
point_t generator_pt = generator; // to avoid using precomputed data in scalar multiplications
point_t random_point = hash_helper_t::hp(scalar_t::random());
point_t A = generator_pt;
for(size_t i = 0; i < 32; ++i)
{
point_t B = c_point_0;
for(size_t j = 0; j < 8; ++j)
{
B += A;
// restore ge_p3 from ge_precomp using native NaCl functions...
point_t restored_pt{};
ge_p1p1 p1p1{};
ge_madd(&p1p1, &random_point.m_p3, &((*generator.m_precomp_data_p)[i][j]));
ge_p1p1_to_p3(&restored_pt.m_p3, &p1p1);
restored_pt -= random_point;
// ...and compare it with the calculated one
if (B != restored_pt)
{
std::cout << "ERROR: " << generator_var_name << ", i: " << i << ", j: " << j << ENDL;
return false;
}
}
if (i != 31)
A.modify_mul_pow_2(8);
}
std::cout << " " << std::left << std::setw(32) << generator_var_name << " OK" << ENDL;
return true;
}
TEST(crypto, generators_precomp)
{
#define CHECK_PRECOMP(G) ASSERT_TRUE(check_generator_precomp(G, #G))
CHECK_PRECOMP(c_point_H);
CHECK_PRECOMP(c_point_H2);
CHECK_PRECOMP(c_point_U);
CHECK_PRECOMP(c_point_X);
CHECK_PRECOMP(c_point_H_plus_G);
CHECK_PRECOMP(c_point_H_minus_G);
return true;
#undef CHECK_PRECOMP
}
//
// test's runner
//

View file

@ -2,7 +2,7 @@
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#pragma once
#include <numeric>
uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_count)
{
@ -20,27 +20,42 @@ uint64_t get_bits_v1(const scalar_t& s, uint8_t bit_index_first, uint8_t bits_co
}
inline std::ostream &operator <<(std::ostream &o, const crypto::ge_precomp v)
TEST(crypto, ge_precomp)
{
o << "{{";
for(size_t i = 0; i < 9; ++i)
o << v.yplusx[i] << ", ";
//precomp_data_t G_precomp = {};
//construct_precomp_data(G_precomp, c_point_G);
//std::cout << "size of G_precomp: " << sizeof G_precomp << " bytes" << ENDL;
//for(size_t i = 0; i < 32; ++i)
// for(size_t j = 0; j < 8; ++j)
// std::cout << "i: " << i << ", j: " << j << ", precomp: " << ENDL << G_precomp[i][j] << ENDL;
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;
precomp_data_t H_precomp = {};
construct_precomp_data(H_precomp, c_point_H);
auto check_for_x = [&](const scalar_t& x) -> bool {
point_t P;
ge_scalarmult_precomp_vartime(&P.m_p3, H_precomp, x.m_s);
return P == x * c_point_H;
};
ASSERT_TRUE(check_for_x(c_scalar_0));
ASSERT_TRUE(check_for_x(c_scalar_1));
ASSERT_TRUE(check_for_x(c_scalar_1div8));
ASSERT_TRUE(check_for_x(c_scalar_Lm1));
ASSERT_TRUE(check_for_x(c_scalar_L));
for(size_t i = 0; i < 1000; ++i)
{
scalar_t x = scalar_t::random();
ASSERT_TRUE(check_for_x(x));
}
return true;
}
TEST(perf, primitives)
{
struct helper
@ -315,7 +330,7 @@ TEST(perf, primitives)
return HASH_64_VEC(points_cached);
});
run("ge_add(p3 + p3)", 50000, [](timer_t& t, size_t rounds) {
run("ge_add(p1p1 = p3 + cached)", 50000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
std::vector<ge_cached> points_cached(rounds);
@ -530,7 +545,7 @@ TEST(perf, primitives)
return HASH_64_VEC(points_p3);
});
run("ge_scalarmult_base()", 5000, [](timer_t& t, size_t rounds) {
run("ge_scalarmult_base()", 10000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
@ -555,6 +570,87 @@ TEST(perf, primitives)
return HASH_64_VEC(points_p3);
});
run("construct_precomp_data()", 300, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
unsigned char s[32] = {};
std::vector<point_t> random_points(rounds);
for (size_t i = 0; i < rounds; ++i)
{
s[0] = i;
ge_p2 p2;
ge_fromfe_frombytes_vartime(&p2, s);
ge_p2_to_p3(&random_points[i].m_p3, &p2);
}
std::vector<ge_p3> points_p3(rounds);
precomp_data_t precomp_data;
uint64_t result = 0;
t.start();
for (size_t i = 0; i < rounds; ++i)
{
construct_precomp_data(precomp_data, random_points[rnd_indecies[i]]);
result ^= (precomp_data[1][1].xy2d[1] + precomp_data[31][7].xy2d[9]);
}
t.stop();
return result;
});
run("ge_scalarmult_precomp_vartime()", 10000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
scalar_t x;
x.make_random();
std::vector<crypto::ec_scalar> scalars(rounds);
for (size_t i = 0; i < rounds; ++i)
{
scalar_t x = x + x + x;
memcpy(&scalars[i].data, x.data(), 32);
}
precomp_data_t precomp_data;
construct_precomp_data(precomp_data, x * c_point_X);
std::vector<ge_p3> points_p3(rounds);
t.start();
for (size_t i = 0; i < rounds; ++i)
{
ge_scalarmult_precomp_vartime(&points_p3[i], precomp_data, (const unsigned char*)&scalars[rnd_indecies[i]]);
}
t.stop();
return HASH_64_VEC(points_p3);
});
run("ge_scalarmult_base_vartime()", 10000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
scalar_t x;
x.make_random();
std::vector<crypto::ec_scalar> 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<ge_p3> points_p3(rounds);
t.start();
for (size_t i = 0; i < rounds; ++i)
{
ge_scalarmult_base_vartime(&points_p3[i], (const unsigned char*)&scalars[rnd_indecies[i]]);
}
t.stop();
return HASH_64_VEC(points_p3);
});
run("ge_mul8_p3()", 5000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
@ -738,5 +834,402 @@ TEST(perf, primitives)
return HASH_64_VEC(result);
});
run("get_bits x 10", 20000, [](timer_t& t, size_t rounds) {
std::vector<size_t> rnd_indecies;
helper::make_rnd_indicies(rnd_indecies, rounds);
scalar_vec_t data;
data.resize_and_make_random(rounds);
std::vector<uint64_t> result(rounds);
t.start();
for (size_t i = 0; i < rounds; ++i)
{
auto& x = data[rnd_indecies[i]];
result[i] =
x.get_bits(x.m_s[11], x.m_s[21] % 65) ^
x.get_bits(x.m_s[12], x.m_s[22] % 65) ^
x.get_bits(x.m_s[13], x.m_s[23] % 65) ^
x.get_bits(x.m_s[14], x.m_s[24] % 65) ^
x.get_bits(x.m_s[15], x.m_s[25] % 65) ^
x.get_bits(x.m_s[16], x.m_s[26] % 65) ^
x.get_bits(x.m_s[17], x.m_s[27] % 65) ^
x.get_bits(x.m_s[18], x.m_s[28] % 65) ^
x.get_bits(x.m_s[19], x.m_s[29] % 65) ^
x.get_bits(x.m_s[20], x.m_s[30] % 65);
}
t.stop();
return HASH_64_VEC(result);
});
return true;
} // TEST
////////////////////////////////////////////////////////////////////////////////
///////////////// v3
///////////////// v4
template<typename CT>
bool msm_and_check_zero_pippenger_v4(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
{
// TODO: with c = 8 and with direct access got much worse result than with c = 7 and get_bits(), consider checking again for bigger datasets (N>256)
CHECK_AND_ASSERT_MES(g_scalars.size() <= CT::c_bpp_mn_max, false, "g_scalars oversized");
CHECK_AND_ASSERT_MES(h_scalars.size() <= CT::c_bpp_mn_max, false, "h_scalars oversized");
CHECK_AND_ASSERT_MES(c < 10, false, "c is too big");
size_t C = 1ull << c;
// k_max * c + (c-1) >= max_bit_idx
//
// max_bit_idx - (c - 1) max_bit_idx - (c - 1) + (c - 1) max_bit_idx
// k_max = ceil ( --------------------- ) = floor ( ------------------------------ ) = floor ( ----------- )
// c c c
const size_t b = 253; // the maximum number of bits in x https://eprint.iacr.org/2022/999.pdf TODO: we may also scan for maximum bit used in all the scalars if all the scalars are small
const size_t max_bit_idx = b - 1;
const size_t k_max = max_bit_idx / c;
const size_t K = k_max + 1;
std::unique_ptr<point_t[]> buckets( new point_t[C * K] );
std::vector<bool> buckets_inited(C * K);
// first loop, calculate partial bucket sums
for (size_t n = 0; n < g_scalars.size(); ++n)
{
for (size_t k = 0; k < K; ++k)
{
uint64_t l = g_scalars[n].get_bits(k * c, c); // l in [0; 2^c-1]
if (l != 0)
{
size_t bucket_id = l * K + k;
if (buckets_inited[bucket_id])
buckets[bucket_id] += CT::get_generator(false, n);
else
{
buckets[bucket_id] = CT::get_generator(false, n);
buckets_inited[bucket_id] = true;
}
}
}
}
for (size_t n = 0; n < h_scalars.size(); ++n)
{
for (size_t k = 0; k < K; ++k)
{
uint64_t l = h_scalars[n].get_bits(k * c, c); // l in [0; 2^c-1]
if (l != 0)
{
size_t bucket_id = l * K + k;
if (buckets_inited[bucket_id])
buckets[bucket_id] += CT::get_generator(true, n);
else
{
buckets[bucket_id] = CT::get_generator(true, n);
buckets_inited[bucket_id] = true;
}
}
}
}
// the second loop
// S[l, k] = S[l-1, k] + B[l, k]
// G[k] = sum{1..C-1} S[l, k]
std::unique_ptr<point_t[]> Sk( new point_t[K] );
std::vector<bool> Sk_inited(K);
std::unique_ptr<point_t[]> Gk( new point_t[K] );
std::vector<bool> Gk_inited(K);
for (size_t l = C - 1; l > 0; --l)
{
for (size_t k = 0; k < K; ++k)
{
size_t bucket_id = l * K + k;
if (buckets_inited[bucket_id])
{
if (Sk_inited[k])
Sk[k] += buckets[bucket_id];
else
{
Sk[k] = buckets[bucket_id];
Sk_inited[k] = true;
}
}
if (Sk_inited[k])
{
if (Gk_inited[k])
Gk[k] += Sk[k];
else
{
Gk[k] = Sk[k];
Gk_inited[k] = true;
}
}
}
}
// the third loop: Horners rule
point_t result = Gk_inited[K - 1] ? Gk[K - 1] : c_point_0;
for (size_t k = K - 2; k != SIZE_MAX; --k)
{
result.modify_mul_pow_2(c);
if (Gk_inited[k])
result += Gk[k];
}
result += summand;
if (!result.is_zero())
{
LOG_PRINT_L0("msm result is non zero: " << result);
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
//template<typename CT>
//struct mes_msm_and_check_zero_pippenger_v1
//{
// static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
// {
// return msm_and_check_zero_pippenger_v1<CT>(g_scalars, h_scalars, summand, c);
// }
//};
//
//template<typename CT>
//struct mes_msm_and_check_zero_pippenger_v2
//{
// static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
// {
// return msm_and_check_zero_pippenger_v2<CT>(g_scalars, h_scalars, summand, c);
// }
//};
template<typename CT>
struct mes_msm_and_check_zero_pippenger_v3
{
static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
{
return msm_and_check_zero_pippenger_v3<CT>(g_scalars, h_scalars, summand, c);
}
};
template<typename CT>
struct mes_msm_and_check_zero_pippenger_v4
{
static bool msm_and_check_zero(const scalar_vec_t& g_scalars, const scalar_vec_t& h_scalars, const point_t& summand, size_t c)
{
return msm_and_check_zero_pippenger_v4<CT>(g_scalars, h_scalars, summand, c);
}
};
struct pme_runner_i
{
virtual ~pme_runner_i() {}
virtual bool iteration(bool warmup) = 0;
};
template<size_t N, typename CT, template<typename> typename selector_t>
struct pme_runner_t : public pme_runner_i
{
pme_runner_t(const char* testname_, size_t pip_partition_bits_c)
: testname(testname_)
, pip_partition_bits_c(pip_partition_bits_c)
{
testname += std::string(", ") + std::string(typeid(selector_t<CT>).name()).erase(0, 11) + std::string(", c = ") + epee::string_tools::num_to_string_fast(pip_partition_bits_c);
std::cout << testname << ENDL;
}
virtual ~pme_runner_t()
{
if (timings.empty())
return;
uint64_t median = 0;
auto median_it = timings.begin() + timings.size() / 2;
std::nth_element(timings.begin(), median_it, timings.end());
median = *median_it;
if (timings.size() % 2 == 0)
{
auto max_it = std::max_element(timings.begin(), median_it);
median = (median + *max_it) / 2;
}
uint64_t total_time = std::accumulate(timings.begin(), timings.end(), 0);
std::cout << std::left << std::setw(100) << testname << " : " << std::setw(5) << median << " (median), " << std::setw(5) << total_time / timings.size() << " (avg), mcs" << ENDL;
}
virtual bool iteration(bool warmup)
{
scalar_vec_t g_scalars, h_scalars;
g_scalars.resize_and_make_random(N);
g_scalars[0] = c_scalar_Lm1;
//std::cout << "bit 251: " << g_scalars[0].get_bit(251) << ", bit 252: " << g_scalars[0].get_bit(252) << ENDL;
h_scalars.resize_and_make_random(N);
point_t sum = c_point_0;
for(size_t i = 0; i < N; ++i)
{
//g_scalars[i].m_u64[3] = 0;
//h_scalars[i].m_u64[3] = 0;
//g_scalars[i].m_s[31] = 0;
//h_scalars[i].m_s[31] = 0;
sum += g_scalars[i] * CT::get_generator(false, i) + h_scalars[i] * CT::get_generator(true, i);
}
TIME_MEASURE_START(t);
bool r = selector_t<CT>::msm_and_check_zero(g_scalars, h_scalars, -sum, pip_partition_bits_c);
TIME_MEASURE_FINISH(t);
ASSERT_TRUE(r);
if (!warmup)
timings.push_back(t);
return true;
}
std::vector<uint64_t> timings;
std::string testname;
size_t pip_partition_bits_c;
};
TEST(perf, msm)
{
bool r = false;
std::deque<std::unique_ptr<pme_runner_i>> runners;
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 1));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 2));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 3));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 4));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 5));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 6));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 8));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 9));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 1));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 2));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 3));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 4));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 5));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 6));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 8));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 9));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 1));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 2));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 3));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 4));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 5));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 6));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 8));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v2> >("Zarcanum, BPPE, 128", 9));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 1));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 2));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 3));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 4));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 5));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 6));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 8));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v2> >("ZC out, BPP, 256", 9));
runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v3> >("Zarcanum, BPPE, 128 +++++++++++", 7));
runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v3> >("ZC out, BPP, 256 +++++++++++", 7));
runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v4> >("Zarcanum, BPPE, 128 ###########", 7));
runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v4> >("ZC out, BPP, 256 ###########", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<128, bpp_crypto_trait_Zarcanum, mes_msm_and_check_zero_pippenger_v1> >("Zarcanum, BPPE, 128", 7));
//runners.emplace_front(std::make_unique< pme_runner_t<256, bpp_crypto_trait_ZC_out, mes_msm_and_check_zero_pippenger_v1> >("ZC out, BPP, 256", 7));
std::cout << "warm up..." << ENDL;
size_t runs_count = 30;
for(size_t k = 0; k < runs_count; ++k)
{
for(auto& runner : runners)
ASSERT_TRUE(runner->iteration(true));
}
runs_count = 200;
for(size_t k = 0; k < runs_count; ++k)
{
for(auto& runner : runners)
ASSERT_TRUE(runner->iteration(false));
size_t done_percent = 100 * k / runs_count;
if (100 * (k + 1) / runs_count > done_percent && done_percent % 5 == 0)
std::cout << done_percent << " %" << ENDL;
}
return true;
}
template<typename T>
bool perf_generators_runner(const T& generator, const char* title)
{
const size_t warmup_rounds = 20;
const size_t rounds = 500;
const size_t inner_rounds = 128;
uint64_t h = 0;
std::vector<uint64_t> timings;
size_t N = 1024;
scalar_vec_t scalars;
scalars.resize_and_make_random(N);
std::vector<point_t> points(N);
for(size_t i = 0; i < warmup_rounds; ++i)
for(size_t j = 0; j < inner_rounds; ++j)
points[(i + j) % N] = scalars[(i + j) % N] * generator;
h = hash_64(points.data(), points.size() * sizeof(point_t));
for(size_t i = 0; i < rounds; ++i)
{
TIME_MEASURE_START(t);
for(size_t j = 0; j < inner_rounds; ++j)
points[(i + j) % N] = scalars[(i + j) % N] * generator;
TIME_MEASURE_FINISH(t);
timings.push_back(t);
}
h ^= hash_64(points.data(), points.size() * sizeof(point_t));
std::cout << std::left << std::setw(20) << title << " : " << std::setw(5) << std::fixed << std::setprecision(1) << (double)epee::misc_utils::median(timings) / inner_rounds << " mcs, hash = " << h << ENDL;
return true;
}
TEST(perf, generators)
{
#define TEST_GENERATOR(G) ASSERT_TRUE(perf_generators_runner(G, #G))
TEST_GENERATOR(c_point_0);
TEST_GENERATOR(c_point_G);
TEST_GENERATOR(c_point_H);
TEST_GENERATOR(c_point_H2);
TEST_GENERATOR(c_point_U);
TEST_GENERATOR(c_point_X);
TEST_GENERATOR(c_point_H_plus_G);
TEST_GENERATOR(c_point_H_minus_G);
return true;
}