From 48b1de0b59bc2969fd9a2b951773488b9501ae4e Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Fri, 2 Mar 2018 22:10:46 -0500 Subject: [PATCH] Changes for the Monero v1 PoW --- src/crypto/CryptoNight.cpp | 102 +++++++++++++++++++++++------------ src/crypto/CryptoNight.h | 4 +- src/crypto/CryptoNight_arm.h | 26 +++++++-- src/crypto/CryptoNight_x86.h | 26 +++++++-- src/workers/DoubleWorker.cpp | 18 ++++--- src/workers/SingleWorker.cpp | 4 +- 6 files changed, 128 insertions(+), 52 deletions(-) diff --git a/src/crypto/CryptoNight.cpp b/src/crypto/CryptoNight.cpp index 3ac9e94bb..ecc051f2c 100644 --- a/src/crypto/CryptoNight.cpp +++ b/src/crypto/CryptoNight.cpp @@ -24,6 +24,34 @@ #include "crypto/CryptoNight.h" +// VARIANT ALTERATIONS +#define VARIANT1_CHECK() \ + if (MONERO && version > 6 && size < 43) \ + { \ + return false; \ + } + +#define VARIANT1_INIT(part) \ + const uint64_t tweak1_2_##part =\ + (MONERO && version > 6) ? \ + (*reinterpret_cast(reinterpret_cast(input) + 35 + part * size) ^ \ + *(reinterpret_cast(ctx->state##part) + 24)) : 0; + +#define VARIANT1_1(p) \ + do if(version > 6) \ + { \ + const uint8_t tmp = reinterpret_cast(p)[11]; \ + static const uint32_t table = 0x75310; \ + const uint8_t index = (((tmp >> 3) & 6) | (tmp & 1)) << 1; \ + ((uint8_t*)(p))[11] = tmp ^ ((table >> index) & 0x30); \ + } while(0) + +#define VARIANT1_2(p, part) \ + do if(MONERO && version > 6) { \ + (p) ^= tweak1_2_##part ; \ + } while(0) + + #if defined(XMRIG_ARM) # include "crypto/CryptoNight_arm.h" #else @@ -36,58 +64,67 @@ #include "Options.h" -void (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = nullptr; + +bool (*cryptonight_hash_ctx)(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t) = nullptr; -static void cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx) { +static bool cryptonight_av1_aesni(const void *input, size_t size, void *output, struct cryptonight_ctx *ctx, uint8_t version) { # if !defined(XMRIG_ARMv7) - cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); + return cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, false, true>(input, size, output, ctx, version); +# else + return false; # endif } -static void cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +static bool cryptonight_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { # if !defined(XMRIG_ARMv7) - cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false>(input, size, output, ctx); + return cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, false, true>(input, size, output, ctx, version); +# else + return false; # endif } -static void cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); +static bool cryptonight_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { + return cryptonight_hash<0x80000, MEMORY, 0x1FFFF0, true, true>(input, size, output, ctx, version); } -static void cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true>(input, size, output, ctx); +static bool cryptonight_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { + return cryptonight_double_hash<0x80000, MEMORY, 0x1FFFF0, true, true>(input, size, output, ctx, version); } #ifndef XMRIG_NO_AEON -static void cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - # if !defined(XMRIG_ARMv7) - cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); -#endif -} - - -static void cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { +static bool cryptonight_lite_av1_aesni(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { # if !defined(XMRIG_ARMv7) - cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false>(input, size, output, ctx); + return cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, false, false>(input, size, output, ctx, version); +# else + return false; # endif } -static void cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); +static bool cryptonight_lite_av2_aesni_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { +# if !defined(XMRIG_ARMv7) + return cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, false, false>(input, size, output, ctx, version); +# else + return false; +# endif } -static void cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx) { - cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true>(input, size, output, ctx); +static bool cryptonight_lite_av3_softaes(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { + return cryptonight_hash<0x40000, MEMORY_LITE, 0xFFFF0, true, false>(input, size, output, ctx, version); } -void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = { + +static bool cryptonight_lite_av4_softaes_double(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t version) { + return cryptonight_double_hash<0x40000, MEMORY_LITE, 0xFFFF0, true, false>(input, size, output, ctx, version); +} + +bool (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t) = { cryptonight_av1_aesni, cryptonight_av2_aesni_double, cryptonight_av3_softaes, @@ -98,7 +135,7 @@ void (*cryptonight_variations[8])(const void *input, size_t size, void *output, cryptonight_lite_av4_softaes_double }; #else -void (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx) = { +bool (*cryptonight_variations[4])(const void *input, size_t size, void *output, cryptonight_ctx *ctx, uint8_t) = { cryptonight_av1_aesni, cryptonight_av2_aesni_double, cryptonight_av3_softaes, @@ -107,11 +144,10 @@ void (*cryptonight_variations[4])(const void *input, size_t size, void *output, #endif -bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx) +bool CryptoNight::hash(const Job &job, JobResult &result, cryptonight_ctx *ctx, uint8_t version) { - cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx); - - return *reinterpret_cast(result.result + 24) < job.target(); + const bool rc = cryptonight_hash_ctx(job.blob(), job.size(), result.result, ctx, version); + return rc && *reinterpret_cast(result.result + 24) < job.target(); } @@ -133,9 +169,9 @@ bool CryptoNight::init(int algo, int variant) } -void CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx) +bool CryptoNight::hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, uint8_t version) { - cryptonight_hash_ctx(input, size, output, ctx); + return cryptonight_hash_ctx(input, size, output, ctx, version); } @@ -149,14 +185,14 @@ bool CryptoNight::selfTest(int algo) { struct cryptonight_ctx *ctx = (struct cryptonight_ctx*) _mm_malloc(sizeof(struct cryptonight_ctx), 16); ctx->memory = (uint8_t *) _mm_malloc(MEMORY * 2, 16); - cryptonight_hash_ctx(test_input, 76, output, ctx); + const bool rc = cryptonight_hash_ctx(test_input, 76, output, ctx, 0); _mm_free(ctx->memory); _mm_free(ctx); # ifndef XMRIG_NO_AEON - return memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; + return rc && memcmp(output, algo == Options::ALGO_CRYPTONIGHT_LITE ? test_output1 : test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; # else - return memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; + return rc && memcmp(output, test_output0, (Options::i()->doubleHash() ? 64 : 32)) == 0; # endif } diff --git a/src/crypto/CryptoNight.h b/src/crypto/CryptoNight.h index 64fc0fd1a..890e6263f 100644 --- a/src/crypto/CryptoNight.h +++ b/src/crypto/CryptoNight.h @@ -50,9 +50,9 @@ class JobResult; class CryptoNight { public: - static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx); + static bool hash(const Job &job, JobResult &result, cryptonight_ctx *ctx, uint8_t version); static bool init(int algo, int variant); - static void hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx); + static bool hash(const uint8_t *input, size_t size, uint8_t *output, cryptonight_ctx *ctx, uint8_t version); private: static bool selfTest(int algo); diff --git a/src/crypto/CryptoNight_arm.h b/src/crypto/CryptoNight_arm.h index 4ac14f34d..513fa8843 100644 --- a/src/crypto/CryptoNight_arm.h +++ b/src/crypto/CryptoNight_arm.h @@ -344,11 +344,14 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) } -template -inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx) +template +inline bool cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx, uint8_t version) { keccak(static_cast(input), (int) size, ctx->state0, 200); + VARIANT1_CHECK(); + VARIANT1_INIT(0); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); const uint8_t* l0 = ctx->memory; @@ -374,6 +377,7 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * } _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + VARIANT1_1(&l0[idx0 & MASK]); idx0 = EXTRACT64(cx); bx0 = cx; @@ -385,8 +389,10 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * al0 += hi; ah0 += lo; + VARIANT1_2(ah0, 0); ((uint64_t*)&l0[idx0 & MASK])[0] = al0; ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; + VARIANT1_2(ah0, 0); ah0 ^= ch; al0 ^= cl; @@ -397,15 +403,20 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * keccakf(h0, 24); extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + return true; } -template -inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +template +inline bool cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx, uint8_t version) { keccak((const uint8_t *) input, (int) size, ctx->state0, 200); keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200); + VARIANT1_CHECK(); + VARIANT1_INIT(0); + VARIANT1_INIT(1); + const uint8_t* l0 = ctx->memory; const uint8_t* l1 = ctx->memory + MEM; uint64_t* h0 = reinterpret_cast(ctx->state0); @@ -443,6 +454,8 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + VARIANT1_1(&l0[idx0 & MASK]); + VARIANT1_1(&l1[idx1 & MASK]); idx0 = EXTRACT64(cx0); idx1 = EXTRACT64(cx1); @@ -458,8 +471,10 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, al0 += hi; ah0 += lo; + VARIANT1_2(ah0, 0); ((uint64_t*) &l0[idx0 & MASK])[0] = al0; ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + VARIANT1_2(ah0, 0); ah0 ^= ch; al0 ^= cl; @@ -472,8 +487,10 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, al1 += hi; ah1 += lo; + VARIANT1_2(ah1, 1); ((uint64_t*) &l1[idx1 & MASK])[0] = al1; ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + VARIANT1_2(ah1, 1); ah1 ^= ch; al1 ^= cl; @@ -488,6 +505,7 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); + return true; } #endif /* __CRYPTONIGHT_ARM_H__ */ diff --git a/src/crypto/CryptoNight_x86.h b/src/crypto/CryptoNight_x86.h index 927aab723..a9500850d 100644 --- a/src/crypto/CryptoNight_x86.h +++ b/src/crypto/CryptoNight_x86.h @@ -307,11 +307,14 @@ static inline void cn_implode_scratchpad(const __m128i *input, __m128i *output) } -template -inline void cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx) +template +inline bool cryptonight_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, cryptonight_ctx *__restrict__ ctx, uint8_t version) { keccak(static_cast(input), (int) size, ctx->state0, 200); + VARIANT1_CHECK(); + VARIANT1_INIT(0); + cn_explode_scratchpad((__m128i*) ctx->state0, (__m128i*) ctx->memory); const uint8_t* l0 = ctx->memory; @@ -334,6 +337,7 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * cx = _mm_aesenc_si128(cx, _mm_set_epi64x(ah0, al0)); } _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx)); + VARIANT1_1(&l0[idx0 & MASK]); idx0 = EXTRACT64(cx); bx0 = cx; @@ -345,8 +349,10 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * al0 += hi; ah0 += lo; + VARIANT1_2(ah0, 0); ((uint64_t*)&l0[idx0 & MASK])[0] = al0; ((uint64_t*)&l0[idx0 & MASK])[1] = ah0; + VARIANT1_2(ah0, 0); ah0 ^= ch; al0 ^= cl; @@ -357,15 +363,20 @@ inline void cryptonight_hash(const void *__restrict__ input, size_t size, void * keccakf(h0, 24); extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); + return true; } -template -inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx) +template +inline bool cryptonight_double_hash(const void *__restrict__ input, size_t size, void *__restrict__ output, struct cryptonight_ctx *__restrict__ ctx, uint8_t version) { keccak((const uint8_t *) input, (int) size, ctx->state0, 200); keccak((const uint8_t *) input + size, (int) size, ctx->state1, 200); + VARIANT1_CHECK(); + VARIANT1_INIT(0); + VARIANT1_INIT(1); + const uint8_t* l0 = ctx->memory; const uint8_t* l1 = ctx->memory + MEM; uint64_t* h0 = reinterpret_cast(ctx->state0); @@ -401,6 +412,8 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, _mm_store_si128((__m128i *) &l0[idx0 & MASK], _mm_xor_si128(bx0, cx0)); _mm_store_si128((__m128i *) &l1[idx1 & MASK], _mm_xor_si128(bx1, cx1)); + VARIANT1_1(&l0[idx0 & MASK]); + VARIANT1_1(&l1[idx1 & MASK]); idx0 = EXTRACT64(cx0); idx1 = EXTRACT64(cx1); @@ -416,8 +429,10 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, al0 += hi; ah0 += lo; + VARIANT1_2(ah0, 0); ((uint64_t*) &l0[idx0 & MASK])[0] = al0; ((uint64_t*) &l0[idx0 & MASK])[1] = ah0; + VARIANT1_2(ah0, 0); ah0 ^= ch; al0 ^= cl; @@ -430,8 +445,10 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, al1 += hi; ah1 += lo; + VARIANT1_2(ah1, 1); ((uint64_t*) &l1[idx1 & MASK])[0] = al1; ((uint64_t*) &l1[idx1 & MASK])[1] = ah1; + VARIANT1_2(ah1, 1); ah1 ^= ch; al1 ^= cl; @@ -446,6 +463,7 @@ inline void cryptonight_double_hash(const void *__restrict__ input, size_t size, extra_hashes[ctx->state0[0] & 3](ctx->state0, 200, static_cast(output)); extra_hashes[ctx->state1[0] & 3](ctx->state1, 200, static_cast(output) + 32); + return true; } #endif /* __CRYPTONIGHT_X86_H__ */ diff --git a/src/workers/DoubleWorker.cpp b/src/workers/DoubleWorker.cpp index 46d6f3663..8c49649ce 100644 --- a/src/workers/DoubleWorker.cpp +++ b/src/workers/DoubleWorker.cpp @@ -76,6 +76,8 @@ void DoubleWorker::start() consumeJob(); } + const uint8_t version = m_state->job.size() ? m_state->job.blob()[0] : 0; + while (!Workers::isOutdated(m_sequence)) { if ((m_count & 0xF) == 0) { storeStats(); @@ -85,15 +87,15 @@ void DoubleWorker::start() *Job::nonce(m_state->blob) = ++m_state->nonce1; *Job::nonce(m_state->blob + m_state->job.size()) = ++m_state->nonce2; - CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx); + if (CryptoNight::hash(m_state->blob, m_state->job.size(), m_hash, m_ctx, version)) { + if (*reinterpret_cast(m_hash + 24) < m_state->job.target()) { + Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff())); + } - if (*reinterpret_cast(m_hash + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce1, m_hash, m_state->job.diff())); - } - - if (*reinterpret_cast(m_hash + 32 + 24) < m_state->job.target()) { - Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff())); - } + if (*reinterpret_cast(m_hash + 32 + 24) < m_state->job.target()) { + Workers::submit(JobResult(m_state->job.poolId(), m_state->job.id(), m_state->nonce2, m_hash + 32, m_state->job.diff())); + } + } // print on error ? std::this_thread::yield(); } diff --git a/src/workers/SingleWorker.cpp b/src/workers/SingleWorker.cpp index ecb566f89..3a2cc32c6 100644 --- a/src/workers/SingleWorker.cpp +++ b/src/workers/SingleWorker.cpp @@ -52,6 +52,8 @@ void SingleWorker::start() consumeJob(); } + const uint8_t version = m_job.size() ? m_job.blob()[0] : 0; + while (!Workers::isOutdated(m_sequence)) { if ((m_count & 0xF) == 0) { storeStats(); @@ -60,7 +62,7 @@ void SingleWorker::start() m_count++; *m_job.nonce() = ++m_result.nonce; - if (CryptoNight::hash(m_job, m_result, m_ctx)) { + if (CryptoNight::hash(m_job, m_result, m_ctx, version)) { Workers::submit(m_result); }