From dab4239aca670a844dac383adcd6fc5e2d343ad2 Mon Sep 17 00:00:00 2001 From: XMRig Date: Mon, 11 Jun 2018 12:00:59 +0700 Subject: [PATCH] Added support for cn-heavy/xhv. --- src/common/net/Job.cpp | 12 ++--- src/crypto/CryptoNight_arm.h | 44 +++++++++++++----- src/crypto/CryptoNight_constants.h | 15 ++++++ src/crypto/CryptoNight_monero.h | 8 ++-- src/crypto/CryptoNight_test.h | 15 +++++- src/crypto/CryptoNight_x86.h | 74 ++++++++++++++++++++---------- src/workers/MultiWorker.cpp | 9 ++-- 7 files changed, 128 insertions(+), 49 deletions(-) diff --git a/src/common/net/Job.cpp b/src/common/net/Job.cpp index 9a7ede8e..80b521ea 100644 --- a/src/common/net/Job.cpp +++ b/src/common/net/Job.cpp @@ -165,10 +165,6 @@ bool Job::setTarget(const char *target) xmrig::Variant Job::variant() const { - if (m_algorithm.algo() == xmrig::CRYPTONIGHT_HEAVY) { - return xmrig::VARIANT_0; - } - if (m_algorithm.variant() == xmrig::VARIANT_XTL && m_blob[0] < 4) { return xmrig::VARIANT_1; } @@ -177,8 +173,12 @@ xmrig::Variant Job::variant() const return xmrig::VARIANT_1; } - if (m_algorithm.variant() == xmrig::VARIANT_AUTO && m_algorithm.algo() != xmrig::CRYPTONIGHT_HEAVY) { - return xmrig::VARIANT_1; + if (m_algorithm.variant() == xmrig::VARIANT_XHV && m_blob[0] < 3) { + return xmrig::VARIANT_0; + } + + if (m_algorithm.variant() == xmrig::VARIANT_AUTO) { + return m_algorithm.algo() == xmrig::CRYPTONIGHT_HEAVY ? xmrig::VARIANT_0 : xmrig::VARIANT_1; } return m_algorithm.variant(); diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index fd5bcb7b..46e1f530 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -402,10 +402,11 @@ template inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, cryptonight_ctx **__restrict__ ctx) { constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 32); return; } @@ -436,7 +437,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); } - if (VARIANT > 0) { + if (IS_MONERO) { cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); } else { _mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); @@ -455,7 +456,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; } @@ -478,7 +479,13 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si const int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - idx0 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx0 = (~d) ^ q; + } + else { + idx0 = d ^ q; + } } } @@ -493,10 +500,11 @@ template inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t size, uint8_t *__restrict__ output, struct cryptonight_ctx **__restrict__ ctx) { constexpr size_t MASK = xmrig::cn_select_mask(); - constexpr size_t ITERATIONS = xmrig::cn_select_iter(); + constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 64); return; } @@ -540,7 +548,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); } - if (VARIANT > 0) { + if (IS_MONERO) { cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); } else { @@ -564,7 +572,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; } @@ -587,7 +595,13 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si const int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - idx0 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx0 = (~d) ^ q; + } + else { + idx0 = d ^ q; + } } cl = ((uint64_t*) &l1[idx1 & MASK])[0]; @@ -599,7 +613,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l1[idx1 & MASK])[0] = al1; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1 ^ al1; } @@ -622,7 +636,13 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si const int64_t q = n / (d | 0x5); ((int64_t*)&l1[idx1 & MASK])[0] = n ^ q; - idx1 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx1 = (~d) ^ q; + } + else { + idx1 = d ^ q; + } } } diff --git a/src/crypto/CryptoNight_constants.h b/src/crypto/CryptoNight_constants.h index 73f3e958..85a2ab85 100644 --- a/src/crypto/CryptoNight_constants.h +++ b/src/crypto/CryptoNight_constants.h @@ -136,6 +136,21 @@ inline uint32_t cn_select_iter(Algo algorithm, Variant variant) } +template inline constexpr bool cn_is_monero() { return false; } +template<> inline constexpr bool cn_is_monero() { return false; } +template<> inline constexpr bool cn_is_monero() { return true; } +template<> inline constexpr bool cn_is_monero() { return true; } +template<> inline constexpr bool cn_is_monero() { return true; } +template<> inline constexpr bool cn_is_monero() { return true; } +template<> inline constexpr bool cn_is_monero() { return false; } + + +inline bool cn_is_monero(Variant variant) +{ + return variant > VARIANT_0 && variant < VARIANT_XHV; +} + + } /* namespace xmrig */ diff --git a/src/crypto/CryptoNight_monero.h b/src/crypto/CryptoNight_monero.h index 28572d88..a758fdbc 100644 --- a/src/crypto/CryptoNight_monero.h +++ b/src/crypto/CryptoNight_monero.h @@ -30,21 +30,21 @@ #ifndef XMRIG_ARM # define VARIANT1_INIT(part) \ uint64_t tweak1_2_##part = 0; \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ tweak1_2_##part = (*reinterpret_cast(input + 35 + part * size) ^ \ *(reinterpret_cast(ctx[part]->state) + 24)); \ } #else # define VARIANT1_INIT(part) \ uint64_t tweak1_2_##part = 0; \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ memcpy(&tweak1_2_##part, input + 35 + part * size, sizeof tweak1_2_##part); \ tweak1_2_##part ^= *(reinterpret_cast(ctx[part]->state) + 24); \ } #endif #define VARIANT1_1(p) \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ const uint8_t tmp = reinterpret_cast(p)[11]; \ static const uint32_t table = 0x75310; \ const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ @@ -52,7 +52,7 @@ } #define VARIANT1_2(p, part) \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ (p) ^= tweak1_2_##part; \ } diff --git a/src/crypto/CryptoNight_test.h b/src/crypto/CryptoNight_test.h index 8d8fe455..187ba07a 100644 --- a/src/crypto/CryptoNight_test.h +++ b/src/crypto/CryptoNight_test.h @@ -161,7 +161,7 @@ const static uint8_t test_output_ipbc_lite[160] = { #ifndef XMRIG_NO_SUMO -const static uint8_t test_output_heavy[160] = { +const static uint8_t test_output_v0_heavy[160] = { 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, @@ -173,6 +173,19 @@ const static uint8_t test_output_heavy[160] = { 0x53, 0x62, 0x0A, 0x54, 0x7D, 0x43, 0xEA, 0x18, 0x94, 0xED, 0xD8, 0x92, 0x06, 0x6A, 0xA1, 0x51, 0xAD, 0xB1, 0xFD, 0x89, 0xFB, 0x5C, 0xB4, 0x25, 0x6A, 0xDD, 0xB0, 0x09, 0xC5, 0x72, 0x87, 0xEB }; + +const static uint8_t test_output_xhv_heavy[160] = { + 0x5A, 0xC3, 0xF7, 0x85, 0xC4, 0x90, 0xC5, 0x85, 0x50, 0xEC, 0x95, 0xD2, 0x72, 0x65, 0x63, 0x57, + 0x7E, 0x7C, 0x1C, 0x21, 0x2D, 0x0C, 0xDE, 0x59, 0x12, 0x73, 0x20, 0x1E, 0x44, 0xFD, 0xD5, 0xB6, + 0x1F, 0x4E, 0xB2, 0x0A, 0x36, 0x51, 0x4B, 0xF5, 0x4D, 0xC9, 0xE0, 0x90, 0x2C, 0x16, 0x47, 0x3F, + 0xDE, 0x18, 0x29, 0x8E, 0xBB, 0x34, 0x2B, 0xEF, 0x7A, 0x04, 0x22, 0xD1, 0xB1, 0xF2, 0x48, 0xDA, + 0xE3, 0x7F, 0x4B, 0x4C, 0xB4, 0xDF, 0xE8, 0xD3, 0x70, 0xE2, 0xE7, 0x44, 0x25, 0x87, 0x12, 0xF9, + 0x8F, 0x28, 0x0B, 0xCE, 0x2C, 0xEE, 0xDD, 0x88, 0x94, 0x35, 0x48, 0x51, 0xAE, 0xC8, 0x9C, 0x0B, + 0xED, 0x2F, 0xE6, 0x0F, 0x39, 0x05, 0xB4, 0x4A, 0x8F, 0x38, 0x44, 0x2D, 0x4B, 0xE9, 0x7B, 0x81, + 0xC6, 0xB0, 0xE0, 0x0A, 0x39, 0x8C, 0x38, 0xFE, 0x63, 0x31, 0x47, 0x65, 0x0D, 0x2B, 0xF4, 0x96, + 0x13, 0x91, 0x89, 0xB4, 0x5B, 0xA9, 0x2A, 0x7A, 0x09, 0x65, 0x14, 0x20, 0x76, 0x24, 0x6C, 0x80, + 0x1D, 0x3F, 0x9F, 0xCD, 0x68, 0x39, 0xA9, 0x42, 0x27, 0xC1, 0x0C, 0x53, 0x98, 0x35, 0x60, 0x7A +}; #endif diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 3aa2a927..8ab65023 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -409,8 +409,9 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si constexpr size_t MASK = xmrig::cn_select_mask(); constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 32); return; } @@ -441,7 +442,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); } - if (VARIANT > 0) { + if (IS_MONERO) { cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); } else { _mm_store_si128((__m128i *)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); @@ -460,7 +461,7 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; } @@ -477,12 +478,18 @@ inline void cryptonight_single_hash(const uint8_t *__restrict__ input, size_t si idx0 = al0; if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { - int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; - int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - idx0 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx0 = (~d) ^ q; + } + else { + idx0 = d ^ q; + } } } @@ -499,8 +506,9 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si constexpr size_t MASK = xmrig::cn_select_mask(); constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 64); return; } @@ -544,7 +552,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si cx1 = _mm_aesenc_si128(cx1, _mm_set_epi64x(ah1, al1)); } - if (VARIANT > 0) { + if (IS_MONERO) { cryptonight_monero_tweak((uint64_t*)&l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); cryptonight_monero_tweak((uint64_t*)&l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); } else { @@ -568,7 +576,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l0[idx0 & MASK])[0] = al0; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l0[idx0 & MASK])[1] = ah0 ^ tweak1_2_0 ^ al0; } @@ -585,12 +593,18 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si idx0 = al0; if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { - int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; - int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; + int64_t n = ((int64_t*)&l0[idx0 & MASK])[0]; + int32_t d = ((int32_t*)&l0[idx0 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l0[idx0 & MASK])[0] = n ^ q; - idx0 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx0 = (~d) ^ q; + } + else { + idx0 = d ^ q; + } } cl = ((uint64_t*) &l1[idx1 & MASK])[0]; @@ -602,7 +616,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si ((uint64_t*)&l1[idx1 & MASK])[0] = al1; - if (VARIANT > 0) { + if (IS_MONERO) { if (VARIANT == xmrig::VARIANT_IPBC) { ((uint64_t*)&l1[idx1 & MASK])[1] = ah1 ^ tweak1_2_1 ^ al1; } @@ -619,12 +633,18 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si idx1 = al1; if (ALGO == xmrig::CRYPTONIGHT_HEAVY) { - int64_t n = ((int64_t*)&l1[idx1 & MASK])[0]; - int32_t d = ((int32_t*)&l1[idx1 & MASK])[2]; + int64_t n = ((int64_t*)&l1[idx1 & MASK])[0]; + int32_t d = ((int32_t*)&l1[idx1 & MASK])[2]; int64_t q = n / (d | 0x5); ((int64_t*)&l1[idx1 & MASK])[0] = n ^ q; - idx1 = d ^ q; + + if (VARIANT == xmrig::VARIANT_XHV) { + idx1 = (~d) ^ q; + } + else { + idx1 = d ^ q; + } } } @@ -653,7 +673,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si \ b = _mm_xor_si128(b, c); \ \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ cryptonight_monero_tweak(reinterpret_cast(ptr), b); \ } else { \ _mm_store_si128(ptr, b); \ @@ -670,7 +690,7 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si lo = __umul128(idx, EXTRACT64(b), &hi); \ a = _mm_add_epi64(a, _mm_set_epi64x(lo, hi)); \ \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ _mm_store_si128(ptr, _mm_xor_si128(a, mc)); \ \ if (VARIANT == xmrig::VARIANT_IPBC) { \ @@ -688,13 +708,18 @@ inline void cryptonight_double_hash(const uint8_t *__restrict__ input, size_t si int32_t d = ((int32_t*)&l[idx & MASK])[2]; \ int64_t q = n / (d | 0x5); \ ((int64_t*)&l[idx & MASK])[0] = n ^ q; \ - idx = d ^ q; \ + if (VARIANT == xmrig::VARIANT_XHV) { \ + idx = (~d) ^ q; \ + } \ + else { \ + idx = d ^ q; \ + } \ } #define CONST_INIT(ctx, n) \ __m128i mc##n; \ - if (VARIANT > 0) { \ + if (IS_MONERO) { \ mc##n = _mm_set_epi64x(*reinterpret_cast(input + n * size + 35) ^ \ *(reinterpret_cast((ctx)->state) + 24), 0); \ } @@ -706,8 +731,9 @@ inline void cryptonight_triple_hash(const uint8_t *__restrict__ input, size_t si constexpr size_t MASK = xmrig::cn_select_mask(); constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 32 * 3); return; } @@ -796,8 +822,9 @@ inline void cryptonight_quad_hash(const uint8_t *__restrict__ input, size_t size constexpr size_t MASK = xmrig::cn_select_mask(); constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 32 * 4); return; } @@ -902,8 +929,9 @@ inline void cryptonight_penta_hash(const uint8_t *__restrict__ input, size_t siz constexpr size_t MASK = xmrig::cn_select_mask(); constexpr size_t ITERATIONS = xmrig::cn_select_iter(); constexpr size_t MEM = xmrig::cn_select_memory(); + constexpr bool IS_MONERO = xmrig::cn_is_monero(); - if (VARIANT > 0 && size < 43) { + if (IS_MONERO && size < 43) { memset(output, 0, 32 * 5); return; } diff --git a/src/workers/MultiWorker.cpp b/src/workers/MultiWorker.cpp index f3acf7f8..73f0dba7 100644 --- a/src/workers/MultiWorker.cpp +++ b/src/workers/MultiWorker.cpp @@ -66,10 +66,13 @@ bool MultiWorker::selfTest() # endif # ifndef XMRIG_NO_SUMO - return m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY && verify(xmrig::VARIANT_0, test_output_heavy); -# else - return false; + if (m_thread->algorithm() == xmrig::CRYPTONIGHT_HEAVY) { + return verify(xmrig::VARIANT_0, test_output_v0_heavy) && + verify(xmrig::VARIANT_XHV, test_output_xhv_heavy); + } # endif + + return false; }