diff --git a/src/Cpu.cpp b/src/Cpu.cpp index ddd4642d..ddc568e7 100644 --- a/src/Cpu.cpp +++ b/src/Cpu.cpp @@ -67,6 +67,7 @@ void CpuImpl::optimizeParameters(size_t& threadsCount, size_t& hashFactor, size_t algoBlockSize; switch (algo) { case Options::ALGO_CRYPTONIGHT_LITE: + case Options::ALGO_CRYPTONIGHT_LITE_IPBC: algoBlockSize = 1024; break; case Options::ALGO_CRYPTONIGHT_HEAVY: diff --git a/src/Mem.cpp b/src/Mem.cpp index 522deab4..871ee20a 100644 --- a/src/Mem.cpp +++ b/src/Mem.cpp @@ -44,6 +44,7 @@ cryptonight_ctx *Mem::create(int threadId) switch (m_algo) { case Options::ALGO_CRYPTONIGHT_LITE: + case Options::ALGO_CRYPTONIGHT_LITE_IPBC: scratchPadSize = MEMORY_LITE; break; case Options::ALGO_CRYPTONIGHT_HEAVY: diff --git a/src/Mem_unix.cpp b/src/Mem_unix.cpp index b52c449b..6cae3a63 100644 --- a/src/Mem_unix.cpp +++ b/src/Mem_unix.cpp @@ -50,6 +50,7 @@ bool Mem::allocate(const Options* options) switch (m_algo) { case Options::ALGO_CRYPTONIGHT_LITE: + case Options::ALGO_CRYPTONIGHT_LITE_IPBC: scratchPadSize = MEMORY_LITE; break; case Options::ALGO_CRYPTONIGHT_HEAVY: diff --git a/src/Mem_win.cpp b/src/Mem_win.cpp index a52cc5b5..658d0ceb 100644 --- a/src/Mem_win.cpp +++ b/src/Mem_win.cpp @@ -156,6 +156,7 @@ bool Mem::allocate(const Options* options) switch (m_algo) { case Options::ALGO_CRYPTONIGHT_LITE: + case Options::ALGO_CRYPTONIGHT_LITE_IPBC: scratchPadSize = MEMORY_LITE; break; case Options::ALGO_CRYPTONIGHT_HEAVY: diff --git a/src/Options.cpp b/src/Options.cpp index e0d2b3b9..7a7dacf4 100644 --- a/src/Options.cpp +++ b/src/Options.cpp @@ -259,6 +259,7 @@ static struct option const cc_server_options[] = { static const char *algo_names[] = { "cryptonight", "cryptonight-lite", + "cryptonight-lite-ipbc", "cryptonight-heavy" }; @@ -924,6 +925,11 @@ bool Options::setAlgo(const char *algo) break; } + if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-light-ipbc")) { + m_algo = ALGO_CRYPTONIGHT_LITE_IPBC; + break; + } + if (i == ARRAY_SIZE(algo_names) - 1 && !strcmp(algo, "cryptonight-heavy")) { m_algo = ALGO_CRYPTONIGHT_HEAVY; break; diff --git a/src/Options.h b/src/Options.h index 7824e838..bc1d7474 100644 --- a/src/Options.h +++ b/src/Options.h @@ -44,6 +44,7 @@ public: enum Algo { ALGO_CRYPTONIGHT, /* CryptoNight (Monero) */ ALGO_CRYPTONIGHT_LITE, /* CryptoNight-Lite (AEON) */ + ALGO_CRYPTONIGHT_LITE_IPBC, /* CryptoNight-Lite-IPBC (IPBC) */ ALGO_CRYPTONIGHT_HEAVY /* CryptoNight-Heavy (SUMO) */ }; diff --git a/src/config.json b/src/config.json index 57882604..9c73e15c 100644 --- a/src/config.json +++ b/src/config.json @@ -1,5 +1,5 @@ { - "algo": "cryptonight", // cryptonight (default), cryptonight-lite or cryptopnight-heavy + "algo": "cryptonight", // cryptonight (default), cryptonight-lite, cryptonight-lite-ipbc or cryptopnight-heavy "av": null, // DEPRECATED: algorithm variation, (0 auto, // 1 -> (aesni=1, multihash-factor=1), // 2 -> (aesni=1, multihash-factor=2), diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index ff2f7553..0362ec91 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -77,6 +77,17 @@ static void cryptonight_lite_softaes(Options::PowVersion powVersion, const uint8 } } +template +static void cryptonight_lite_ipbc_aesni(Options::PowVersion powVersion, const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx *ctx) { +# if !defined(XMRIG_ARMv7) + CryptoNightMultiHash<0x40000, MEMORY_LITE, 0xFFFF0, false, NUM_HASH_BLOCKS>::hashLiteIpbc(input, size, output, ctx); +# endif +} + +template +static void cryptonight_lite_ipbc_softaes(Options::PowVersion powVersion, const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx *ctx) { + CryptoNightMultiHash<0x40000, MEMORY_LITE, 0xFFFF0, true, NUM_HASH_BLOCKS>::hashLiteIpbc(input, size, output, ctx); +} template static void cryptonight_heavy_aesni(Options::PowVersion powVersion, const uint8_t* input, size_t size, uint8_t* output, cryptonight_ctx *ctx) { @@ -112,6 +123,14 @@ void setCryptoNightHashMethods(Options::Algo algo, bool aesni) } break; + case Options::ALGO_CRYPTONIGHT_LITE_IPBC: + if (aesni) { + cryptonight_hash_ctx[HASH_FACTOR - 1] = cryptonight_lite_ipbc_aesni; + } else { + cryptonight_hash_ctx[HASH_FACTOR - 1] = cryptonight_lite_ipbc_softaes; + } + break; + case Options::ALGO_CRYPTONIGHT_HEAVY: if (aesni) { cryptonight_hash_ctx[HASH_FACTOR - 1] = cryptonight_heavy_aesni; @@ -167,6 +186,7 @@ bool CryptoNight::selfTest(int algo) bool resultV1Pow = true; bool resultV2Pow = true; + bool resultLiteIpbc = true; bool resultHeavy = true; if (algo == Options::ALGO_CRYPTONIGHT_HEAVY) { @@ -184,8 +204,32 @@ bool CryptoNight::selfTest(int algo) cryptonight_hash_ctx[2](Options::PowVersion::POW_AUTODETECT, test_input, 76, output, ctx); resultHeavy = resultHeavy && memcmp(output, test_output_heavy, 96) == 0; #endif - } - else { + } else if (algo == Options::ALGO_CRYPTONIGHT_LITE_IPBC) { + // cn-lite-ipbc tests + + cryptonight_hash_ctx[0](Options::PowVersion::POW_AUTODETECT, test_input_lite_ipbc, 43, output, ctx); + resultLiteIpbc = resultLiteIpbc && memcmp(output, test_output_lite_ipbc, 32) == 0; + + #if MAX_NUM_HASH_BLOCKS > 1 + cryptonight_hash_ctx[1](Options::PowVersion::POW_AUTODETECT, test_input_lite_ipbc, 43, output, ctx); + resultLiteIpbc = resultLiteIpbc && memcmp(output, test_output_lite_ipbc, 64) == 0; + #endif + + #if MAX_NUM_HASH_BLOCKS > 2 + cryptonight_hash_ctx[2](Options::PowVersion::POW_AUTODETECT, test_input_lite_ipbc, 43, output, ctx); + resultLiteIpbc = resultLiteIpbc && memcmp(output, test_output_lite_ipbc, 96) == 0; + #endif + + #if MAX_NUM_HASH_BLOCKS > 3 + cryptonight_hash_ctx[3](Options::PowVersion::POW_AUTODETECT, test_input_lite_ipbc, 43, output, ctx); + resultLiteIpbc = resultLiteIpbc && memcmp(output, test_output_lite_ipbc, 128) == 0; + #endif + + #if MAX_NUM_HASH_BLOCKS > 4 + cryptonight_hash_ctx[4](Options::PowVersion::POW_AUTODETECT, test_input_lite_ipbc, 43, output, ctx); + resultLiteIpbc = resultLiteIpbc && memcmp(output, test_output_lite_ipbc, 160) == 0; + #endif + } else { // < v7 tests autodetect cryptonight_hash_ctx[0](Options::PowVersion::POW_AUTODETECT,test_input, 76, output, ctx); resultV1Pow = resultV1Pow && @@ -248,5 +292,5 @@ bool CryptoNight::selfTest(int algo) _mm_free(ctx->memory); _mm_free(ctx); - return resultV1Pow && resultV2Pow & resultHeavy; + return resultV1Pow && resultV2Pow & resultLiteIpbc & resultHeavy; } \ No newline at end of file diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index 1baed91a..eb23d715 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -30,8 +30,8 @@ #include "Options.h" -#define MEMORY 2097152 /* 2 MiB */ -#define MEMORY_LITE 1048576 /* 1 MiB */ +#define MEMORY 2097152 /* 2 MiB */ +#define MEMORY_LITE 1048576 /* 1 MiB */ #define MEMORY_HEAVY 4194304 /* 4 MiB */ struct cryptonight_ctx { diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index fbe329dd..d5a2150a 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -732,6 +732,93 @@ public: } } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + const uint8_t* l[NUM_HASH_BLOCKS]; + uint64_t* h[NUM_HASH_BLOCKS]; + uint64_t al[NUM_HASH_BLOCKS]; + uint64_t ah[NUM_HASH_BLOCKS]; + __m128i bx[NUM_HASH_BLOCKS]; + uint64_t idx[NUM_HASH_BLOCKS]; + uint64_t tweak1_2[NUM_HASH_BLOCKS]; + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + keccak(static_cast(input) + hashBlock * size, (int) size, ctx->state[hashBlock], 200); + tweak1_2[hashBlock] = (*reinterpret_cast(input + 35 + hashBlock * size) ^ + *(reinterpret_cast(ctx->state[hashBlock]) + 24)); + } + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + l[hashBlock] = ctx->memory + hashBlock * MEM; + h[hashBlock] = reinterpret_cast(ctx->state[hashBlock]); + + cn_explode_scratchpad((__m128i*) h[hashBlock], (__m128i*) l[hashBlock]); + + al[hashBlock] = h[hashBlock][0] ^ h[hashBlock][4]; + ah[hashBlock] = h[hashBlock][1] ^ h[hashBlock][5]; + bx[hashBlock] = + _mm_set_epi64x(h[hashBlock][3] ^ h[hashBlock][7], h[hashBlock][2] ^ h[hashBlock][6]); + idx[hashBlock] = h[hashBlock][0] ^ h[hashBlock][4]; + } + + for (size_t i = 0; i < ITERATIONS; i++) { + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + __m128i cx; + + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*)&l[hashBlock][idx[hashBlock] & MASK], _mm_set_epi64x(ah[hashBlock], al[hashBlock])); + } else { + cx = _mm_load_si128((__m128i *) &l[hashBlock][idx[hashBlock] & MASK]); +# ifndef XMRIG_ARMv7 + cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah[hashBlock], al[hashBlock]); +# endif + } + + _mm_store_si128((__m128i*) &l[hashBlock][idx[hashBlock] & MASK], + _mm_xor_si128(bx[hashBlock], cx)); + + const uint8_t tmp = reinterpret_cast(&l[hashBlock][idx[hashBlock] & MASK])[11]; + static const uint32_t table = 0x75310; + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l[hashBlock][idx[hashBlock] & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx[hashBlock] = EXTRACT64(cx); + bx[hashBlock] = cx; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[0]; + ch = ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[1]; + lo = __umul128(idx[hashBlock], cl, &hi); + + al[hashBlock] += hi; + ah[hashBlock] += lo; + + ah[hashBlock] ^= tweak1_2[hashBlock]; + + ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[0] = al[hashBlock]; + ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[1] = ah[hashBlock]; + + ah[hashBlock] ^= tweak1_2[hashBlock]; + + ((uint64_t*)&l[hashBlock][idx[hashBlock] & MASK])[1] ^= ((uint64_t*)&l[hashBlock][idx[hashBlock] & MASK])[0]; + + ah[hashBlock] ^= ch; + al[hashBlock] ^= cl; + idx[hashBlock] = al[hashBlock]; + } + } + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + cn_implode_scratchpad((__m128i*) l[hashBlock], (__m128i*) h[hashBlock]); + keccakf(h[hashBlock], 24); + extra_hashes[ctx->state[hashBlock][0] & 3](ctx->state[hashBlock], 200, + output + hashBlock * 32); + } + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, @@ -949,6 +1036,78 @@ public: extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + const uint8_t* l; + uint64_t* h; + uint64_t al; + uint64_t ah; + __m128i bx; + uint64_t idx; + + keccak(static_cast(input), (int) size, ctx->state[0], 200); + + uint64_t tweak1_2 = (*reinterpret_cast(input + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + l = ctx->memory; + h = reinterpret_cast(ctx->state[0]); + + cn_explode_scratchpad((__m128i*) h, (__m128i*) l); + + al = h[0] ^ h[4]; + ah = h[1] ^ h[5]; + bx = _mm_set_epi64x(h[3] ^ h[7], h[2] ^ h[6]); + idx = h[0] ^ h[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx; + + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*)&l[idx & MASK], _mm_set_epi64x(ah, al)); + } + else { + cx = _mm_load_si128((__m128i *) &l[idx & MASK]); +# ifndef XMRIG_ARMv7 + cx = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah, al); +# endif + } + + _mm_store_si128((__m128i*) &l[idx & MASK], _mm_xor_si128(bx, cx)); + const uint8_t tmp = reinterpret_cast(&l[idx & MASK])[11]; + static const uint32_t table = 0x75310; + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l[idx & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + idx = EXTRACT64(cx); + bx = cx; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l[idx & MASK])[0]; + ch = ((uint64_t*) &l[idx & MASK])[1]; + lo = __umul128(idx, cl, &hi); + + al += hi; + ah += lo; + + ah ^= tweak1_2; + ((uint64_t*) &l[idx & MASK])[0] = al; + ((uint64_t*) &l[idx & MASK])[1] = ah; + ah ^= tweak1_2; + + ((uint64_t*)&l[idx & MASK])[1] ^= ((uint64_t*)&l[idx & MASK])[0]; + + ah ^= ch; + al ^= cl; + idx = al; + } + + cn_implode_scratchpad((__m128i*) l, (__m128i*) h); + keccakf(h, 24); + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, @@ -1226,6 +1385,120 @@ public: extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak(input, (int) size, ctx->state[0], 200); + keccak(input + size, (int) size, ctx->state[1], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(input + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(input + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } else { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + +# ifndef XMRIG_ARMv7 + cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); +# endif + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + + bx0 = cx0; + bx1 = cx1; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + + keccakf(h0, 24); + keccakf(h1, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, @@ -1618,6 +1891,164 @@ public: extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak(input, (int) size, ctx->state[0], 200); + keccak(input + size, (int) size, ctx->state[1], 200); + keccak(input + 2 * size, (int) size, ctx->state[2], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(input + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(input + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(input + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + } + else { + cx0 = _mm_load_si128((__m128i *) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i *) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i *) &l2[idx2 & MASK]); +# ifndef XMRIG_ARMv7 + cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); + cx2 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx2, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah2, al2); +# endif + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, @@ -2125,6 +2556,206 @@ public: extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak(input, (int) size, ctx->state[0], 200); + keccak(input + size, (int) size, ctx->state[1], 200); + keccak(input + 2 * size, (int) size, ctx->state[2], 200); + keccak(input + 3 * size, (int) size, ctx->state[3], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(input + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(input + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(input + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + uint64_t tweak1_2_3 = (*reinterpret_cast(input + 35 + 3 * size) ^ + *(reinterpret_cast(ctx->state[3]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + const uint8_t* l3 = ctx->memory + 3 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + uint64_t* h3 = reinterpret_cast(ctx->state[3]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + cn_explode_scratchpad((__m128i*) h3, (__m128i*) l3); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t al3 = h3[0] ^h3[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + uint64_t ah3 = h3[1] ^h3[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + __m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + uint64_t idx3 = h3[0] ^h3[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + __m128i cx3; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + cx3 = soft_aesenc((uint32_t*)&l3[idx3 & MASK], _mm_set_epi64x(ah3, al3)); + } else { +# ifndef XMRIG_ARMv7 + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i*) &l2[idx2 & MASK]); + cx3 = _mm_load_si128((__m128i*) &l3[idx3 & MASK]); + + cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); + cx2 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx2, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah2, al2); + cx3 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx3, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah3, al3); +# endif + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + _mm_store_si128((__m128i*) &l3[idx3 & MASK], _mm_xor_si128(bx3, cx3)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l3[idx3 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l3[idx3 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + idx3 = EXTRACT64(cx3); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + bx3 = cx3; + + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + + + cl = ((uint64_t*) &l3[idx3 & MASK])[0]; + ch = ((uint64_t*) &l3[idx3 & MASK])[1]; + lo = __umul128(idx3, cl, &hi); + + al3 += hi; + ah3 += lo; + + ah3 ^= tweak1_2_3; + ((uint64_t*) &l3[idx3 & MASK])[0] = al3; + ((uint64_t*) &l3[idx3 & MASK])[1] = ah3; + ah3 ^= tweak1_2_3; + + ((uint64_t*)&l3[idx3 & MASK])[1] ^= ((uint64_t*)&l3[idx3 & MASK])[0]; + + ah3 ^= ch; + al3 ^= cl; + idx3 = al3; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + cn_implode_scratchpad((__m128i*) l3, (__m128i*) h3); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + keccakf(h3, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, @@ -2744,6 +3375,248 @@ public: extra_hashes[ctx->state[4][0] & 3](ctx->state[4], 200, output + 128); } + inline static void hashLiteIpbc (const uint8_t* __restrict__ input, + size_t size, + uint8_t *__restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak(input, (int) size, ctx->state[0], 200); + keccak(input + size, (int) size, ctx->state[1], 200); + keccak(input + 2 * size, (int) size, ctx->state[2], 200); + keccak(input + 3 * size, (int) size, ctx->state[3], 200); + keccak(input + 4 * size, (int) size, ctx->state[4], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(input + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(input + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(input + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + uint64_t tweak1_2_3 = (*reinterpret_cast(input + 35 + 3 * size) ^ + *(reinterpret_cast(ctx->state[3]) + 24)); + uint64_t tweak1_2_4 = (*reinterpret_cast(input + 35 + 4 * size) ^ + *(reinterpret_cast(ctx->state[4]) + 24)); + + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + const uint8_t* l3 = ctx->memory + 3 * MEM; + const uint8_t* l4 = ctx->memory + 4 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + uint64_t* h3 = reinterpret_cast(ctx->state[3]); + uint64_t* h4 = reinterpret_cast(ctx->state[4]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + cn_explode_scratchpad((__m128i*) h3, (__m128i*) l3); + cn_explode_scratchpad((__m128i*) h4, (__m128i*) l4); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t al3 = h3[0] ^h3[4]; + uint64_t al4 = h4[0] ^h4[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + uint64_t ah3 = h3[1] ^h3[5]; + uint64_t ah4 = h4[1] ^h4[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + __m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]); + __m128i bx4 = _mm_set_epi64x(h4[3] ^ h4[7], h4[2] ^ h4[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + uint64_t idx3 = h3[0] ^h3[4]; + uint64_t idx4 = h4[0] ^h4[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + __m128i cx3; + __m128i cx4; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + cx3 = soft_aesenc((uint32_t*)&l3[idx3 & MASK], _mm_set_epi64x(ah3, al3)); + cx4 = soft_aesenc((uint32_t*)&l4[idx4 & MASK], _mm_set_epi64x(ah4, al4)); + } else { +# ifndef XMRIG_ARMv7 + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i*) &l2[idx2 & MASK]); + cx3 = _mm_load_si128((__m128i*) &l3[idx3 & MASK]); + cx4 = _mm_load_si128((__m128i*) &l4[idx4 & MASK]); + + cx0 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx0, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah0, al0); + cx1 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx1, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah1, al1); + cx2 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx2, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah2, al2); + cx3 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx3, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah3, al3); + cx4 = vreinterpretq_m128i_u8(vaesmcq_u8(vaeseq_u8(cx4, vdupq_n_u8(0)))) ^ _mm_set_epi64x(ah4, al4); +# endif + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + _mm_store_si128((__m128i*) &l3[idx3 & MASK], _mm_xor_si128(bx3, cx3)); + _mm_store_si128((__m128i*) &l4[idx4 & MASK], _mm_xor_si128(bx4, cx4)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l3[idx3 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l3[idx3 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l4[idx4 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l4[idx4 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + idx3 = EXTRACT64(cx3); + idx4 = EXTRACT64(cx4); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + bx3 = cx3; + bx4 = cx4; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + + + cl = ((uint64_t*) &l3[idx3 & MASK])[0]; + ch = ((uint64_t*) &l3[idx3 & MASK])[1]; + lo = __umul128(idx3, cl, &hi); + + al3 += hi; + ah3 += lo; + + ah3 ^= tweak1_2_3; + ((uint64_t*) &l3[idx3 & MASK])[0] = al3; + ((uint64_t*) &l3[idx3 & MASK])[1] = ah3; + ah3 ^= tweak1_2_3; + + ((uint64_t*)&l3[idx3 & MASK])[1] ^= ((uint64_t*)&l3[idx3 & MASK])[0]; + + ah3 ^= ch; + al3 ^= cl; + idx3 = al3; + + + cl = ((uint64_t*) &l4[idx4 & MASK])[0]; + ch = ((uint64_t*) &l4[idx4 & MASK])[1]; + lo = __umul128(idx4, cl, &hi); + + al4 += hi; + ah4 += lo; + + ah4 ^= tweak1_2_4; + ((uint64_t*) &l4[idx4 & MASK])[0] = al4; + ((uint64_t*) &l4[idx4 & MASK])[1] = ah4; + ah4 ^= tweak1_2_4; + + ((uint64_t*)&l4[idx4 & MASK])[1] ^= ((uint64_t*)&l4[idx4 & MASK])[0]; + + ah4 ^= ch; + al4 ^= cl; + idx4 = al4; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + cn_implode_scratchpad((__m128i*) l3, (__m128i*) h3); + cn_implode_scratchpad((__m128i*) l4, (__m128i*) h4); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + keccakf(h3, 24); + keccakf(h4, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); + extra_hashes[ctx->state[4][0] & 3](ctx->state[4], 200, output + 128); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t *__restrict__ output, diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h index 3c103693..b9c735f4 100644 --- a/src/crypto/CryptoNight_test.h +++ b/src/crypto/CryptoNight_test.h @@ -26,130 +26,174 @@ const static uint8_t test_input[] = { - 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, - 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, - 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, - 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, - 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, - 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, - 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, - 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, - 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, - 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01, - 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, - 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, - 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, - 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, - 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, - 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, - 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, - 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, - 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, - 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01, - 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, - 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, - 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, - 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, - 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, - 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, - 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, - 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, - 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, - 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01 + 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, + 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, + 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, + 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, + 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, + 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, + 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, + 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, + 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, + 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01, + 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, + 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, + 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, + 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, + 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, + 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, + 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, + 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, + 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, + 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01, + 0x01, 0x00, 0xFB, 0x8E, 0x8A, 0xC8, 0x05, 0x89, 0x93, 0x23, 0x37, 0x1B, 0xB7, 0x90, 0xDB, 0x19, + 0x21, 0x8A, 0xFD, 0x8D, 0xB8, 0xE3, 0x75, 0x5D, 0x8B, 0x90, 0xF3, 0x9B, 0x3D, 0x55, 0x06, 0xA9, + 0xAB, 0xCE, 0x4F, 0xA9, 0x12, 0x24, 0x45, 0x00, 0x00, 0x00, 0x00, 0xEE, 0x81, 0x46, 0xD4, 0x9F, + 0xA9, 0x3E, 0xE7, 0x24, 0xDE, 0xB5, 0x7D, 0x12, 0xCB, 0xC6, 0xC6, 0xF3, 0xB9, 0x24, 0xD9, 0x46, + 0x12, 0x7C, 0x7A, 0x97, 0x41, 0x8F, 0x93, 0x48, 0x82, 0x8F, 0x0F, 0x02, + 0x03, 0x05, 0xA0, 0xDB, 0xD6, 0xBF, 0x05, 0xCF, 0x16, 0xE5, 0x03, 0xF3, 0xA6, 0x6F, 0x78, 0x00, + 0x7C, 0xBF, 0x34, 0x14, 0x43, 0x32, 0xEC, 0xBF, 0xC2, 0x2E, 0xD9, 0x5C, 0x87, 0x00, 0x38, 0x3B, + 0x30, 0x9A, 0xCE, 0x19, 0x23, 0xA0, 0x96, 0x4B, 0x00, 0x00, 0x00, 0x08, 0xBA, 0x93, 0x9A, 0x62, + 0x72, 0x4C, 0x0D, 0x75, 0x81, 0xFC, 0xE5, 0x76, 0x1E, 0x9D, 0x8A, 0x0E, 0x6A, 0x1C, 0x3F, 0x92, + 0x4F, 0xDD, 0x84, 0x93, 0xD1, 0x11, 0x56, 0x49, 0xC0, 0x5E, 0xB6, 0x01 }; const static uint8_t test_output[] = { - 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, - 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, - 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, - 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00, + 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, + 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, + 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, + 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00, - 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, - 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, - 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, - 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00, + 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, + 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, + 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, + 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00, - 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, - 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, - 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, - 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00 + 0x1B, 0x60, 0x6A, 0x3F, 0x4A, 0x07, 0xD6, 0x48, 0x9A, 0x1B, 0xCD, 0x07, 0x69, 0x7B, 0xD1, 0x66, + 0x96, 0xB6, 0x1C, 0x8A, 0xE9, 0x82, 0xF6, 0x1A, 0x90, 0x16, 0x0F, 0x4E, 0x52, 0x82, 0x8A, 0x7F, + 0x1A, 0x3F, 0xFB, 0xEE, 0x90, 0x9B, 0x42, 0x0D, 0x91, 0xF7, 0xBE, 0x6E, 0x5F, 0xB5, 0x6D, 0xB7, + 0x1B, 0x31, 0x10, 0xD8, 0x86, 0x01, 0x1E, 0x87, 0x7E, 0xE5, 0x78, 0x6A, 0xFD, 0x08, 0x01, 0x00 }; const static uint8_t test_output_light[] = { - 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, - 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, - 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, - 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88, + 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, + 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, + 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, + 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88, - 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, - 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, - 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, - 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88, + 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, + 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, + 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, + 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88, - 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, - 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, - 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, - 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88 + 0x28, 0xA2, 0x2B, 0xAD, 0x3F, 0x93, 0xD1, 0x40, 0x8F, 0xCA, 0x47, 0x2E, 0xB5, 0xAD, 0x1C, 0xBE, + 0x75, 0xF2, 0x1D, 0x05, 0x3C, 0x8C, 0xE5, 0xB3, 0xAF, 0x10, 0x5A, 0x57, 0x71, 0x3E, 0x21, 0xDD, + 0x36, 0x95, 0xB4, 0xB5, 0x3B, 0xB0, 0x03, 0x58, 0xB0, 0xAD, 0x38, 0xDC, 0x16, 0x0F, 0xEB, 0x9E, + 0x00, 0x4E, 0xEC, 0xE0, 0x9B, 0x83, 0xA7, 0x2E, 0xF6, 0xBA, 0x98, 0x64, 0xD3, 0x51, 0x0C, 0x88 }; const static uint8_t test_input_monero_v2_pow_0[] = { - 0x85, 0x19, 0xe0, 0x39, 0x17, 0x2b, 0x0d, 0x70, 0xe5, 0xca, 0x7b, 0x33, 0x83, 0xd6, 0xb3, 0x16, - 0x73, 0x15, 0xa4, 0x22, 0x74, 0x7b, 0x73, 0xf0, 0x19, 0xcf, 0x95, 0x28, 0xf0, 0xfd, 0xe3, 0x41, - 0xfd, 0x0f, 0x2a, 0x63, 0x03, 0x0b, 0xa6, 0x45, 0x05, 0x25, 0xcf, 0x6d, 0xe3, 0x18, 0x37, 0x66, - 0x9a, 0xf6, 0xf1, 0xdf, 0x81, 0x31, 0xfa, 0xf5, 0x0a, 0xaa, 0xb8, 0xd3, 0xa7, 0x40, 0x55, 0x89 + 0x85, 0x19, 0xe0, 0x39, 0x17, 0x2b, 0x0d, 0x70, 0xe5, 0xca, 0x7b, 0x33, 0x83, 0xd6, 0xb3, 0x16, + 0x73, 0x15, 0xa4, 0x22, 0x74, 0x7b, 0x73, 0xf0, 0x19, 0xcf, 0x95, 0x28, 0xf0, 0xfd, 0xe3, 0x41, + 0xfd, 0x0f, 0x2a, 0x63, 0x03, 0x0b, 0xa6, 0x45, 0x05, 0x25, 0xcf, 0x6d, 0xe3, 0x18, 0x37, 0x66, + 0x9a, 0xf6, 0xf1, 0xdf, 0x81, 0x31, 0xfa, 0xf5, 0x0a, 0xaa, 0xb8, 0xd3, 0xa7, 0x40, 0x55, 0x89 }; const static uint8_t test_input_monero_v2_pow_1[] = { - 0x37, 0xa6, 0x36, 0xd7, 0xda, 0xfd, 0xf2, 0x59, 0xb7, 0x28, 0x7e, 0xdd, 0xca, 0x2f, 0x58, 0x09, - 0x9e, 0x98, 0x61, 0x9d, 0x2f, 0x99, 0xbd, 0xb8, 0x96, 0x9d, 0x7b, 0x14, 0x49, 0x81, 0x02, 0xcc, - 0x06, 0x52, 0x01, 0xc8, 0xbe, 0x90, 0xbd, 0x77, 0x73, 0x23, 0xf4, 0x49, 0x84, 0x8b, 0x21, 0x5d, - 0x29, 0x77, 0xc9, 0x2c, 0x4c, 0x1c, 0x2d, 0xa3, 0x6a, 0xb4, 0x6b, 0x2e, 0x38, 0x96, 0x89, 0xed, - 0x97, 0xc1, 0x8f, 0xec, 0x08, 0xcd, 0x3b, 0x03, 0x23, 0x5c, 0x5e, 0x4c, 0x62, 0xa3, 0x7a, 0xd8, - 0x8c, 0x7b, 0x67, 0x93, 0x24, 0x95, 0xa7, 0x10, 0x90, 0xe8, 0x5d, 0xd4, 0x02, 0x0a, 0x93, 0x00 + 0x37, 0xa6, 0x36, 0xd7, 0xda, 0xfd, 0xf2, 0x59, 0xb7, 0x28, 0x7e, 0xdd, 0xca, 0x2f, 0x58, 0x09, + 0x9e, 0x98, 0x61, 0x9d, 0x2f, 0x99, 0xbd, 0xb8, 0x96, 0x9d, 0x7b, 0x14, 0x49, 0x81, 0x02, 0xcc, + 0x06, 0x52, 0x01, 0xc8, 0xbe, 0x90, 0xbd, 0x77, 0x73, 0x23, 0xf4, 0x49, 0x84, 0x8b, 0x21, 0x5d, + 0x29, 0x77, 0xc9, 0x2c, 0x4c, 0x1c, 0x2d, 0xa3, 0x6a, 0xb4, 0x6b, 0x2e, 0x38, 0x96, 0x89, 0xed, + 0x97, 0xc1, 0x8f, 0xec, 0x08, 0xcd, 0x3b, 0x03, 0x23, 0x5c, 0x5e, 0x4c, 0x62, 0xa3, 0x7a, 0xd8, + 0x8c, 0x7b, 0x67, 0x93, 0x24, 0x95, 0xa7, 0x10, 0x90, 0xe8, 0x5d, 0xd4, 0x02, 0x0a, 0x93, 0x00 }; const static uint8_t test_input_monero_v2_pow_2[] = { - 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, - 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, - 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb }; const static uint8_t test_output_monero_v2_pow[3][32] = { - {0x5b, 0xb4, 0x0c, 0x58, 0x80, 0xce, 0xf2, 0xf7, 0x39, 0xbd, 0xb6, 0xaa, 0xaf, 0x16, 0x16, 0x1e, - 0xaa, 0xe5, 0x55, 0x30, 0xe7, 0xb1, 0x0d, 0x7e, 0xa9, 0x96, 0xb7, 0x51, 0xa2, 0x99, 0xe9, 0x49}, - {0x61, 0x3e, 0x63, 0x85, 0x05, 0xba, 0x1f, 0xd0, 0x5f, 0x42, 0x8d, 0x5c, 0x9f, 0x8e, 0x08, 0xf8, - 0x16, 0x56, 0x14, 0x34, 0x2d, 0xac, 0x41, 0x9a, 0xdc, 0x6a, 0x47, 0xdc, 0xe2, 0x57, 0xeb, 0x3e}, - {0xed, 0x08, 0x2e, 0x49, 0xdb, 0xd5, 0xbb, 0xe3, 0x4a, 0x37, 0x26, 0xa0, 0xd1, 0xda, 0xd9, 0x81, - 0x14, 0x60, 0x62, 0xb3, 0x9d, 0x36, 0xd6, 0x2c, 0x71, 0xeb, 0x1e, 0xd8, 0xab, 0x49, 0x45, 0x9b} + {0x5b, 0xb4, 0x0c, 0x58, 0x80, 0xce, 0xf2, 0xf7, 0x39, 0xbd, 0xb6, 0xaa, 0xaf, 0x16, 0x16, 0x1e, + 0xaa, 0xe5, 0x55, 0x30, 0xe7, 0xb1, 0x0d, 0x7e, 0xa9, 0x96, 0xb7, 0x51, 0xa2, 0x99, 0xe9, 0x49}, + {0x61, 0x3e, 0x63, 0x85, 0x05, 0xba, 0x1f, 0xd0, 0x5f, 0x42, 0x8d, 0x5c, 0x9f, 0x8e, 0x08, 0xf8, + 0x16, 0x56, 0x14, 0x34, 0x2d, 0xac, 0x41, 0x9a, 0xdc, 0x6a, 0x47, 0xdc, 0xe2, 0x57, 0xeb, 0x3e}, + {0xed, 0x08, 0x2e, 0x49, 0xdb, 0xd5, 0xbb, 0xe3, 0x4a, 0x37, 0x26, 0xa0, 0xd1, 0xda, 0xd9, 0x81, + 0x14, 0x60, 0x62, 0xb3, 0x9d, 0x36, 0xd6, 0x2c, 0x71, 0xeb, 0x1e, 0xd8, 0xab, 0x49, 0x45, 0x9b} }; const static uint8_t test_output_monero_v2_pow_light[3][32] = { - {0xbb, 0x19, 0x6c, 0x4c, 0x0c, 0x9d, 0xc1, 0xc4, 0xe4, 0x4c, 0x2a, 0x6f, 0x9e, 0x61, 0x20, 0x0f, - 0xe3, 0xc8, 0xb4, 0xef, 0x23, 0x21, 0x34, 0xe6, 0x5c, 0x3c, 0x78, 0x62, 0xc7, 0xd3, 0xdf, 0x6a}, - {0x45, 0x21, 0x03, 0x73, 0x1d, 0xd8, 0xd7, 0x0c, 0xe3, 0x2f, 0x72, 0x6b, 0x8e, 0x71, 0xfc, 0xd9, - 0x10, 0x05, 0xfb, 0x3c, 0xb2, 0xab, 0xd7, 0x8f, 0x2b, 0x73, 0x57, 0xbb, 0x07, 0xf8, 0xc8, 0xbc}, - {0x4e, 0x78, 0x53, 0x76, 0xed, 0x27, 0x33, 0x26, 0x2d, 0x83, 0xcc, 0x25, 0x32, 0x1a, 0x9d, 0x00, - 0x03, 0xf5, 0x39, 0x53, 0x15, 0xde, 0x91, 0x9a, 0xcf, 0x1b, 0x97, 0xf0, 0xa8, 0x4f, 0xbd, 0x2d} + {0xbb, 0x19, 0x6c, 0x4c, 0x0c, 0x9d, 0xc1, 0xc4, 0xe4, 0x4c, 0x2a, 0x6f, 0x9e, 0x61, 0x20, 0x0f, + 0xe3, 0xc8, 0xb4, 0xef, 0x23, 0x21, 0x34, 0xe6, 0x5c, 0x3c, 0x78, 0x62, 0xc7, 0xd3, 0xdf, 0x6a}, + {0x45, 0x21, 0x03, 0x73, 0x1d, 0xd8, 0xd7, 0x0c, 0xe3, 0x2f, 0x72, 0x6b, 0x8e, 0x71, 0xfc, 0xd9, + 0x10, 0x05, 0xfb, 0x3c, 0xb2, 0xab, 0xd7, 0x8f, 0x2b, 0x73, 0x57, 0xbb, 0x07, 0xf8, 0xc8, 0xbc}, + {0x4e, 0x78, 0x53, 0x76, 0xed, 0x27, 0x33, 0x26, 0x2d, 0x83, 0xcc, 0x25, 0x32, 0x1a, 0x9d, 0x00, + 0x03, 0xf5, 0x39, 0x53, 0x15, 0xde, 0x91, 0x9a, 0xcf, 0x1b, 0x97, 0xf0, 0xa8, 0x4f, 0xbd, 0x2d} +}; + +const static uint8_t test_input_lite_ipbc[] = { + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb, + + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb, + + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb, + + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb, + + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb, + + 0x38, 0x27, 0x4c, 0x97, 0xc4, 0x5a, 0x17, 0x2c, 0xfc, 0x97, 0x67, 0x98, 0x70, 0x42, 0x2e, 0x3a, + 0x1a, 0xb0, 0x78, 0x49, 0x60, 0xc6, 0x05, 0x14, 0xd8, 0x16, 0x27, 0x14, 0x15, 0xc3, 0x06, 0xee, + 0x3a, 0x3e, 0xd1, 0xa7, 0x7e, 0x31, 0xf6, 0xa8, 0x85, 0xc3, 0xcb +}; + + +const static uint8_t test_output_lite_ipbc[] = { + 0xb4, 0x42, 0xa2, 0xb9, 0x56, 0xe6, 0x3f, 0xef, 0xe8, 0x1b, 0xfa, 0x8b, 0xcb, 0xc4, 0xdd, 0xd6, 0xb6, 0x3f, + 0x86, 0x53, 0x0e, 0xea, 0xa4, 0x65, 0x88, 0x31, 0x1d, 0x29, 0x0a, 0xfb, 0xb2, 0xc0, + + 0xb4, 0x42, 0xa2, 0xb9, 0x56, 0xe6, 0x3f, 0xef, 0xe8, 0x1b, 0xfa, 0x8b, 0xcb, 0xc4, 0xdd, 0xd6, 0xb6, 0x3f, + 0x86, 0x53, 0x0e, 0xea, 0xa4, 0x65, 0x88, 0x31, 0x1d, 0x29, 0x0a, 0xfb, 0xb2, 0xc0, + + 0xb4, 0x42, 0xa2, 0xb9, 0x56, 0xe6, 0x3f, 0xef, 0xe8, 0x1b, 0xfa, 0x8b, 0xcb, 0xc4, 0xdd, 0xd6, 0xb6, 0x3f, + 0x86, 0x53, 0x0e, 0xea, 0xa4, 0x65, 0x88, 0x31, 0x1d, 0x29, 0x0a, 0xfb, 0xb2, 0xc0, + + 0xb4, 0x42, 0xa2, 0xb9, 0x56, 0xe6, 0x3f, 0xef, 0xe8, 0x1b, 0xfa, 0x8b, 0xcb, 0xc4, 0xdd, 0xd6, 0xb6, 0x3f, + 0x86, 0x53, 0x0e, 0xea, 0xa4, 0x65, 0x88, 0x31, 0x1d, 0x29, 0x0a, 0xfb, 0xb2, 0xc0, + + 0xb4, 0x42, 0xa2, 0xb9, 0x56, 0xe6, 0x3f, 0xef, 0xe8, 0x1b, 0xfa, 0x8b, 0xcb, 0xc4, 0xdd, 0xd6, 0xb6, 0x3f, + 0x86, 0x53, 0x0e, 0xea, 0xa4, 0x65, 0x88, 0x31, 0x1d, 0x29, 0x0a, 0xfb, 0xb2, 0xc0 }; const static uint8_t test_output_heavy[] = { - 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, - 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, - 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, - 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2, + 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, + 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, + 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, + 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2, - 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, - 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, - 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, - 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2, + 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, + 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, + 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, + 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2, - 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, - 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, - 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, - 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2 + 0x4D, 0x94, 0x7D, 0xD6, 0xDB, 0x6E, 0x07, 0x48, 0x26, 0x4A, 0x51, 0x2E, 0xAC, 0xF3, 0x25, 0x4A, + 0x1F, 0x1A, 0xA2, 0x5B, 0xFC, 0x0A, 0xAD, 0x82, 0xDE, 0xA8, 0x99, 0x96, 0x88, 0x52, 0xD2, 0x7D, + 0x99, 0x83, 0xF2, 0x1B, 0xDF, 0x20, 0x10, 0xA8, 0xD7, 0x07, 0xBB, 0x2F, 0x14, 0xD7, 0x86, 0x64, + 0xBB, 0xE1, 0x18, 0x7F, 0x55, 0x01, 0x4B, 0x39, 0xE5, 0xF3, 0xD6, 0x93, 0x28, 0xE4, 0x8F, 0xC2 }; diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 4e602e7e..18488bff 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -626,6 +626,91 @@ public: } } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + const uint8_t* l[NUM_HASH_BLOCKS]; + uint64_t* h[NUM_HASH_BLOCKS]; + uint64_t al[NUM_HASH_BLOCKS]; + uint64_t ah[NUM_HASH_BLOCKS]; + __m128i bx[NUM_HASH_BLOCKS]; + uint64_t idx[NUM_HASH_BLOCKS]; + uint64_t tweak1_2[NUM_HASH_BLOCKS]; + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + keccak(static_cast(input) + hashBlock * size, (int) size, ctx->state[hashBlock], 200); + tweak1_2[hashBlock] = (*reinterpret_cast(reinterpret_cast(input) + 35 + hashBlock * size) ^ + *(reinterpret_cast(ctx->state[hashBlock]) + 24)); + } + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + l[hashBlock] = ctx->memory + hashBlock * MEM; + h[hashBlock] = reinterpret_cast(ctx->state[hashBlock]); + + cn_explode_scratchpad((__m128i*) h[hashBlock], (__m128i*) l[hashBlock]); + + al[hashBlock] = h[hashBlock][0] ^ h[hashBlock][4]; + ah[hashBlock] = h[hashBlock][1] ^ h[hashBlock][5]; + bx[hashBlock] = + _mm_set_epi64x(h[hashBlock][3] ^ h[hashBlock][7], h[hashBlock][2] ^ h[hashBlock][6]); + idx[hashBlock] = h[hashBlock][0] ^ h[hashBlock][4]; + } + + for (size_t i = 0; i < ITERATIONS; i++) { + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + __m128i cx; + + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*) &l[hashBlock][idx[hashBlock] & MASK], _mm_set_epi64x(ah[hashBlock], al[hashBlock])); + } else { + cx = _mm_load_si128((__m128i*) &l[hashBlock][idx[hashBlock] & MASK]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah[hashBlock], al[hashBlock])); + } + + _mm_store_si128((__m128i*) &l[hashBlock][idx[hashBlock] & MASK], + _mm_xor_si128(bx[hashBlock], cx)); + + const uint8_t tmp = reinterpret_cast(&l[hashBlock][idx[hashBlock] & MASK])[11]; + static const uint32_t table = 0x75310; + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l[hashBlock][idx[hashBlock] & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx[hashBlock] = EXTRACT64(cx); + bx[hashBlock] = cx; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[0]; + ch = ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[1]; + lo = __umul128(idx[hashBlock], cl, &hi); + + al[hashBlock] += hi; + ah[hashBlock] += lo; + + ah[hashBlock] ^= tweak1_2[hashBlock]; + + ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[0] = al[hashBlock]; + ((uint64_t*) &l[hashBlock][idx[hashBlock] & MASK])[1] = ah[hashBlock]; + + ah[hashBlock] ^= tweak1_2[hashBlock]; + + ((uint64_t*)&l[hashBlock][idx[hashBlock] & MASK])[1] ^= ((uint64_t*)&l[hashBlock][idx[hashBlock] & MASK])[0]; + + ah[hashBlock] ^= ch; + al[hashBlock] ^= cl; + idx[hashBlock] = al[hashBlock]; + } + } + + for (size_t hashBlock = 0; hashBlock < NUM_HASH_BLOCKS; ++hashBlock) { + cn_implode_scratchpad((__m128i*) l[hashBlock], (__m128i*) h[hashBlock]); + keccakf(h[hashBlock], 24); + extra_hashes[ctx->state[hashBlock][0] & 3](ctx->state[hashBlock], 200, + output + hashBlock * 32); + } + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, @@ -835,6 +920,75 @@ public: extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + const uint8_t* l; + uint64_t* h; + uint64_t al; + uint64_t ah; + __m128i bx; + uint64_t idx; + + keccak(static_cast(input), (int) size, ctx->state[0], 200); + + uint64_t tweak1_2 = (*reinterpret_cast(reinterpret_cast(input) + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + l = ctx->memory; + h = reinterpret_cast(ctx->state[0]); + + cn_explode_scratchpad((__m128i*) h, (__m128i*) l); + + al = h[0] ^ h[4]; + ah = h[1] ^ h[5]; + bx = _mm_set_epi64x(h[3] ^ h[7], h[2] ^ h[6]); + idx = h[0] ^ h[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx; + + if (SOFT_AES) { + cx = soft_aesenc((uint32_t*)&l[idx & MASK], _mm_set_epi64x(ah, al)); + } else { + cx = _mm_load_si128((__m128i*) &l[idx & MASK]); + cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah, al)); + } + + _mm_store_si128((__m128i*) &l[idx & MASK], _mm_xor_si128(bx, cx)); + const uint8_t tmp = reinterpret_cast(&l[idx & MASK])[11]; + static const uint32_t table = 0x75310; + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l[idx & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + idx = EXTRACT64(cx); + bx = cx; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l[idx & MASK])[0]; + ch = ((uint64_t*) &l[idx & MASK])[1]; + lo = __umul128(idx, cl, &hi); + + al += hi; + ah += lo; + + ah ^= tweak1_2; + ((uint64_t*) &l[idx & MASK])[0] = al; + ((uint64_t*) &l[idx & MASK])[1] = ah; + ah ^= tweak1_2; + + ((uint64_t*)&l[idx & MASK])[1] ^= ((uint64_t*)&l[idx & MASK])[0]; + + ah ^= ch; + al ^= cl; + idx = al; + } + + cn_implode_scratchpad((__m128i*) l, (__m128i*) h); + keccakf(h, 24); + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, @@ -1105,6 +1259,118 @@ public: extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak((const uint8_t*) input, (int) size, ctx->state[0], 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state[1], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(reinterpret_cast(input) + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(reinterpret_cast(input) + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + } else { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + + cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); + cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + + bx0 = cx0; + bx1 = cx1; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + + keccakf(h0, 24); + keccakf(h1, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, @@ -1492,6 +1758,162 @@ public: extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak((const uint8_t*) input, (int) size, ctx->state[0], 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state[1], 200); + keccak((const uint8_t*) input + 2 * size, (int) size, ctx->state[2], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(reinterpret_cast(input) + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(reinterpret_cast(input) + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + } else { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i*) &l2[idx2 & MASK]); + + cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); + cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); + cx2 = _mm_aesenc_si128(cx2, _mm_set_epi64x(ah2, al2)); + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, @@ -1993,6 +2415,204 @@ public: extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak((const uint8_t*) input, (int) size, ctx->state[0], 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state[1], 200); + keccak((const uint8_t*) input + 2 * size, (int) size, ctx->state[2], 200); + keccak((const uint8_t*) input + 3 * size, (int) size, ctx->state[3], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(reinterpret_cast(input) + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(reinterpret_cast(input) + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + uint64_t tweak1_2_3 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 3 * size) ^ + *(reinterpret_cast(ctx->state[3]) + 24)); + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + const uint8_t* l3 = ctx->memory + 3 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + uint64_t* h3 = reinterpret_cast(ctx->state[3]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + cn_explode_scratchpad((__m128i*) h3, (__m128i*) l3); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t al3 = h3[0] ^h3[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + uint64_t ah3 = h3[1] ^h3[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + __m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + uint64_t idx3 = h3[0] ^h3[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + __m128i cx3; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + cx3 = soft_aesenc((uint32_t*)&l3[idx3 & MASK], _mm_set_epi64x(ah3, al3)); + } else { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i*) &l2[idx2 & MASK]); + cx3 = _mm_load_si128((__m128i*) &l3[idx3 & MASK]); + + cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); + cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); + cx2 = _mm_aesenc_si128(cx2, _mm_set_epi64x(ah2, al2)); + cx3 = _mm_aesenc_si128(cx3, _mm_set_epi64x(ah3, al3)); + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + _mm_store_si128((__m128i*) &l3[idx3 & MASK], _mm_xor_si128(bx3, cx3)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l3[idx3 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l3[idx3 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + idx3 = EXTRACT64(cx3); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + bx3 = cx3; + + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + + + cl = ((uint64_t*) &l3[idx3 & MASK])[0]; + ch = ((uint64_t*) &l3[idx3 & MASK])[1]; + lo = __umul128(idx3, cl, &hi); + + al3 += hi; + ah3 += lo; + + ah3 ^= tweak1_2_3; + ((uint64_t*) &l3[idx3 & MASK])[0] = al3; + ((uint64_t*) &l3[idx3 & MASK])[1] = ah3; + ah3 ^= tweak1_2_3; + + ((uint64_t*)&l3[idx3 & MASK])[1] ^= ((uint64_t*)&l3[idx3 & MASK])[0]; + + ah3 ^= ch; + al3 ^= cl; + idx3 = al3; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + cn_implode_scratchpad((__m128i*) l3, (__m128i*) h3); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + keccakf(h3, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, @@ -2606,6 +3226,246 @@ public: extra_hashes[ctx->state[4][0] & 3](ctx->state[4], 200, output + 128); } + inline static void hashLiteIpbc(const uint8_t* __restrict__ input, + size_t size, + uint8_t* __restrict__ output, + cryptonight_ctx* __restrict__ ctx) + { + keccak((const uint8_t*) input, (int) size, ctx->state[0], 200); + keccak((const uint8_t*) input + size, (int) size, ctx->state[1], 200); + keccak((const uint8_t*) input + 2 * size, (int) size, ctx->state[2], 200); + keccak((const uint8_t*) input + 3 * size, (int) size, ctx->state[3], 200); + keccak((const uint8_t*) input + 4 * size, (int) size, ctx->state[4], 200); + + uint64_t tweak1_2_0 = (*reinterpret_cast(reinterpret_cast(input) + 35) ^ + *(reinterpret_cast(ctx->state[0]) + 24)); + uint64_t tweak1_2_1 = (*reinterpret_cast(reinterpret_cast(input) + 35 + size) ^ + *(reinterpret_cast(ctx->state[1]) + 24)); + uint64_t tweak1_2_2 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 2 * size) ^ + *(reinterpret_cast(ctx->state[2]) + 24)); + uint64_t tweak1_2_3 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 3 * size) ^ + *(reinterpret_cast(ctx->state[3]) + 24)); + uint64_t tweak1_2_4 = (*reinterpret_cast(reinterpret_cast(input) + 35 + 4 * size) ^ + *(reinterpret_cast(ctx->state[4]) + 24)); + + + const uint8_t* l0 = ctx->memory; + const uint8_t* l1 = ctx->memory + MEM; + const uint8_t* l2 = ctx->memory + 2 * MEM; + const uint8_t* l3 = ctx->memory + 3 * MEM; + const uint8_t* l4 = ctx->memory + 4 * MEM; + uint64_t* h0 = reinterpret_cast(ctx->state[0]); + uint64_t* h1 = reinterpret_cast(ctx->state[1]); + uint64_t* h2 = reinterpret_cast(ctx->state[2]); + uint64_t* h3 = reinterpret_cast(ctx->state[3]); + uint64_t* h4 = reinterpret_cast(ctx->state[4]); + + cn_explode_scratchpad((__m128i*) h0, (__m128i*) l0); + cn_explode_scratchpad((__m128i*) h1, (__m128i*) l1); + cn_explode_scratchpad((__m128i*) h2, (__m128i*) l2); + cn_explode_scratchpad((__m128i*) h3, (__m128i*) l3); + cn_explode_scratchpad((__m128i*) h4, (__m128i*) l4); + + uint64_t al0 = h0[0] ^h0[4]; + uint64_t al1 = h1[0] ^h1[4]; + uint64_t al2 = h2[0] ^h2[4]; + uint64_t al3 = h3[0] ^h3[4]; + uint64_t al4 = h4[0] ^h4[4]; + uint64_t ah0 = h0[1] ^h0[5]; + uint64_t ah1 = h1[1] ^h1[5]; + uint64_t ah2 = h2[1] ^h2[5]; + uint64_t ah3 = h3[1] ^h3[5]; + uint64_t ah4 = h4[1] ^h4[5]; + + __m128i bx0 = _mm_set_epi64x(h0[3] ^ h0[7], h0[2] ^ h0[6]); + __m128i bx1 = _mm_set_epi64x(h1[3] ^ h1[7], h1[2] ^ h1[6]); + __m128i bx2 = _mm_set_epi64x(h2[3] ^ h2[7], h2[2] ^ h2[6]); + __m128i bx3 = _mm_set_epi64x(h3[3] ^ h3[7], h3[2] ^ h3[6]); + __m128i bx4 = _mm_set_epi64x(h4[3] ^ h4[7], h4[2] ^ h4[6]); + + uint64_t idx0 = h0[0] ^h0[4]; + uint64_t idx1 = h1[0] ^h1[4]; + uint64_t idx2 = h2[0] ^h2[4]; + uint64_t idx3 = h3[0] ^h3[4]; + uint64_t idx4 = h4[0] ^h4[4]; + + for (size_t i = 0; i < ITERATIONS; i++) { + __m128i cx0; + __m128i cx1; + __m128i cx2; + __m128i cx3; + __m128i cx4; + + if (SOFT_AES) { + cx0 = soft_aesenc((uint32_t*)&l0[idx0 & MASK], _mm_set_epi64x(ah0, al0)); + cx1 = soft_aesenc((uint32_t*)&l1[idx1 & MASK], _mm_set_epi64x(ah1, al1)); + cx2 = soft_aesenc((uint32_t*)&l2[idx2 & MASK], _mm_set_epi64x(ah2, al2)); + cx3 = soft_aesenc((uint32_t*)&l3[idx3 & MASK], _mm_set_epi64x(ah3, al3)); + cx4 = soft_aesenc((uint32_t*)&l4[idx4 & MASK], _mm_set_epi64x(ah4, al4)); + } else { + cx0 = _mm_load_si128((__m128i*) &l0[idx0 & MASK]); + cx1 = _mm_load_si128((__m128i*) &l1[idx1 & MASK]); + cx2 = _mm_load_si128((__m128i*) &l2[idx2 & MASK]); + cx3 = _mm_load_si128((__m128i*) &l3[idx3 & MASK]); + cx4 = _mm_load_si128((__m128i*) &l4[idx4 & MASK]); + + cx0 = _mm_aesenc_si128(cx0, _mm_set_epi64x(ah0, al0)); + cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); + cx2 = _mm_aesenc_si128(cx2, _mm_set_epi64x(ah2, al2)); + cx3 = _mm_aesenc_si128(cx3, _mm_set_epi64x(ah3, al3)); + cx4 = _mm_aesenc_si128(cx4, _mm_set_epi64x(ah4, al4)); + } + + _mm_store_si128((__m128i*) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); + _mm_store_si128((__m128i*) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + _mm_store_si128((__m128i*) &l2[idx2 & MASK], _mm_xor_si128(bx2, cx2)); + _mm_store_si128((__m128i*) &l3[idx3 & MASK], _mm_xor_si128(bx3, cx3)); + _mm_store_si128((__m128i*) &l4[idx4 & MASK], _mm_xor_si128(bx4, cx4)); + + static const uint32_t table = 0x75310; + uint8_t tmp = reinterpret_cast(&l0[idx0 & MASK])[11]; + uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l0[idx0 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l1[idx1 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l1[idx1 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l2[idx2 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l2[idx2 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l3[idx3 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l3[idx3 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + tmp = reinterpret_cast(&l4[idx4 & MASK])[11]; + index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; + ((uint8_t*)(&l4[idx4 & MASK]))[11] = tmp ^ ((table >> index) & 0x30); + + idx0 = EXTRACT64(cx0); + idx1 = EXTRACT64(cx1); + idx2 = EXTRACT64(cx2); + idx3 = EXTRACT64(cx3); + idx4 = EXTRACT64(cx4); + + bx0 = cx0; + bx1 = cx1; + bx2 = cx2; + bx3 = cx3; + bx4 = cx4; + + uint64_t hi, lo, cl, ch; + cl = ((uint64_t*) &l0[idx0 & MASK])[0]; + ch = ((uint64_t*) &l0[idx0 & MASK])[1]; + lo = __umul128(idx0, cl, &hi); + + al0 += hi; + ah0 += lo; + + ah0 ^= tweak1_2_0; + ((uint64_t*) &l0[idx0 & MASK])[0] = al0; + ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + ah0 ^= tweak1_2_0; + + ((uint64_t*)&l0[idx0 & MASK])[1] ^= ((uint64_t*)&l0[idx0 & MASK])[0]; + + ah0 ^= ch; + al0 ^= cl; + idx0 = al0; + + + cl = ((uint64_t*) &l1[idx1 & MASK])[0]; + ch = ((uint64_t*) &l1[idx1 & MASK])[1]; + lo = __umul128(idx1, cl, &hi); + + al1 += hi; + ah1 += lo; + + ah1 ^= tweak1_2_1; + ((uint64_t*) &l1[idx1 & MASK])[0] = al1; + ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + ah1 ^= tweak1_2_1; + + ((uint64_t*)&l1[idx1 & MASK])[1] ^= ((uint64_t*)&l1[idx1 & MASK])[0]; + + ah1 ^= ch; + al1 ^= cl; + idx1 = al1; + + + cl = ((uint64_t*) &l2[idx2 & MASK])[0]; + ch = ((uint64_t*) &l2[idx2 & MASK])[1]; + lo = __umul128(idx2, cl, &hi); + + al2 += hi; + ah2 += lo; + + ah2 ^= tweak1_2_2; + ((uint64_t*) &l2[idx2 & MASK])[0] = al2; + ((uint64_t*) &l2[idx2 & MASK])[1] = ah2; + ah2 ^= tweak1_2_2; + + ((uint64_t*)&l2[idx2 & MASK])[1] ^= ((uint64_t*)&l2[idx2 & MASK])[0]; + + ah2 ^= ch; + al2 ^= cl; + idx2 = al2; + + + cl = ((uint64_t*) &l3[idx3 & MASK])[0]; + ch = ((uint64_t*) &l3[idx3 & MASK])[1]; + lo = __umul128(idx3, cl, &hi); + + al3 += hi; + ah3 += lo; + + ah3 ^= tweak1_2_3; + ((uint64_t*) &l3[idx3 & MASK])[0] = al3; + ((uint64_t*) &l3[idx3 & MASK])[1] = ah3; + ah3 ^= tweak1_2_3; + + ((uint64_t*)&l3[idx3 & MASK])[1] ^= ((uint64_t*)&l3[idx3 & MASK])[0]; + + ah3 ^= ch; + al3 ^= cl; + idx3 = al3; + + + cl = ((uint64_t*) &l4[idx4 & MASK])[0]; + ch = ((uint64_t*) &l4[idx4 & MASK])[1]; + lo = __umul128(idx4, cl, &hi); + + al4 += hi; + ah4 += lo; + + ah4 ^= tweak1_2_4; + ((uint64_t*) &l4[idx4 & MASK])[0] = al4; + ((uint64_t*) &l4[idx4 & MASK])[1] = ah4; + ah4 ^= tweak1_2_4; + + ((uint64_t*)&l4[idx4 & MASK])[1] ^= ((uint64_t*)&l4[idx4 & MASK])[0]; + + ah4 ^= ch; + al4 ^= cl; + idx4 = al4; + } + + cn_implode_scratchpad((__m128i*) l0, (__m128i*) h0); + cn_implode_scratchpad((__m128i*) l1, (__m128i*) h1); + cn_implode_scratchpad((__m128i*) l2, (__m128i*) h2); + cn_implode_scratchpad((__m128i*) l3, (__m128i*) h3); + cn_implode_scratchpad((__m128i*) l4, (__m128i*) h4); + + keccakf(h0, 24); + keccakf(h1, 24); + keccakf(h2, 24); + keccakf(h3, 24); + keccakf(h4, 24); + + extra_hashes[ctx->state[0][0] & 3](ctx->state[0], 200, output); + extra_hashes[ctx->state[1][0] & 3](ctx->state[1], 200, output + 32); + extra_hashes[ctx->state[2][0] & 3](ctx->state[2], 200, output + 64); + extra_hashes[ctx->state[3][0] & 3](ctx->state[3], 200, output + 96); + extra_hashes[ctx->state[4][0] & 3](ctx->state[4], 200, output + 128); + } + inline static void hashHeavy(const uint8_t* __restrict__ input, size_t size, uint8_t* __restrict__ output, diff --git a/src/default_config.json b/src/default_config.json index b7eaf97f..3dc4ae32 100644 --- a/src/default_config.json +++ b/src/default_config.json @@ -1,5 +1,5 @@ { - "algo": "cryptonight", // cryptonight (default), cryptonight-lite or cryptopnight-heavy + "algo": "cryptonight", // cryptonight (default), cryptonight-lite, cryptonight-lite-ipbc or cryptopnight-heavy "av": null, // DEPRECATED: algorithm variation, (0 auto, // 1 -> (aesni=1, multihash-factor=1), // 2 -> (aesni=1, multihash-factor=2), diff --git a/src/net/strategies/DonateStrategy.cpp b/src/net/strategies/DonateStrategy.cpp index a047ae9c..9079c214 100644 --- a/src/net/strategies/DonateStrategy.cpp +++ b/src/net/strategies/DonateStrategy.cpp @@ -58,6 +58,8 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) : #ifndef XMRIG_NO_TLS if (Options::i()->algo() == Options::ALGO_CRYPTONIGHT_HEAVY) { url = new Url("donate2.graef.in", 8443, userId, nullptr, true, false, true); + } else if (Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE_IPBC) { + url = new Url("donate2.graef.in", 1080, userId, nullptr, true, false, true); } else { if (Options::i()->forcePowVersion() == Options::POW_V1) { url = new Url("donate.graef.in", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 8080 : 8081, userId, nullptr, true, false, true); @@ -70,6 +72,8 @@ DonateStrategy::DonateStrategy(const char *agent, IStrategyListener *listener) : #else if (Options::i()->algo() == Options::ALGO_CRYPTONIGHT_HEAVY) { url = new Url("donate.graef.in", 8443, userId, nullptr, false, false, true); + } else if (Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE_IPBC) { + url = new Url("donate.graef.in", 1080, userId, nullptr, false, false, true); } else { if (Options::i()->forcePowVersion() == Options::POW_V1) { url = new Url("donate.graef.in", Options::i()->algo() == Options::ALGO_CRYPTONIGHT_LITE ? 80 : 443, userId, nullptr, false, false, true); @@ -153,7 +157,7 @@ void DonateStrategy::onResultAccepted(Client *client, const SubmitResult &result } -void DonateStrategy::idle(uint64_t timeout) +void DonateStrategy::idle(int64_t timeout) { uv_timer_start(&m_timer, DonateStrategy::onTimer, timeout, 0); } diff --git a/src/net/strategies/DonateStrategy.h b/src/net/strategies/DonateStrategy.h index fa3e06a5..841070c5 100644 --- a/src/net/strategies/DonateStrategy.h +++ b/src/net/strategies/DonateStrategy.h @@ -58,7 +58,7 @@ protected: void onResultAccepted(Client *client, const SubmitResult &result, const char *error) override; private: - void idle(uint64_t timeout); + void idle(int64_t timeout); void suspend(); static void onTimer(uv_timer_t *handle); diff --git a/src/version.h b/src/version.h index 3c6d42c5..e27bd5f2 100644 --- a/src/version.h +++ b/src/version.h @@ -36,14 +36,14 @@ #define APP_DESC "XMRigCC CPU miner" #define APP_COPYRIGHT "Copyright (C) 2017- BenDr0id" #endif -#define APP_VERSION "1.6.0 (based on XMRig 2.5.2)" +#define APP_VERSION "1.6.1-beta1 (based on XMRig 2.5.2)" #define APP_DOMAIN "" #define APP_SITE "https://github.com/Bendr0id/xmrigCC" #define APP_KIND "cpu" #define APP_VER_MAJOR 1 #define APP_VER_MINOR 6 -#define APP_VER_BUILD 0 +#define APP_VER_BUILD 1 #define APP_VER_REV 0 #ifndef NDEBUG