Merge branch 'develop' into atomics
This commit is contained in:
commit
54bf59ceab
15 changed files with 4268 additions and 550 deletions
|
|
@ -21,8 +21,8 @@ namespace tools
|
|||
};
|
||||
|
||||
#ifndef TESTNET
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_95_900000.pak", "1c748d0f90fb1ed0af0ffe59d4b8f6046b2d0f92a8b8fe21932208829733f053", 1097493715, 2147450880 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_95_900000.pak", "f2d498ed7abf641824eca4ce584c756d6138d670980c1abdddcdf07343f10bfc", 1406827811, 2079617024 };
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "http://95.217.43.225/pre-download/zano_mdbx_95_1000000.pak", "6b0bbba85bc420eaae5ec68373e528f70bffaa17fb111c796e951d06ad71e4fe", 1104150892, 2147450880 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "http://95.217.43.225/pre-download/zano_lmdb_95_1000000.pak", "b4d45c727dbf1b92671f9fd1a9624e79019e890bd3d33cb71e011ab4bcb0d21e", 1450748151, 2114449408 };
|
||||
#else
|
||||
static constexpr pre_download_entry c_pre_download_mdbx = { "", "", 0, 0 };
|
||||
static constexpr pre_download_entry c_pre_download_lmdb = { "", "", 0, 0 };
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright (c) 2018-2020 Zano Project
|
||||
// Copyright (c) 2018-2021 Zano Project
|
||||
// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -341,6 +342,16 @@ int fe_isnonzero(const fe f) {
|
|||
s[27] | s[28] | s[29] | s[30] | s[31]) - 1) >> 8) + 1;
|
||||
}
|
||||
|
||||
int fe_cmp(const fe a, const fe b)
|
||||
{
|
||||
for (size_t i = 9; i != SIZE_MAX; --i)
|
||||
{
|
||||
if ((const uint32_t)a[i] < (const uint32_t)b[i]) return -1;
|
||||
if ((const uint32_t)a[i] > (const uint32_t)b[i]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* From fe_mul.c */
|
||||
|
||||
/*
|
||||
|
|
@ -1234,6 +1245,96 @@ void ge_double_scalarmult_base_vartime(ge_p2 *r, const unsigned char *a, const g
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
r = a * A + b * B
|
||||
where a = a[0]+256*a[1]+...+256^31 a[31].
|
||||
and b = b[0]+256*b[1]+...+256^31 b[31].
|
||||
B is the Ed25519 base point (x,4/5) with x positive.
|
||||
*/
|
||||
|
||||
void ge_double_scalarmult_base_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
|
||||
signed char aslide[256];
|
||||
signed char bslide[256];
|
||||
ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */
|
||||
ge_p1p1 t;
|
||||
ge_p3 u;
|
||||
ge_p2 r_p2;
|
||||
int i;
|
||||
|
||||
slide(aslide, a);
|
||||
slide(bslide, b);
|
||||
ge_dsm_precomp(Ai, A);
|
||||
|
||||
ge_p2_0(&r_p2);
|
||||
|
||||
for (i = 255; i >= 0; --i) {
|
||||
if (aslide[i] || bslide[i]) break;
|
||||
}
|
||||
|
||||
for (; i >= 0; --i) {
|
||||
ge_p2_dbl(&t, &r_p2);
|
||||
|
||||
if (aslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ai[aslide[i]/2]);
|
||||
} else if (aslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ai[(-aslide[i])/2]);
|
||||
}
|
||||
|
||||
if (bslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_madd(&t, &u, &ge_Bi[bslide[i]/2]);
|
||||
} else if (bslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_msub(&t, &u, &ge_Bi[(-bslide[i])/2]);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
ge_p1p1_to_p2(&r_p2, &t);
|
||||
else
|
||||
ge_p1p1_to_p3(r, &t); // last step
|
||||
}
|
||||
}
|
||||
|
||||
void ge_scalarmult_vartime_p3(ge_p3 *r, const unsigned char *a, const ge_p3 *A) {
|
||||
signed char aslide[256];
|
||||
ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */
|
||||
ge_p1p1 t;
|
||||
ge_p3 u;
|
||||
ge_p2 r_p2;
|
||||
int i;
|
||||
|
||||
slide(aslide, a);
|
||||
ge_dsm_precomp(Ai, A);
|
||||
|
||||
ge_p2_0(&r_p2);
|
||||
ge_p3_0(r);
|
||||
|
||||
for (i = 255; i >= 0; --i) {
|
||||
if (aslide[i]) break;
|
||||
}
|
||||
|
||||
for (; i >= 0; --i) {
|
||||
ge_p2_dbl(&t, &r_p2);
|
||||
|
||||
if (aslide[i] > 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ai[aslide[i] / 2]);
|
||||
}
|
||||
else if (aslide[i] < 0) {
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
|
||||
}
|
||||
|
||||
if (i != 0)
|
||||
ge_p1p1_to_p2(&r_p2, &t);
|
||||
else
|
||||
ge_p1p1_to_p3(r, &t); // last step
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* From ge_frombytes.c, modified */
|
||||
|
||||
int ge_frombytes_vartime(ge_p3 *h, const unsigned char *s) {
|
||||
|
|
@ -2168,17 +2269,17 @@ void ge_fromfe_frombytes_vartime(ge_p2 *r, const unsigned char *s) {
|
|||
|
||||
/* End fe_frombytes.c */
|
||||
|
||||
fe_sq2(v, u); /* 2 * u^2 */
|
||||
fe_1(w);
|
||||
fe_add(w, v, w); /* w = 2 * u^2 + 1 */
|
||||
fe_sq(x, w); /* w^2 */
|
||||
fe_mul(y, fe_ma2, v); /* -2 * A^2 * u^2 */
|
||||
fe_add(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */
|
||||
fe_divpowm1(r->X, w, x); /* (w / x)^(m + 1) */
|
||||
fe_sq(y, r->X);
|
||||
fe_mul(x, y, x);
|
||||
fe_sub(y, w, x);
|
||||
fe_copy(z, fe_ma);
|
||||
fe_sq2(v, u); /* v = 2 * u^2 */
|
||||
fe_1(w); /* w = 1 */
|
||||
fe_add(w, v, w); /* w = 2 * u^2 + 1 */
|
||||
fe_sq(x, w); /* x = w^2 */
|
||||
fe_mul(y, fe_ma2, v); /* y = -A^2 * (2 * u^2) = -2 * A^2 * u^2 n.b. A = 2 * (1 - d) / (1 + d) = 486662*/
|
||||
fe_add(x, x, y); /* x = w^2 - 2 * A^2 * u^2 */
|
||||
fe_divpowm1(r->X, w, x); /* r->X = (w / x)^(m + 1) */
|
||||
fe_sq(y, r->X); /* y = (w / x)^(2*(m + 1)) */
|
||||
fe_mul(x, y, x); /* x = (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */
|
||||
fe_sub(y, w, x); /* y = 2 * u^2 + 1 - (w / x)^(2*(m + 1)) * (w^2 - 2 * A^2 * u^2) */
|
||||
fe_copy(z, fe_ma); /* z = -A */
|
||||
if (fe_isnonzero(y)) {
|
||||
fe_add(y, w, x);
|
||||
if (fe_isnonzero(y)) {
|
||||
|
|
@ -3522,6 +3623,494 @@ void sc_mul(unsigned char* s, const unsigned char* a, const unsigned char* b)
|
|||
s[31] = s11 >> 17;
|
||||
}
|
||||
|
||||
/* libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c */
|
||||
/*
|
||||
Input:
|
||||
a[0]+256*a[1]+...+256^31*a[31] = a
|
||||
b[0]+256*b[1]+...+256^31*b[31] = b
|
||||
c[0]+256*c[1]+...+256^31*c[31] = c
|
||||
*
|
||||
Output:
|
||||
s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
|
||||
where l = 2^252 + 27742317777372353535851937790883648493.
|
||||
*/
|
||||
void sc_muladd(unsigned char* s, const unsigned char* a,
|
||||
const unsigned char* b, const unsigned char* c)
|
||||
{
|
||||
int64_t a0 = 2097151 & load_3(a);
|
||||
int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
|
||||
int64_t a2 = 2097151 & (load_3(a + 5) >> 2);
|
||||
int64_t a3 = 2097151 & (load_4(a + 7) >> 7);
|
||||
int64_t a4 = 2097151 & (load_4(a + 10) >> 4);
|
||||
int64_t a5 = 2097151 & (load_3(a + 13) >> 1);
|
||||
int64_t a6 = 2097151 & (load_4(a + 15) >> 6);
|
||||
int64_t a7 = 2097151 & (load_3(a + 18) >> 3);
|
||||
int64_t a8 = 2097151 & load_3(a + 21);
|
||||
int64_t a9 = 2097151 & (load_4(a + 23) >> 5);
|
||||
int64_t a10 = 2097151 & (load_3(a + 26) >> 2);
|
||||
int64_t a11 = (load_4(a + 28) >> 7);
|
||||
|
||||
int64_t b0 = 2097151 & load_3(b);
|
||||
int64_t b1 = 2097151 & (load_4(b + 2) >> 5);
|
||||
int64_t b2 = 2097151 & (load_3(b + 5) >> 2);
|
||||
int64_t b3 = 2097151 & (load_4(b + 7) >> 7);
|
||||
int64_t b4 = 2097151 & (load_4(b + 10) >> 4);
|
||||
int64_t b5 = 2097151 & (load_3(b + 13) >> 1);
|
||||
int64_t b6 = 2097151 & (load_4(b + 15) >> 6);
|
||||
int64_t b7 = 2097151 & (load_3(b + 18) >> 3);
|
||||
int64_t b8 = 2097151 & load_3(b + 21);
|
||||
int64_t b9 = 2097151 & (load_4(b + 23) >> 5);
|
||||
int64_t b10 = 2097151 & (load_3(b + 26) >> 2);
|
||||
int64_t b11 = (load_4(b + 28) >> 7);
|
||||
|
||||
int64_t c0 = 2097151 & load_3(c);
|
||||
int64_t c1 = 2097151 & (load_4(c + 2) >> 5);
|
||||
int64_t c2 = 2097151 & (load_3(c + 5) >> 2);
|
||||
int64_t c3 = 2097151 & (load_4(c + 7) >> 7);
|
||||
int64_t c4 = 2097151 & (load_4(c + 10) >> 4);
|
||||
int64_t c5 = 2097151 & (load_3(c + 13) >> 1);
|
||||
int64_t c6 = 2097151 & (load_4(c + 15) >> 6);
|
||||
int64_t c7 = 2097151 & (load_3(c + 18) >> 3);
|
||||
int64_t c8 = 2097151 & load_3(c + 21);
|
||||
int64_t c9 = 2097151 & (load_4(c + 23) >> 5);
|
||||
int64_t c10 = 2097151 & (load_3(c + 26) >> 2);
|
||||
int64_t c11 = (load_4(c + 28) >> 7);
|
||||
|
||||
int64_t s0;
|
||||
int64_t s1;
|
||||
int64_t s2;
|
||||
int64_t s3;
|
||||
int64_t s4;
|
||||
int64_t s5;
|
||||
int64_t s6;
|
||||
int64_t s7;
|
||||
int64_t s8;
|
||||
int64_t s9;
|
||||
int64_t s10;
|
||||
int64_t s11;
|
||||
int64_t s12;
|
||||
int64_t s13;
|
||||
int64_t s14;
|
||||
int64_t s15;
|
||||
int64_t s16;
|
||||
int64_t s17;
|
||||
int64_t s18;
|
||||
int64_t s19;
|
||||
int64_t s20;
|
||||
int64_t s21;
|
||||
int64_t s22;
|
||||
int64_t s23;
|
||||
|
||||
int64_t carry0;
|
||||
int64_t carry1;
|
||||
int64_t carry2;
|
||||
int64_t carry3;
|
||||
int64_t carry4;
|
||||
int64_t carry5;
|
||||
int64_t carry6;
|
||||
int64_t carry7;
|
||||
int64_t carry8;
|
||||
int64_t carry9;
|
||||
int64_t carry10;
|
||||
int64_t carry11;
|
||||
int64_t carry12;
|
||||
int64_t carry13;
|
||||
int64_t carry14;
|
||||
int64_t carry15;
|
||||
int64_t carry16;
|
||||
int64_t carry17;
|
||||
int64_t carry18;
|
||||
int64_t carry19;
|
||||
int64_t carry20;
|
||||
int64_t carry21;
|
||||
int64_t carry22;
|
||||
|
||||
s0 = c0 + a0 * b0;
|
||||
s1 = c1 + a0 * b1 + a1 * b0;
|
||||
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
|
||||
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
|
||||
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
|
||||
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
|
||||
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 +
|
||||
a6 * b0;
|
||||
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 +
|
||||
a6 * b1 + a7 * b0;
|
||||
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 +
|
||||
a6 * b2 + a7 * b1 + a8 * b0;
|
||||
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 +
|
||||
a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
|
||||
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 +
|
||||
a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
|
||||
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 +
|
||||
a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
|
||||
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 +
|
||||
a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
|
||||
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 +
|
||||
a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
|
||||
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 +
|
||||
a9 * b5 + a10 * b4 + a11 * b3;
|
||||
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 +
|
||||
a10 * b5 + a11 * b4;
|
||||
s16 =
|
||||
a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
|
||||
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
|
||||
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
|
||||
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
|
||||
s20 = a9 * b11 + a10 * b10 + a11 * b9;
|
||||
s21 = a10 * b11 + a11 * b10;
|
||||
s22 = a11 * b11;
|
||||
s23 = 0;
|
||||
|
||||
carry0 = (s0 + (int64_t)(1L << 20)) >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 * ((uint64_t)1L << 21);
|
||||
carry2 = (s2 + (int64_t)(1L << 20)) >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 * ((uint64_t)1L << 21);
|
||||
carry4 = (s4 + (int64_t)(1L << 20)) >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 * ((uint64_t)1L << 21);
|
||||
carry6 = (s6 + (int64_t)(1L << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 * ((uint64_t)1L << 21);
|
||||
carry8 = (s8 + (int64_t)(1L << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 * ((uint64_t)1L << 21);
|
||||
carry10 = (s10 + (int64_t)(1L << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 * ((uint64_t)1L << 21);
|
||||
carry12 = (s12 + (int64_t)(1L << 20)) >> 21;
|
||||
s13 += carry12;
|
||||
s12 -= carry12 * ((uint64_t)1L << 21);
|
||||
carry14 = (s14 + (int64_t)(1L << 20)) >> 21;
|
||||
s15 += carry14;
|
||||
s14 -= carry14 * ((uint64_t)1L << 21);
|
||||
carry16 = (s16 + (int64_t)(1L << 20)) >> 21;
|
||||
s17 += carry16;
|
||||
s16 -= carry16 * ((uint64_t)1L << 21);
|
||||
carry18 = (s18 + (int64_t)(1L << 20)) >> 21;
|
||||
s19 += carry18;
|
||||
s18 -= carry18 * ((uint64_t)1L << 21);
|
||||
carry20 = (s20 + (int64_t)(1L << 20)) >> 21;
|
||||
s21 += carry20;
|
||||
s20 -= carry20 * ((uint64_t)1L << 21);
|
||||
carry22 = (s22 + (int64_t)(1L << 20)) >> 21;
|
||||
s23 += carry22;
|
||||
s22 -= carry22 * ((uint64_t)1L << 21);
|
||||
|
||||
carry1 = (s1 + (int64_t)(1L << 20)) >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 * ((uint64_t)1L << 21);
|
||||
carry3 = (s3 + (int64_t)(1L << 20)) >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 * ((uint64_t)1L << 21);
|
||||
carry5 = (s5 + (int64_t)(1L << 20)) >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 * ((uint64_t)1L << 21);
|
||||
carry7 = (s7 + (int64_t)(1L << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 * ((uint64_t)1L << 21);
|
||||
carry9 = (s9 + (int64_t)(1L << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 * ((uint64_t)1L << 21);
|
||||
carry11 = (s11 + (int64_t)(1L << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 * ((uint64_t)1L << 21);
|
||||
carry13 = (s13 + (int64_t)(1L << 20)) >> 21;
|
||||
s14 += carry13;
|
||||
s13 -= carry13 * ((uint64_t)1L << 21);
|
||||
carry15 = (s15 + (int64_t)(1L << 20)) >> 21;
|
||||
s16 += carry15;
|
||||
s15 -= carry15 * ((uint64_t)1L << 21);
|
||||
carry17 = (s17 + (int64_t)(1L << 20)) >> 21;
|
||||
s18 += carry17;
|
||||
s17 -= carry17 * ((uint64_t)1L << 21);
|
||||
carry19 = (s19 + (int64_t)(1L << 20)) >> 21;
|
||||
s20 += carry19;
|
||||
s19 -= carry19 * ((uint64_t)1L << 21);
|
||||
carry21 = (s21 + (int64_t)(1L << 20)) >> 21;
|
||||
s22 += carry21;
|
||||
s21 -= carry21 * ((uint64_t)1L << 21);
|
||||
|
||||
s11 += s23 * 666643;
|
||||
s12 += s23 * 470296;
|
||||
s13 += s23 * 654183;
|
||||
s14 -= s23 * 997805;
|
||||
s15 += s23 * 136657;
|
||||
s16 -= s23 * 683901;
|
||||
|
||||
s10 += s22 * 666643;
|
||||
s11 += s22 * 470296;
|
||||
s12 += s22 * 654183;
|
||||
s13 -= s22 * 997805;
|
||||
s14 += s22 * 136657;
|
||||
s15 -= s22 * 683901;
|
||||
|
||||
s9 += s21 * 666643;
|
||||
s10 += s21 * 470296;
|
||||
s11 += s21 * 654183;
|
||||
s12 -= s21 * 997805;
|
||||
s13 += s21 * 136657;
|
||||
s14 -= s21 * 683901;
|
||||
|
||||
s8 += s20 * 666643;
|
||||
s9 += s20 * 470296;
|
||||
s10 += s20 * 654183;
|
||||
s11 -= s20 * 997805;
|
||||
s12 += s20 * 136657;
|
||||
s13 -= s20 * 683901;
|
||||
|
||||
s7 += s19 * 666643;
|
||||
s8 += s19 * 470296;
|
||||
s9 += s19 * 654183;
|
||||
s10 -= s19 * 997805;
|
||||
s11 += s19 * 136657;
|
||||
s12 -= s19 * 683901;
|
||||
|
||||
s6 += s18 * 666643;
|
||||
s7 += s18 * 470296;
|
||||
s8 += s18 * 654183;
|
||||
s9 -= s18 * 997805;
|
||||
s10 += s18 * 136657;
|
||||
s11 -= s18 * 683901;
|
||||
|
||||
carry6 = (s6 + (int64_t)(1L << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 * ((uint64_t)1L << 21);
|
||||
carry8 = (s8 + (int64_t)(1L << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 * ((uint64_t)1L << 21);
|
||||
carry10 = (s10 + (int64_t)(1L << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 * ((uint64_t)1L << 21);
|
||||
carry12 = (s12 + (int64_t)(1L << 20)) >> 21;
|
||||
s13 += carry12;
|
||||
s12 -= carry12 * ((uint64_t)1L << 21);
|
||||
carry14 = (s14 + (int64_t)(1L << 20)) >> 21;
|
||||
s15 += carry14;
|
||||
s14 -= carry14 * ((uint64_t)1L << 21);
|
||||
carry16 = (s16 + (int64_t)(1L << 20)) >> 21;
|
||||
s17 += carry16;
|
||||
s16 -= carry16 * ((uint64_t)1L << 21);
|
||||
|
||||
carry7 = (s7 + (int64_t)(1L << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 * ((uint64_t)1L << 21);
|
||||
carry9 = (s9 + (int64_t)(1L << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 * ((uint64_t)1L << 21);
|
||||
carry11 = (s11 + (int64_t)(1L << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 * ((uint64_t)1L << 21);
|
||||
carry13 = (s13 + (int64_t)(1L << 20)) >> 21;
|
||||
s14 += carry13;
|
||||
s13 -= carry13 * ((uint64_t)1L << 21);
|
||||
carry15 = (s15 + (int64_t)(1L << 20)) >> 21;
|
||||
s16 += carry15;
|
||||
s15 -= carry15 * ((uint64_t)1L << 21);
|
||||
|
||||
s5 += s17 * 666643;
|
||||
s6 += s17 * 470296;
|
||||
s7 += s17 * 654183;
|
||||
s8 -= s17 * 997805;
|
||||
s9 += s17 * 136657;
|
||||
s10 -= s17 * 683901;
|
||||
|
||||
s4 += s16 * 666643;
|
||||
s5 += s16 * 470296;
|
||||
s6 += s16 * 654183;
|
||||
s7 -= s16 * 997805;
|
||||
s8 += s16 * 136657;
|
||||
s9 -= s16 * 683901;
|
||||
|
||||
s3 += s15 * 666643;
|
||||
s4 += s15 * 470296;
|
||||
s5 += s15 * 654183;
|
||||
s6 -= s15 * 997805;
|
||||
s7 += s15 * 136657;
|
||||
s8 -= s15 * 683901;
|
||||
|
||||
s2 += s14 * 666643;
|
||||
s3 += s14 * 470296;
|
||||
s4 += s14 * 654183;
|
||||
s5 -= s14 * 997805;
|
||||
s6 += s14 * 136657;
|
||||
s7 -= s14 * 683901;
|
||||
|
||||
s1 += s13 * 666643;
|
||||
s2 += s13 * 470296;
|
||||
s3 += s13 * 654183;
|
||||
s4 -= s13 * 997805;
|
||||
s5 += s13 * 136657;
|
||||
s6 -= s13 * 683901;
|
||||
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
s3 -= s12 * 997805;
|
||||
s4 += s12 * 136657;
|
||||
s5 -= s12 * 683901;
|
||||
s12 = 0;
|
||||
|
||||
carry0 = (s0 + (int64_t)(1L << 20)) >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 * ((uint64_t)1L << 21);
|
||||
carry2 = (s2 + (int64_t)(1L << 20)) >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 * ((uint64_t)1L << 21);
|
||||
carry4 = (s4 + (int64_t)(1L << 20)) >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 * ((uint64_t)1L << 21);
|
||||
carry6 = (s6 + (int64_t)(1L << 20)) >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 * ((uint64_t)1L << 21);
|
||||
carry8 = (s8 + (int64_t)(1L << 20)) >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 * ((uint64_t)1L << 21);
|
||||
carry10 = (s10 + (int64_t)(1L << 20)) >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 * ((uint64_t)1L << 21);
|
||||
|
||||
carry1 = (s1 + (int64_t)(1L << 20)) >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 * ((uint64_t)1L << 21);
|
||||
carry3 = (s3 + (int64_t)(1L << 20)) >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 * ((uint64_t)1L << 21);
|
||||
carry5 = (s5 + (int64_t)(1L << 20)) >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 * ((uint64_t)1L << 21);
|
||||
carry7 = (s7 + (int64_t)(1L << 20)) >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 * ((uint64_t)1L << 21);
|
||||
carry9 = (s9 + (int64_t)(1L << 20)) >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 * ((uint64_t)1L << 21);
|
||||
carry11 = (s11 + (int64_t)(1L << 20)) >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 * ((uint64_t)1L << 21);
|
||||
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
s3 -= s12 * 997805;
|
||||
s4 += s12 * 136657;
|
||||
s5 -= s12 * 683901;
|
||||
s12 = 0;
|
||||
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 * ((uint64_t)1L << 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 * ((uint64_t)1L << 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 * ((uint64_t)1L << 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 * ((uint64_t)1L << 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 * ((uint64_t)1L << 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 * ((uint64_t)1L << 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 * ((uint64_t)1L << 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 * ((uint64_t)1L << 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 * ((uint64_t)1L << 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 * ((uint64_t)1L << 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 * ((uint64_t)1L << 21);
|
||||
carry11 = s11 >> 21;
|
||||
s12 += carry11;
|
||||
s11 -= carry11 * ((uint64_t)1L << 21);
|
||||
|
||||
s0 += s12 * 666643;
|
||||
s1 += s12 * 470296;
|
||||
s2 += s12 * 654183;
|
||||
s3 -= s12 * 997805;
|
||||
s4 += s12 * 136657;
|
||||
s5 -= s12 * 683901;
|
||||
|
||||
carry0 = s0 >> 21;
|
||||
s1 += carry0;
|
||||
s0 -= carry0 * ((uint64_t)1L << 21);
|
||||
carry1 = s1 >> 21;
|
||||
s2 += carry1;
|
||||
s1 -= carry1 * ((uint64_t)1L << 21);
|
||||
carry2 = s2 >> 21;
|
||||
s3 += carry2;
|
||||
s2 -= carry2 * ((uint64_t)1L << 21);
|
||||
carry3 = s3 >> 21;
|
||||
s4 += carry3;
|
||||
s3 -= carry3 * ((uint64_t)1L << 21);
|
||||
carry4 = s4 >> 21;
|
||||
s5 += carry4;
|
||||
s4 -= carry4 * ((uint64_t)1L << 21);
|
||||
carry5 = s5 >> 21;
|
||||
s6 += carry5;
|
||||
s5 -= carry5 * ((uint64_t)1L << 21);
|
||||
carry6 = s6 >> 21;
|
||||
s7 += carry6;
|
||||
s6 -= carry6 * ((uint64_t)1L << 21);
|
||||
carry7 = s7 >> 21;
|
||||
s8 += carry7;
|
||||
s7 -= carry7 * ((uint64_t)1L << 21);
|
||||
carry8 = s8 >> 21;
|
||||
s9 += carry8;
|
||||
s8 -= carry8 * ((uint64_t)1L << 21);
|
||||
carry9 = s9 >> 21;
|
||||
s10 += carry9;
|
||||
s9 -= carry9 * ((uint64_t)1L << 21);
|
||||
carry10 = s10 >> 21;
|
||||
s11 += carry10;
|
||||
s10 -= carry10 * ((uint64_t)1L << 21);
|
||||
|
||||
s[0] = s0 >> 0;
|
||||
s[1] = s0 >> 8;
|
||||
s[2] = (s0 >> 16) | (s1 * ((uint64_t)1 << 5));
|
||||
s[3] = s1 >> 3;
|
||||
s[4] = s1 >> 11;
|
||||
s[5] = (s1 >> 19) | (s2 * ((uint64_t)1 << 2));
|
||||
s[6] = s2 >> 6;
|
||||
s[7] = (s2 >> 14) | (s3 * ((uint64_t)1 << 7));
|
||||
s[8] = s3 >> 1;
|
||||
s[9] = s3 >> 9;
|
||||
s[10] = (s3 >> 17) | (s4 * ((uint64_t)1 << 4));
|
||||
s[11] = s4 >> 4;
|
||||
s[12] = s4 >> 12;
|
||||
s[13] = (s4 >> 20) | (s5 * ((uint64_t)1 << 1));
|
||||
s[14] = s5 >> 7;
|
||||
s[15] = (s5 >> 15) | (s6 * ((uint64_t)1 << 6));
|
||||
s[16] = s6 >> 2;
|
||||
s[17] = s6 >> 10;
|
||||
s[18] = (s6 >> 18) | (s7 * ((uint64_t)1 << 3));
|
||||
s[19] = s7 >> 5;
|
||||
s[20] = s7 >> 13;
|
||||
s[21] = s8 >> 0;
|
||||
s[22] = s8 >> 8;
|
||||
s[23] = (s8 >> 16) | (s9 * ((uint64_t)1 << 5));
|
||||
s[24] = s9 >> 3;
|
||||
s[25] = s9 >> 11;
|
||||
s[26] = (s9 >> 19) | (s10 * ((uint64_t)1 << 2));
|
||||
s[27] = s10 >> 6;
|
||||
s[28] = (s10 >> 14) | (s11 * ((uint64_t)1 << 7));
|
||||
s[29] = s11 >> 1;
|
||||
s[30] = s11 >> 9;
|
||||
s[31] = s11 >> 17;
|
||||
}
|
||||
|
||||
|
||||
// out = z ^ -1 (= z ^ (L - 2) according to Fermat little theorem)
|
||||
void sc_invert(unsigned char* out, const unsigned char* z)
|
||||
{
|
||||
|
|
@ -3744,19 +4333,123 @@ void ge_p2_to_p3(ge_p3 *r, const ge_p2 *t)
|
|||
|
||||
|
||||
/*
|
||||
In: ge_bytes -- points to 32 bytes of data
|
||||
Out: res = Hp(ge_bytes)
|
||||
where Hp = 8 * ge_fromfe_frombytes_vartime(cn_fast_hash(ge_bytes))
|
||||
In: data -- points to 'size' bytes of data
|
||||
Out: res = Hp(data)
|
||||
where Hp = 8 * ge_fromfe_frombytes_vartime(cn_fast_hash(data))
|
||||
*/
|
||||
void ge_bytes_hash_to_ec(ge_p3 *res, const unsigned char *ge_bytes)
|
||||
void ge_bytes_hash_to_ec(ge_p3 *res, const void *data, size_t size)
|
||||
{
|
||||
unsigned char h[HASH_SIZE];
|
||||
ge_p2 point;
|
||||
ge_p1p1 point2;
|
||||
|
||||
cn_fast_hash(ge_bytes, 32, (char*)h);
|
||||
cn_fast_hash(data, size, (char*)h);
|
||||
ge_fromfe_frombytes_vartime(&point, &h[0]);
|
||||
/*ge_p2_to_p3(res, &point); -- can be used to avoid multiplication by 8 for debugging */
|
||||
ge_mul8(&point2, &point);
|
||||
ge_p1p1_to_p3(res, &point2);
|
||||
}
|
||||
|
||||
void ge_bytes_hash_to_ec_32(ge_p3 *res, const unsigned char *ge_bytes)
|
||||
{
|
||||
ge_bytes_hash_to_ec(res, ge_bytes, 32);
|
||||
}
|
||||
|
||||
void ge_mul8_p3(ge_p3 *r, const ge_p3 *t)
|
||||
{
|
||||
ge_p1p1 p1;
|
||||
ge_p2 p2;
|
||||
|
||||
// TODO: consider removing the following copy, replace &p2 by (ge_p2*)t as it's ugly but possible
|
||||
ge_p3_to_p2(&p2, t); // copying
|
||||
|
||||
ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub
|
||||
ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul
|
||||
ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub
|
||||
ge_p1p1_to_p2(&p2, &p1); // 3 fe_mul
|
||||
ge_p2_dbl(&p1, &p2); // 3 fe_sq, 1 fe_sq2, 5 fe_add/sub
|
||||
|
||||
ge_p1p1_to_p3(r, &p1); // 4 fe_mul
|
||||
}
|
||||
|
||||
|
||||
// returns the most non-zero index of r
|
||||
int slide_v2(signed char *r, const unsigned char *a)
|
||||
{
|
||||
int i;
|
||||
int b;
|
||||
int k;
|
||||
int nzi = 0;
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
r[i] = 1 & (a[i >> 3] >> (i & 7));
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; ++i) {
|
||||
if (r[i]) {
|
||||
for (b = 1; b <= 6 && i + b < 256; ++b) {
|
||||
if (r[i + b]) {
|
||||
if (r[i] + (r[i + b] << b) <= 15) {
|
||||
r[i] += r[i + b] << b; r[i + b] = 0;
|
||||
}
|
||||
else if (r[i] - (r[i + b] << b) >= -15) {
|
||||
r[i] -= r[i + b] << b;
|
||||
for (k = i + b; k < 256; ++k) {
|
||||
if (!r[k]) {
|
||||
r[k] = 1;
|
||||
break;
|
||||
}
|
||||
r[k] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r[i])
|
||||
nzi = i;
|
||||
}
|
||||
}
|
||||
|
||||
return nzi;
|
||||
}
|
||||
|
||||
void ge_scalarmult_vartime_p3_v2(ge_p3 *r, const unsigned char *a, const ge_p3 *A)
|
||||
{
|
||||
signed char aslide[256];
|
||||
ge_dsmp Ai; /* A, 3A, 5A, 7A, 9A, 11A, 13A, 15A */
|
||||
ge_p1p1 t;
|
||||
ge_p3 u;
|
||||
ge_p2 r_p2;
|
||||
int i;
|
||||
|
||||
i = slide_v2(aslide, a);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
ge_p3_0(r);
|
||||
return;
|
||||
}
|
||||
|
||||
ge_dsm_precomp(Ai, A);
|
||||
ge_p2_0(&r_p2);
|
||||
|
||||
for (; i >= 0; --i)
|
||||
{
|
||||
ge_p2_dbl(&t, &r_p2);
|
||||
if (aslide[i] > 0)
|
||||
{
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_add(&t, &u, &Ai[aslide[i] / 2]);
|
||||
}
|
||||
else if (aslide[i] < 0)
|
||||
{
|
||||
ge_p1p1_to_p3(&u, &t);
|
||||
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
|
||||
}
|
||||
if (i != 0)
|
||||
ge_p1p1_to_p2(&r_p2, &t);
|
||||
else
|
||||
ge_p1p1_to_p3(r, &t);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (c) 2018-2021 Zano Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
/* From fe.h */
|
||||
|
||||
|
|
@ -104,11 +106,17 @@ void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *);
|
|||
void ge_scalarmult_p3(ge_p3 *, const unsigned char *, const ge_p3 *);
|
||||
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp);
|
||||
void ge_mul8(ge_p1p1 *, const ge_p2 *);
|
||||
void ge_mul8_p3(ge_p3 *, const ge_p3 *);
|
||||
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *);
|
||||
void ge_bytes_hash_to_ec(ge_p3 *, const unsigned char *);
|
||||
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_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);
|
||||
|
||||
extern const fe fe_ma2;
|
||||
extern const fe fe_ma;
|
||||
|
|
@ -123,12 +131,14 @@ void sc_add(unsigned char *, const unsigned char *, const unsigned char *);
|
|||
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *);
|
||||
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *);
|
||||
void sc_mul(unsigned char *, const unsigned char *, const unsigned char *);
|
||||
void sc_muladd(unsigned char* s, const unsigned char* a, const unsigned char* b, const unsigned char* c);
|
||||
int sc_check(const unsigned char *);
|
||||
int sc_isnonzero(const unsigned char *); /* Doesn't normalize */
|
||||
void sc_invert(unsigned char*, const unsigned char*);
|
||||
|
||||
void fe_sq(fe h, const fe f);
|
||||
int fe_isnonzero(const fe f);
|
||||
int fe_cmp(const fe a, const fe b);
|
||||
void fe_mul(fe, const fe, const fe);
|
||||
void fe_frombytes(fe h, const unsigned char *s);
|
||||
void fe_invert(fe out, const fe z);
|
||||
|
|
|
|||
26
src/crypto/crypto-sugar.cpp
Normal file
26
src/crypto/crypto-sugar.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2020-2021 Zano Project
|
||||
// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
|
||||
|
||||
#include "crypto-sugar.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
|
||||
const point_g_t c_point_G;
|
||||
|
||||
const scalar_t c_scalar_1 = { 1 };
|
||||
const scalar_t c_scalar_L = { 0x5812631a5cf5d3ed, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
|
||||
const scalar_t c_scalar_Lm1 = { 0x5812631a5cf5d3ec, 0x14def9dea2f79cd6, 0x0, 0x1000000000000000 };
|
||||
const scalar_t c_scalar_P = { 0xffffffffffffffed, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff };
|
||||
const scalar_t c_scalar_Pm1 = { 0xffffffffffffffec, 0xffffffffffffffff, 0xffffffffffffffff, 0x7fffffffffffffff };
|
||||
const scalar_t c_scalar_256m1 = { 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff };
|
||||
const scalar_t c_scalar_1div8 = { 0x6106e529e2dc2f79, 0x7d39db37d1cdad0, 0x0, 0x600000000000000 };
|
||||
|
||||
const point_t c_point_H = { 0x05087c1f5b9b32d6, 0x00547595f445c3b5, 0x764df64578552f2a, 0x8a49a651e0e0da45 }; // == Hp(G), this is being checked in bpp_basics
|
||||
const point_t c_point_0 = point_t(point_t::tag_zero());
|
||||
|
||||
} // namespace crypto
|
||||
821
src/crypto/crypto-sugar.h
Normal file
821
src/crypto/crypto-sugar.h
Normal file
|
|
@ -0,0 +1,821 @@
|
|||
// Copyright (c) 2020-2021 Zano Project
|
||||
// Copyright (c) 2020-2021 sowle (val@zano.org, crypto.sowle@gmail.com)
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
//
|
||||
// Note: This file originates from tests/functional_tests/crypto_tests.cpp
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include "crypto.h"
|
||||
#include "epee/include/string_tools.h"
|
||||
|
||||
namespace crypto
|
||||
{
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/crypto-ops.h"
|
||||
} // extern "C"
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Helpers
|
||||
//
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex_reversed(const pod_t &h)
|
||||
{
|
||||
constexpr char hexmap[] = "0123456789abcdef";
|
||||
const unsigned char* data = reinterpret_cast<const unsigned char*>(&h);
|
||||
size_t len = sizeof h;
|
||||
|
||||
std::string s(len * 2, ' ');
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
s[2 * i] = hexmap[data[len - 1 - i] >> 4];
|
||||
s[2 * i + 1] = hexmap[data[len - 1 - i] & 0x0F];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex(const pod_t &h)
|
||||
{
|
||||
constexpr char hexmap[] = "0123456789abcdef";
|
||||
const unsigned char* data = reinterpret_cast<const unsigned char*>(&h);
|
||||
size_t len = sizeof h;
|
||||
|
||||
std::string s(len * 2, ' ');
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
s[2 * i] = hexmap[data[i] >> 4];
|
||||
s[2 * i + 1] = hexmap[data[i] & 0x0F];
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex_comma_separated_bytes(const pod_t &h)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
size_t len = sizeof h;
|
||||
const unsigned char* p = (const unsigned char*)&h;
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
ss << "0x" << std::setw(2) << static_cast<unsigned int>(p[i]);
|
||||
if (i + 1 != len)
|
||||
ss << ", ";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
template<class pod_t>
|
||||
std::string pod_to_hex_comma_separated_uint64(const pod_t &h)
|
||||
{
|
||||
static_assert((sizeof h) % 8 == 0, "size of h should be a multiple of 64 bit");
|
||||
size_t len = (sizeof h) / 8;
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
const uint64_t* p = (const uint64_t*)&h;
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
{
|
||||
ss << "0x" << std::setw(16) << static_cast<uint64_t>(p[i]);
|
||||
if (i + 1 != len)
|
||||
ss << ", ";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// scalar_t - holds a 256-bit scalar, normally in [0..L-1]
|
||||
//
|
||||
struct alignas(32) scalar_t
|
||||
{
|
||||
union
|
||||
{
|
||||
uint64_t m_u64[4];
|
||||
unsigned char m_s[32];
|
||||
};
|
||||
|
||||
scalar_t()
|
||||
{}
|
||||
|
||||
// won't check scalar range validity (< L)
|
||||
scalar_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
|
||||
{
|
||||
m_u64[0] = a0;
|
||||
m_u64[1] = a1;
|
||||
m_u64[2] = a2;
|
||||
m_u64[3] = a3;
|
||||
}
|
||||
|
||||
// won't check scalar range validity (< L)
|
||||
scalar_t(const unsigned char(&v)[32])
|
||||
{
|
||||
memcpy(m_s, v, 32);
|
||||
}
|
||||
|
||||
// won't check secret key validity (sk < L)
|
||||
scalar_t(const crypto::secret_key& sk)
|
||||
{
|
||||
from_secret_key(sk);
|
||||
}
|
||||
|
||||
// copy data and reduce
|
||||
scalar_t(const crypto::hash& hash)
|
||||
{
|
||||
m_u64[0] = ((uint64_t*)&hash)[0];
|
||||
m_u64[1] = ((uint64_t*)&hash)[1];
|
||||
m_u64[2] = ((uint64_t*)&hash)[2];
|
||||
m_u64[3] = ((uint64_t*)&hash)[3];
|
||||
sc_reduce32(&m_s[0]);
|
||||
}
|
||||
|
||||
scalar_t(uint64_t v)
|
||||
{
|
||||
zero();
|
||||
m_u64[0] = v;
|
||||
// do not need to call reduce as 2^64 < L
|
||||
}
|
||||
|
||||
// copy at most 256 bits (32 bytes) and reduce
|
||||
template<typename T>
|
||||
explicit scalar_t(const boost::multiprecision::number<T>& bigint)
|
||||
{
|
||||
zero();
|
||||
unsigned int bytes_to_copy = bigint.backend().size() * bigint.backend().limb_bits / 8;
|
||||
if (bytes_to_copy > sizeof *this)
|
||||
bytes_to_copy = sizeof *this;
|
||||
memcpy(&m_s[0], bigint.backend().limbs(), bytes_to_copy);
|
||||
sc_reduce32(&m_s[0]);
|
||||
}
|
||||
|
||||
unsigned char* data()
|
||||
{
|
||||
return &m_s[0];
|
||||
}
|
||||
|
||||
const unsigned char* data() const
|
||||
{
|
||||
return &m_s[0];
|
||||
}
|
||||
|
||||
crypto::secret_key &as_secret_key()
|
||||
{
|
||||
return *(crypto::secret_key*)&m_s[0];
|
||||
}
|
||||
|
||||
const crypto::secret_key& as_secret_key() const
|
||||
{
|
||||
return *(const crypto::secret_key*)&m_s[0];
|
||||
}
|
||||
|
||||
operator crypto::secret_key() const
|
||||
{
|
||||
crypto::secret_key result;
|
||||
memcpy(result.data, &m_s, sizeof result.data);
|
||||
return result;
|
||||
}
|
||||
|
||||
void from_secret_key(const crypto::secret_key& sk)
|
||||
{
|
||||
uint64_t *p_sk64 = (uint64_t*)&sk;
|
||||
m_u64[0] = p_sk64[0];
|
||||
m_u64[1] = p_sk64[1];
|
||||
m_u64[2] = p_sk64[2];
|
||||
m_u64[3] = p_sk64[3];
|
||||
// assuming secret key is correct (< L), so we don't need to call reduce here
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
m_u64[0] = 0;
|
||||
m_u64[1] = 0;
|
||||
m_u64[2] = 0;
|
||||
m_u64[3] = 0;
|
||||
}
|
||||
|
||||
// genrate 0 <= x < L
|
||||
static scalar_t random()
|
||||
{
|
||||
scalar_t result;
|
||||
result.make_random();
|
||||
return result;
|
||||
}
|
||||
|
||||
// genrate 0 <= x < L
|
||||
void make_random()
|
||||
{
|
||||
unsigned char tmp[64];
|
||||
crypto::generate_random_bytes(64, tmp);
|
||||
sc_reduce(tmp);
|
||||
memcpy(&m_s, tmp, sizeof m_s);
|
||||
|
||||
/* // for tests
|
||||
int x[8] = { rand() };
|
||||
crypto::cn_fast_hash(&x, sizeof x, *(crypto::hash*)this);
|
||||
sc_reduce32(m_s);
|
||||
*/
|
||||
}
|
||||
|
||||
bool is_zero() const
|
||||
{
|
||||
return sc_isnonzero(&m_s[0]) == 0;
|
||||
}
|
||||
|
||||
bool is_reduced() const
|
||||
{
|
||||
return sc_check(&m_s[0]) == 0;
|
||||
}
|
||||
|
||||
scalar_t operator+(const scalar_t& v) const
|
||||
{
|
||||
scalar_t result;
|
||||
sc_add(&result.m_s[0], &m_s[0], &v.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
scalar_t& operator+=(const scalar_t& v)
|
||||
{
|
||||
sc_add(&m_s[0], &m_s[0], &v.m_s[0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
scalar_t operator-(const scalar_t& v) const
|
||||
{
|
||||
scalar_t result;
|
||||
sc_sub(&result.m_s[0], &m_s[0], &v.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
scalar_t& operator-=(const scalar_t& v)
|
||||
{
|
||||
sc_sub(&m_s[0], &m_s[0], &v.m_s[0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
scalar_t operator*(const scalar_t& v) const
|
||||
{
|
||||
scalar_t result;
|
||||
sc_mul(result.m_s, m_s, v.m_s);
|
||||
return result;
|
||||
}
|
||||
|
||||
scalar_t& operator*=(const scalar_t& v)
|
||||
{
|
||||
sc_mul(m_s, m_s, v.m_s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
I think it has bad symantic (operator-like), consider rename/reimplement -- sowle
|
||||
*/
|
||||
// returns this * b + c
|
||||
scalar_t muladd(const scalar_t& b, const scalar_t& c) const
|
||||
{
|
||||
scalar_t result;
|
||||
sc_muladd(result.m_s, m_s, b.m_s, c.m_s);
|
||||
return result;
|
||||
}
|
||||
|
||||
// returns this = a * b + c
|
||||
scalar_t& assign_muladd(const scalar_t& a, const scalar_t& b, const scalar_t& c)
|
||||
{
|
||||
sc_muladd(m_s, a.m_s, b.m_s, c.m_s);
|
||||
return *this;
|
||||
}
|
||||
|
||||
scalar_t reciprocal() const
|
||||
{
|
||||
scalar_t result;
|
||||
sc_invert(result.m_s, m_s);
|
||||
return result;
|
||||
}
|
||||
|
||||
scalar_t operator/(const scalar_t& v) const
|
||||
{
|
||||
return operator*(v.reciprocal());
|
||||
}
|
||||
|
||||
scalar_t& operator/=(const scalar_t& v)
|
||||
{
|
||||
scalar_t reciprocal;
|
||||
sc_invert(&reciprocal.m_s[0], &v.m_s[0]);
|
||||
sc_mul(&m_s[0], &m_s[0], &reciprocal.m_s[0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const scalar_t& rhs) const
|
||||
{
|
||||
return
|
||||
m_u64[0] == rhs.m_u64[0] &&
|
||||
m_u64[1] == rhs.m_u64[1] &&
|
||||
m_u64[2] == rhs.m_u64[2] &&
|
||||
m_u64[3] == rhs.m_u64[3];
|
||||
}
|
||||
|
||||
bool operator!=(const scalar_t& rhs) const
|
||||
{
|
||||
return
|
||||
m_u64[0] != rhs.m_u64[0] ||
|
||||
m_u64[1] != rhs.m_u64[1] ||
|
||||
m_u64[2] != rhs.m_u64[2] ||
|
||||
m_u64[3] != rhs.m_u64[3];
|
||||
}
|
||||
|
||||
bool operator<(const scalar_t& rhs) const
|
||||
{
|
||||
if (m_u64[3] < rhs.m_u64[3]) return true;
|
||||
if (m_u64[3] > rhs.m_u64[3]) return false;
|
||||
if (m_u64[2] < rhs.m_u64[2]) return true;
|
||||
if (m_u64[2] > rhs.m_u64[2]) return false;
|
||||
if (m_u64[1] < rhs.m_u64[1]) return true;
|
||||
if (m_u64[1] > rhs.m_u64[1]) return false;
|
||||
if (m_u64[0] < rhs.m_u64[0]) return true;
|
||||
if (m_u64[0] > rhs.m_u64[0]) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator>(const scalar_t& rhs) const
|
||||
{
|
||||
if (m_u64[3] < rhs.m_u64[3]) return false;
|
||||
if (m_u64[3] > rhs.m_u64[3]) return true;
|
||||
if (m_u64[2] < rhs.m_u64[2]) return false;
|
||||
if (m_u64[2] > rhs.m_u64[2]) return true;
|
||||
if (m_u64[1] < rhs.m_u64[1]) return false;
|
||||
if (m_u64[1] > rhs.m_u64[1]) return true;
|
||||
if (m_u64[0] < rhs.m_u64[0]) return false;
|
||||
if (m_u64[0] > rhs.m_u64[0]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& ss, const scalar_t &v)
|
||||
{
|
||||
return ss << "0x" << pod_to_hex_reversed(v);
|
||||
}
|
||||
|
||||
std::string to_string_as_hex_number() const
|
||||
{
|
||||
return pod_to_hex_reversed(*this);
|
||||
}
|
||||
|
||||
std::string to_string_as_secret_key() const
|
||||
{
|
||||
return epee::string_tools::pod_to_hex(*this);
|
||||
}
|
||||
|
||||
template<typename MP_type>
|
||||
MP_type as_boost_mp_type() const
|
||||
{
|
||||
MP_type result = 0;
|
||||
static_assert(sizeof result >= sizeof *this, "size missmatch"); // to avoid using types less than uint256_t
|
||||
unsigned int sz = sizeof *this / sizeof(boost::multiprecision::limb_type);
|
||||
result.backend().resize(sz, sz);
|
||||
memcpy(result.backend().limbs(), &m_s[0], sizeof *this);
|
||||
result.backend().normalize();
|
||||
return result;
|
||||
}
|
||||
|
||||
}; // struct scalar_t
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
struct point_t
|
||||
{
|
||||
struct tag_zero {};
|
||||
|
||||
// A point(x, y) is represented in extended homogeneous coordinates (X, Y, Z, T)
|
||||
// with x = X / Z, y = Y / Z, x * y = T / Z.
|
||||
ge_p3 m_p3;
|
||||
|
||||
point_t()
|
||||
{
|
||||
}
|
||||
|
||||
explicit point_t(const crypto::public_key& pk)
|
||||
{
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
}
|
||||
|
||||
point_t(const unsigned char(&v)[32])
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
}
|
||||
|
||||
point_t(const uint64_t(&v)[4])
|
||||
{
|
||||
static_assert(sizeof(crypto::public_key) == sizeof v, "size missmatch");
|
||||
if (!from_public_key(*(const crypto::public_key*)v))
|
||||
zero();
|
||||
}
|
||||
|
||||
point_t(uint64_t a0, uint64_t a1, uint64_t a2, uint64_t a3)
|
||||
{
|
||||
crypto::public_key pk;
|
||||
((uint64_t*)&pk)[0] = a0;
|
||||
((uint64_t*)&pk)[1] = a1;
|
||||
((uint64_t*)&pk)[2] = a2;
|
||||
((uint64_t*)&pk)[3] = a3;
|
||||
|
||||
if (!from_public_key(pk))
|
||||
zero();
|
||||
}
|
||||
|
||||
explicit point_t(tag_zero&&)
|
||||
{
|
||||
zero();
|
||||
}
|
||||
|
||||
void zero()
|
||||
{
|
||||
ge_p3_0(&m_p3);
|
||||
}
|
||||
|
||||
bool is_zero() const
|
||||
{
|
||||
// (0, 1) ~ (0, z, z, 0)
|
||||
return fe_isnonzero(m_p3.X) * fe_cmp(m_p3.Y, m_p3.Z) == 0;
|
||||
}
|
||||
|
||||
bool from_public_key(const crypto::public_key& pk)
|
||||
{
|
||||
return ge_frombytes_vartime(&m_p3, reinterpret_cast<const unsigned char*>(&pk)) == 0;
|
||||
}
|
||||
|
||||
bool from_key_image(const crypto::key_image& ki)
|
||||
{
|
||||
return ge_frombytes_vartime(&m_p3, reinterpret_cast<const unsigned char*>(&ki)) == 0;
|
||||
}
|
||||
|
||||
bool from_string(const std::string& str)
|
||||
{
|
||||
crypto::public_key pk;
|
||||
if (!epee::string_tools::parse_tpod_from_hex_string(str, pk))
|
||||
return false;
|
||||
return from_public_key(pk);
|
||||
}
|
||||
|
||||
crypto::public_key to_public_key() const
|
||||
{
|
||||
crypto::public_key result;
|
||||
ge_p3_tobytes((unsigned char*)&result, &m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
crypto::key_image to_key_image() const
|
||||
{
|
||||
crypto::key_image result;
|
||||
ge_p3_tobytes((unsigned char*)&result, &m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t operator+(const point_t& rhs) const
|
||||
{
|
||||
point_t result;
|
||||
ge_cached rhs_c;
|
||||
ge_p1p1 t;
|
||||
ge_p3_to_cached(&rhs_c, &rhs.m_p3);
|
||||
ge_add(&t, &m_p3, &rhs_c);
|
||||
ge_p1p1_to_p3(&result.m_p3, &t);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t& operator+=(const point_t& rhs)
|
||||
{
|
||||
ge_cached rhs_c;
|
||||
ge_p1p1 t;
|
||||
ge_p3_to_cached(&rhs_c, &rhs.m_p3);
|
||||
ge_add(&t, &m_p3, &rhs_c);
|
||||
ge_p1p1_to_p3(&m_p3, &t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
point_t operator-(const point_t& rhs) const
|
||||
{
|
||||
point_t result;
|
||||
ge_cached rhs_c;
|
||||
ge_p1p1 t;
|
||||
ge_p3_to_cached(&rhs_c, &rhs.m_p3);
|
||||
ge_sub(&t, &m_p3, &rhs_c);
|
||||
ge_p1p1_to_p3(&result.m_p3, &t);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t& operator-=(const point_t& rhs)
|
||||
{
|
||||
ge_cached rhs_c;
|
||||
ge_p1p1 t;
|
||||
ge_p3_to_cached(&rhs_c, &rhs.m_p3);
|
||||
ge_sub(&t, &m_p3, &rhs_c);
|
||||
ge_p1p1_to_p3(&m_p3, &t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend point_t operator*(const scalar_t& lhs, const point_t& rhs)
|
||||
{
|
||||
point_t result;
|
||||
ge_scalarmult_p3(&result.m_p3, reinterpret_cast<const unsigned char*>(&lhs), &rhs.m_p3);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend point_t operator/(const point_t& lhs, const scalar_t& rhs)
|
||||
{
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
point_t& modify_mul8()
|
||||
{
|
||||
ge_mul8_p3(&m_p3, &m_p3);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// returns a * this + G
|
||||
point_t mul_plus_G(const scalar_t& a) const
|
||||
{
|
||||
static const unsigned char one[32] = { 1 };
|
||||
static_assert(sizeof one == sizeof(crypto::ec_scalar), "size missmatch");
|
||||
|
||||
point_t result;
|
||||
ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &one[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// returns a * this + b * G
|
||||
point_t mul_plus_G(const scalar_t& a, const scalar_t& b) const
|
||||
{
|
||||
point_t result;
|
||||
ge_double_scalarmult_base_vartime_p3(&result.m_p3, &a.m_s[0], &m_p3, &b.m_s[0]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// *this = a * A + b * G
|
||||
void assign_mul_plus_G(const scalar_t& a, const point_t& A, const scalar_t& b)
|
||||
{
|
||||
ge_double_scalarmult_base_vartime_p3(&m_p3, &a.m_s[0], &A.m_p3, &b.m_s[0]);
|
||||
}
|
||||
|
||||
friend bool operator==(const point_t& lhs, const point_t& rhs)
|
||||
{
|
||||
// convert to xy form, then compare components (because (x, y, z, t) representation is not unique)
|
||||
fe lrecip, lx, ly;
|
||||
fe rrecip, rx, ry;
|
||||
|
||||
fe_invert(lrecip, lhs.m_p3.Z);
|
||||
fe_invert(rrecip, rhs.m_p3.Z);
|
||||
|
||||
fe_mul(lx, lhs.m_p3.X, lrecip);
|
||||
fe_mul(rx, rhs.m_p3.X, rrecip);
|
||||
if (memcmp(&lx, &rx, sizeof lx) != 0)
|
||||
return false;
|
||||
|
||||
fe_mul(ly, lhs.m_p3.Y, lrecip);
|
||||
fe_mul(ry, rhs.m_p3.Y, rrecip);
|
||||
if (memcmp(&ly, &ry, sizeof ly) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& ss, const point_t &v)
|
||||
{
|
||||
crypto::public_key pk = v.to_public_key();
|
||||
return ss << epee::string_tools::pod_to_hex(pk);
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
{
|
||||
crypto::public_key pk = to_public_key();
|
||||
return epee::string_tools::pod_to_hex(pk);
|
||||
}
|
||||
|
||||
std::string to_string() const
|
||||
{
|
||||
crypto::public_key pk = to_public_key();
|
||||
return epee::string_tools::pod_to_hex(pk);
|
||||
}
|
||||
|
||||
std::string to_hex_comma_separated_bytes_str() const
|
||||
{
|
||||
crypto::public_key pk = to_public_key();
|
||||
return pod_to_hex_comma_separated_bytes(pk);
|
||||
}
|
||||
|
||||
std::string to_hex_comma_separated_uint64_str() const
|
||||
{
|
||||
crypto::public_key pk = to_public_key();
|
||||
return pod_to_hex_comma_separated_uint64(pk);
|
||||
}
|
||||
|
||||
}; // struct point_t
|
||||
|
||||
|
||||
//
|
||||
// point_g_t -- special type for curve's base point
|
||||
//
|
||||
struct point_g_t : public point_t
|
||||
{
|
||||
point_g_t()
|
||||
{
|
||||
scalar_t one(1);
|
||||
ge_scalarmult_base(&m_p3, &one.m_s[0]);
|
||||
}
|
||||
|
||||
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]);
|
||||
return result;
|
||||
}
|
||||
|
||||
friend point_t operator/(const point_g_t&, const scalar_t& rhs)
|
||||
{
|
||||
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]);
|
||||
return result;
|
||||
}
|
||||
|
||||
static_assert(sizeof(crypto::public_key) == 32, "size error");
|
||||
|
||||
}; // struct point_g_t
|
||||
|
||||
|
||||
//
|
||||
// Global constants
|
||||
//
|
||||
|
||||
extern const point_g_t c_point_G;
|
||||
|
||||
extern const scalar_t c_scalar_1;
|
||||
extern const scalar_t c_scalar_L;
|
||||
extern const scalar_t c_scalar_Lm1;
|
||||
extern const scalar_t c_scalar_P;
|
||||
extern const scalar_t c_scalar_Pm1;
|
||||
extern const scalar_t c_scalar_256m1;
|
||||
extern const scalar_t c_scalar_1div8;
|
||||
|
||||
extern const point_t c_point_H;
|
||||
extern const point_t c_point_0;
|
||||
|
||||
//
|
||||
// hash functions' helper
|
||||
//
|
||||
struct hash_helper_t
|
||||
{
|
||||
static scalar_t hs(const scalar_t& s)
|
||||
{
|
||||
return scalar_t(crypto::cn_fast_hash(s.data(), sizeof s)); // will reduce mod L
|
||||
}
|
||||
|
||||
static scalar_t hs(const void* data, size_t size)
|
||||
{
|
||||
return scalar_t(crypto::cn_fast_hash(data, size)); // will reduce mod L
|
||||
}
|
||||
|
||||
static scalar_t hs(const std::string& str)
|
||||
{
|
||||
return scalar_t(crypto::cn_fast_hash(str.c_str(), str.size())); // will reduce mod L
|
||||
}
|
||||
|
||||
struct hs_t
|
||||
{
|
||||
hs_t()
|
||||
{
|
||||
static_assert(sizeof(scalar_t) == sizeof(crypto::public_key), "unexpected size of data");
|
||||
}
|
||||
|
||||
void reserve(size_t elements_count)
|
||||
{
|
||||
m_elements.reserve(elements_count);
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_elements.clear();
|
||||
}
|
||||
|
||||
void add_scalar(const scalar_t& scalar)
|
||||
{
|
||||
m_elements.emplace_back(scalar);
|
||||
}
|
||||
|
||||
void add_point(const point_t& point)
|
||||
{
|
||||
m_elements.emplace_back(point.to_public_key());
|
||||
|
||||
// faster?
|
||||
/* static_assert(sizeof point.m_p3 == 5 * sizeof(item_t), "size missmatch");
|
||||
const item_t *p = (item_t*)&point.m_p3;
|
||||
m_elements.emplace_back(p[0]);
|
||||
m_elements.emplace_back(p[1]);
|
||||
m_elements.emplace_back(p[2]);
|
||||
m_elements.emplace_back(p[3]);
|
||||
m_elements.emplace_back(p[4]); */
|
||||
}
|
||||
|
||||
void add_pub_key(const crypto::public_key& pk)
|
||||
{
|
||||
m_elements.emplace_back(pk);
|
||||
}
|
||||
|
||||
void add_points_array(const std::vector<point_t>& points_array)
|
||||
{
|
||||
for (size_t i = 0, size = points_array.size(); i < size; ++i)
|
||||
add_point(points_array[i]);
|
||||
}
|
||||
|
||||
void add_pub_keys_array(const std::vector<crypto::public_key>& pub_keys_array)
|
||||
{
|
||||
for (size_t i = 0, size = pub_keys_array.size(); i < size; ++i)
|
||||
m_elements.emplace_back(pub_keys_array[i]);
|
||||
}
|
||||
|
||||
void add_key_images_array(const std::vector<crypto::key_image>& key_image_array)
|
||||
{
|
||||
for (size_t i = 0, size = key_image_array.size(); i < size; ++i)
|
||||
m_elements.emplace_back(key_image_array[i]);
|
||||
}
|
||||
|
||||
scalar_t calc_hash(bool clear = true)
|
||||
{
|
||||
size_t data_size_bytes = m_elements.size() * sizeof(item_t);
|
||||
crypto::hash hash;
|
||||
crypto::cn_fast_hash(m_elements.data(), data_size_bytes, hash);
|
||||
if (clear)
|
||||
this->clear();
|
||||
return scalar_t(hash); // this will reduce to L
|
||||
}
|
||||
|
||||
union item_t
|
||||
{
|
||||
item_t(const scalar_t& scalar) : scalar(scalar) {}
|
||||
item_t(const crypto::public_key& pk) : pk(pk) {}
|
||||
item_t(const crypto::key_image& ki) : ki(ki) {}
|
||||
scalar_t scalar;
|
||||
crypto::public_key pk;
|
||||
crypto::key_image ki;
|
||||
};
|
||||
|
||||
std::vector<item_t> m_elements;
|
||||
};
|
||||
|
||||
static scalar_t hs(const scalar_t& s, const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_calculator.add_scalar(s);
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const crypto::hash& s, const std::vector<crypto::public_key>& ps0, const std::vector<crypto::key_image>& ps1)
|
||||
{
|
||||
static_assert(sizeof(crypto::hash) == sizeof(scalar_t), "size missmatch");
|
||||
hs_t hs_calculator;
|
||||
hs_calculator.add_scalar(*reinterpret_cast<const scalar_t*>(&s));
|
||||
hs_calculator.add_pub_keys_array(ps0);
|
||||
hs_calculator.add_key_images_array(ps1);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static scalar_t hs(const std::vector<point_t>& ps0, const std::vector<point_t>& ps1)
|
||||
{
|
||||
hs_t hs_calculator;
|
||||
hs_calculator.add_points_array(ps0);
|
||||
hs_calculator.add_points_array(ps1);
|
||||
return hs_calculator.calc_hash();
|
||||
}
|
||||
|
||||
static point_t hp(const point_t& p)
|
||||
{
|
||||
point_t result;
|
||||
crypto::public_key pk = p.to_public_key();
|
||||
|
||||
ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&pk);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static point_t hp(const crypto::public_key& p)
|
||||
{
|
||||
point_t result;
|
||||
ge_bytes_hash_to_ec_32(&result.m_p3, (const unsigned char*)&p);
|
||||
return result;
|
||||
}
|
||||
}; // hash_helper_t struct
|
||||
|
||||
|
||||
} // namespace crypto
|
||||
|
|
@ -413,10 +413,10 @@ POP_VS_WARNINGS
|
|||
if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
|
||||
return false;
|
||||
}
|
||||
ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
|
||||
ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r); // L_i = r_i * G + c_i * P_i
|
||||
ge_tobytes(&buf->ab[i].a, &tmp2);
|
||||
hash_to_ec(*pubs[i], tmp3);
|
||||
ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
|
||||
ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre); // R_i = r_i * Hp(P_i) + c_i * I
|
||||
ge_tobytes(&buf->ab[i].b, &tmp2);
|
||||
sc_add(&sum, &sum, &sig[i].c);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ void hash_process(union hash_state *state, const uint8_t *buf, size_t count);
|
|||
#define HASH_DATA_AREA 136
|
||||
|
||||
|
||||
void cn_fast_hash_old(const void *data, size_t length, char *hash);
|
||||
void cn_fast_hash(const void *data, size_t length, char *hash);
|
||||
//void cn_slow_hash(const void *data, size_t length, char *hash);
|
||||
|
||||
void hash_extra_blake(const void *data, size_t length, char *hash);
|
||||
void hash_extra_groestl(const void *data, size_t length, char *hash);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
// Copyright (c) 2020-2021 Zano project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
|
@ -17,8 +18,14 @@ void hash_process(union hash_state *state, const uint8_t *buf, size_t count) {
|
|||
keccak1600(buf, (int)count, (uint8_t*)state);
|
||||
}
|
||||
|
||||
void cn_fast_hash(const void *data, size_t length, char *hash) {
|
||||
void cn_fast_hash_old(const void *data, size_t length, char *hash)
|
||||
{
|
||||
union hash_state state;
|
||||
hash_process(&state, data, length);
|
||||
memcpy(hash, &state, HASH_SIZE);
|
||||
}
|
||||
|
||||
void cn_fast_hash(const void *data, size_t length, char *hash)
|
||||
{
|
||||
keccak(data, (int)length, hash, HASH_SIZE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public:
|
|||
m_cmd_binder.set_handler("print_bc_outs_stats", boost::bind(&daemon_commands_handler::print_bc_outs_stats, this, _1));
|
||||
m_cmd_binder.set_handler("print_block", boost::bind(&daemon_commands_handler::print_block, this, _1), "Print block, print_block <block_hash> | <block_height>");
|
||||
m_cmd_binder.set_handler("print_block_info", boost::bind(&daemon_commands_handler::print_block_info, this, _1), "Print block info, print_block <block_hash> | <block_height>");
|
||||
m_cmd_binder.set_handler("print_tx_prun_info", boost::bind(&daemon_commands_handler::print_tx_prun_info, this, _1), "Print tx prunning info");
|
||||
m_cmd_binder.set_handler("print_tx", boost::bind(&daemon_commands_handler::print_tx, this, _1), "Print transaction, print_tx <transaction_hash>");
|
||||
m_cmd_binder.set_handler("start_mining", boost::bind(&daemon_commands_handler::start_mining, this, _1), "Start mining for specified address, start_mining <addr> [threads=1]");
|
||||
m_cmd_binder.set_handler("stop_mining", boost::bind(&daemon_commands_handler::stop_mining, this, _1), "Stop mining");
|
||||
|
|
@ -630,6 +631,56 @@ private:
|
|||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_tx_prun_info(const std::vector<std::string>& arg)
|
||||
{
|
||||
currency::blockchain_storage& bcs = m_srv.get_payload_object().get_core().get_blockchain_storage();
|
||||
|
||||
size_t txs = 0;
|
||||
size_t pruned_txs = 0;
|
||||
size_t signatures = 0;
|
||||
size_t attachments = 0;
|
||||
size_t blocks = 0;
|
||||
|
||||
uint64_t last_block_height = bcs.get_top_block_height();
|
||||
|
||||
LOG_PRINT_MAGENTA("start getting stats from 0 to " << last_block_height << " block, please wait ...", LOG_LEVEL_0);
|
||||
|
||||
for (uint64_t height = 0; height <= last_block_height; height++, blocks++)
|
||||
{
|
||||
currency::block_extended_info bei = AUTO_VAL_INIT(bei);
|
||||
bool r = bcs.get_block_extended_info_by_height(height, bei);
|
||||
if (!r)
|
||||
{
|
||||
LOG_PRINT_RED("Failed to get block #" << height, LOG_LEVEL_0);
|
||||
break;
|
||||
}
|
||||
|
||||
for (const auto& h : bei.bl.tx_hashes)
|
||||
{
|
||||
auto ptx = bcs.get_tx(h);
|
||||
CHECK_AND_ASSERT_MES(ptx != nullptr, false, "failed to find transaction " << h << " in blockchain index, in block on height = " << height);
|
||||
|
||||
if (ptx->signatures.size() == 0)
|
||||
pruned_txs += 1;
|
||||
|
||||
txs += 1;
|
||||
signatures += ptx->signatures.size();
|
||||
attachments += ptx->attachment.size();
|
||||
}
|
||||
}
|
||||
|
||||
LOG_PRINT_MAGENTA(ENDL << "blockchain pruning stats:" << ENDL <<
|
||||
" last block height: " << last_block_height << ENDL <<
|
||||
" blocks processed: " << blocks << ENDL <<
|
||||
" total txs: " << txs << ENDL <<
|
||||
" pruned txs: " << pruned_txs << ENDL <<
|
||||
" total signatures: " << signatures << ENDL <<
|
||||
" total attachments: " << attachments << ENDL <<
|
||||
(pruned_txs == 0 ? "*** The database seems to be unpruned!" : "The database contains pruned transactions."), LOG_LEVEL_0);
|
||||
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------
|
||||
bool print_tx(const std::vector<std::string>& args)
|
||||
{
|
||||
if (args.empty())
|
||||
|
|
|
|||
|
|
@ -2061,8 +2061,10 @@ int main(int argc, char* argv[])
|
|||
std::string arg_pos_mining_reward_address_str = command_line::get_arg(vm, arg_pos_mining_reward_address);
|
||||
if (!arg_pos_mining_reward_address_str.empty())
|
||||
{
|
||||
r = get_account_address_from_str(miner_address, arg_pos_mining_reward_address_str);
|
||||
std::string payment_id;
|
||||
r = wal.get_transfer_address(arg_pos_mining_reward_address_str, miner_address, payment_id);
|
||||
CHECK_AND_ASSERT_MES(r, EXIT_FAILURE, "Failed to parse miner address from string: " << arg_pos_mining_reward_address_str);
|
||||
CHECK_AND_ASSERT_MES(payment_id.size() == 0, EXIT_FAILURE, "Address for rewards should not be integrated address: " << arg_pos_mining_reward_address_str);
|
||||
LOG_PRINT_YELLOW("PoS reward will be sent to another address: " << arg_pos_mining_reward_address_str, LOG_LEVEL_0);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -3,4 +3,4 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
||||
int crypto_tests();
|
||||
int crypto_tests(const std::string& cmd_line_param);
|
||||
|
|
|
|||
666
tests/functional_tests/crypto_tests_performance.h
Normal file
666
tests/functional_tests/crypto_tests_performance.h
Normal file
|
|
@ -0,0 +1,666 @@
|
|||
// Copyright (c) 2021 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#pragma once
|
||||
|
||||
TEST(crypto, primitives)
|
||||
{
|
||||
struct helper
|
||||
{
|
||||
static void make_rnd_indicies(std::vector<size_t>& 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::microseconds>(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(40) << 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("sc_reduce", 30000, [](timer_t& t, size_t rounds) {
|
||||
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);
|
||||
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
sc_reduce(scalars_64[rnd_indecies[i]].b);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(scalars_64);
|
||||
});
|
||||
|
||||
run("sc_reduce32", 30000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<crypto::ec_scalar> scalars(rounds);
|
||||
for (size_t i = 0; i < scalars.size(); ++i)
|
||||
crypto::generate_random_bytes(sizeof(crypto::ec_scalar), scalars[i].data);
|
||||
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
sc_reduce32((unsigned char*)&scalars[rnd_indecies[i]].data);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(scalars);
|
||||
});
|
||||
|
||||
run("sc_mul", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> a(rounds), b(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
a[i].make_random();
|
||||
b[i].make_random();
|
||||
}
|
||||
|
||||
std::vector<scalar_t> result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
sc_mul(result[rnd_indecies[i]].m_s, a[rnd_indecies[i]].m_s, b[rnd_indecies[i]].m_s);
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
run("sc_add", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> a(rounds), b(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
a[i].make_random();
|
||||
b[i].make_random();
|
||||
}
|
||||
|
||||
std::vector<scalar_t> result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
sc_add(result[i].m_s, a[rnd_indecies[i]].m_s, b[rnd_indecies[i]].m_s);
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
run("sc_mul + sc_add", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> a(rounds), b(rounds), c(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
a[i].make_random();
|
||||
b[i].make_random();
|
||||
c[i].make_random();
|
||||
}
|
||||
|
||||
std::vector<scalar_t> result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
scalar_t tmp;
|
||||
sc_mul(tmp.m_s, a[rnd_indecies[i]].m_s, b[rnd_indecies[i]].m_s); // tmp = a * b
|
||||
sc_add(result[i].m_s, tmp.m_s, c[rnd_indecies[i]].m_s); // result = tmp + c
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
run("sc_muladd", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> a(rounds), b(rounds), c(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
a[i].make_random();
|
||||
b[i].make_random();
|
||||
c[i].make_random();
|
||||
}
|
||||
|
||||
std::vector<scalar_t> result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
sc_muladd(result[i].m_s, a[rnd_indecies[i]].m_s, b[rnd_indecies[i]].m_s, c[rnd_indecies[i]].m_s);
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(result);
|
||||
});
|
||||
|
||||
run("ge_p3_tobytes", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<ge_p3> 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_32(&points_p3[i], (const unsigned char*)&points_p3[i - 1].X); // P_{i+1} = Hp(P_i.X)
|
||||
|
||||
std::vector<crypto::ec_point> points(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_p3_tobytes((unsigned char*)points[i].data, &points_p3[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points);
|
||||
});
|
||||
|
||||
run("ge_frombytes_vartime(p3)", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
point_t P = c_point_G;
|
||||
|
||||
std::vector<crypto::ec_point> points_p3_bytes(rounds);
|
||||
for (size_t i = 0; i < points_p3_bytes.size(); ++i)
|
||||
{
|
||||
P = hash_helper_t::hp(P);
|
||||
ge_p3_tobytes((unsigned char*)&points_p3_bytes[i], &P.m_p3);
|
||||
}
|
||||
|
||||
std::vector<ge_p3> points(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_frombytes_vartime(&points[i], (unsigned char*)&points_p3_bytes[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points);
|
||||
});
|
||||
|
||||
run("ge_p3_to_cached(p3)", 10000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<ge_p3> 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_32(&points_p3[i], (const unsigned char*)&points_p3[i - 1].X); // P_{i+1} = Hp(P_i.X)
|
||||
|
||||
std::vector<ge_cached> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
std::vector<ge_cached> 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<ge_p1p1> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
ge_cached G;
|
||||
ge_p3_to_cached(&G, &c_point_G.m_p3);
|
||||
|
||||
std::vector<ge_p1p1> 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<ge_p3> 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<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;
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
point_t p = scalar_t::random() * c_point_G;
|
||||
|
||||
//std::vector<ge_p2> points_p2(rounds);
|
||||
std::vector<ge_p3> 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<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;
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
point_t p = scalar_t::random() * c_point_G;
|
||||
|
||||
//std::vector<ge_p2> points_p2(rounds);
|
||||
std::vector<ge_p3> 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<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;
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
point_t p = scalar_t::random() * c_point_G;
|
||||
|
||||
std::vector<ge_p3> 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<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;
|
||||
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<ge_p3> 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<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;
|
||||
scalar_t x;
|
||||
x.make_random();
|
||||
memcpy(&scalars[i].data, x.data(), 32);
|
||||
}
|
||||
|
||||
point_t p = scalar_t::random() * c_point_G;
|
||||
|
||||
std::vector<ge_p3> 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<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(&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);
|
||||
|
||||
std::vector<ge_p3> 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_32(&points_p3[i], (const unsigned char*)&points_p3[i - 1].X); // P_{i+1} = Hp(P_i.X)
|
||||
|
||||
std::vector<ge_p3> points_result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_mul8_p3(&points_result[i], &points_p3[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points_result);
|
||||
});
|
||||
|
||||
run("ge_mul8()", 5000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
point_t p = scalar_t::random() * c_point_G;
|
||||
|
||||
std::vector<ge_p2> points_p2(rounds);
|
||||
ge_p3_to_p2(&points_p2[0], &p.m_p3);
|
||||
ge_p1p1 p1;
|
||||
for (size_t i = 0; i < points_p2.size() - 1; ++i)
|
||||
{
|
||||
ge_p2_dbl(&p1, &points_p2[i]);
|
||||
ge_p1p1_to_p2(&points_p2[i + 1], &p1);
|
||||
}
|
||||
|
||||
std::vector<ge_p1p1> points_result(rounds);
|
||||
t.start();
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
ge_mul8(&points_result[i], &points_p2[rnd_indecies[i]]);
|
||||
}
|
||||
t.stop();
|
||||
|
||||
return HASH_64_VEC(points_result);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
LOG_PRINT_L0(ENDL << "new primitives:");
|
||||
|
||||
run("point_t + point_t", 50000, [](timer_t& t, size_t rounds) {
|
||||
std::vector<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<point_t> points(rounds);
|
||||
point_t p = c_point_G;
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
{
|
||||
points[i] = p;
|
||||
p = p + p;
|
||||
}
|
||||
|
||||
std::vector<point_t> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> 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<point_t> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> scalars(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
scalars[i].make_random();
|
||||
|
||||
std::vector<point_t> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> scalars(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
scalars[i].make_random();
|
||||
|
||||
scalar_t s = scalar_t::random();
|
||||
|
||||
std::vector<scalar_t> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<scalar_t> scalars(rounds);
|
||||
for (size_t i = 0; i < rounds; ++i)
|
||||
scalars[i].make_random();
|
||||
|
||||
scalar_t s = scalar_t::random();
|
||||
|
||||
std::vector<scalar_t> 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<size_t> rnd_indecies;
|
||||
helper::make_rnd_indicies(rnd_indecies, rounds);
|
||||
|
||||
std::vector<point_t> 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<point_t> 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;
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ namespace
|
|||
const command_line::arg_descriptor<bool> arg_deadlock_guard = { "test-deadlock-guard", "Do deadlock guard test", false, true };
|
||||
const command_line::arg_descriptor<std::string> arg_difficulty_analysis = { "difficulty-analysis", "Do difficulty analysis", "", true };
|
||||
const command_line::arg_descriptor<bool> arg_test_plain_wallet = { "test-plainwallet", "Do testing of plain wallet interface", false, true };
|
||||
const command_line::arg_descriptor<bool> arg_crypto_tests = { "crypto-tests", "Run experimental crypto tests", false, true };
|
||||
const command_line::arg_descriptor<std::string> arg_crypto_tests = { "crypto-tests", "Run experimental crypto tests", "", true };
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -212,9 +212,9 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
else if (command_line::get_arg(vm, arg_crypto_tests))
|
||||
else if (command_line::has_arg(vm, arg_crypto_tests))
|
||||
{
|
||||
return crypto_tests();
|
||||
return crypto_tests(command_line::get_arg(vm, arg_crypto_tests));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue