From 5876be361823dea3dc16060e124ac8da27dc1559 Mon Sep 17 00:00:00 2001 From: CoinFu Master Shifu <145641460+CoinFuMasterShifu@users.noreply.github.com> Date: Sun, 23 Jun 2024 21:12:46 +0200 Subject: [PATCH] v0.3.0: miner supports both, verushash v2.1 (block version 2) and v2.2 (for block version 3) --- meson.build | 2 +- src/miner/verusopt/verus_clhash_opt.cpp | 127 ++++++++++++++++-- src/miner/verusopt/verus_clhash_opt.hpp | 4 + src/shared/src/block/header/header.hpp | 1 - src/shared/src/block/header/header_impl.hpp | 4 - src/shared/src/block/header/view.hpp | 1 - src/shared/src/block/header/view_inline.hpp | 11 -- src/shared/src/crypto/verushash/verushash.cpp | 8 +- src/shared/src/crypto/verushash/verushash.hpp | 6 +- 9 files changed, 127 insertions(+), 37 deletions(-) diff --git a/meson.build b/meson.build index 3ef5732..d03fc78 100644 --- a/meson.build +++ b/meson.build @@ -1,5 +1,5 @@ project( 'Warthog Miner (Janushash)', ['c','cpp'], - version : '0.2.9', + version : '0.3.0', default_options : ['warning_level=3', 'cpp_std=c++20']) diff --git a/src/miner/verusopt/verus_clhash_opt.cpp b/src/miner/verusopt/verus_clhash_opt.cpp index 663dab7..f8f93eb 100644 --- a/src/miner/verusopt/verus_clhash_opt.cpp +++ b/src/miner/verusopt/verus_clhash_opt.cpp @@ -864,16 +864,17 @@ __m128i __verusclmulwithoutreduction64alignedrepeat_sv2_1( return acc; } -inline __m128i _mm_load_si128_emu(const void *p) { return *(__m128i *)p; } +inline __m128i _mm_load_si128_emu(const void* p) { return *(__m128i*)p; } -inline __m128i _mm_xor_si128_emu(__m128i a, __m128i b) { +inline __m128i _mm_xor_si128_emu(__m128i a, __m128i b) +{ #ifdef _WIN32 - uint64_t result[2]; - result[0] = *(uint64_t *)&a ^ *(uint64_t *)&b; - result[1] = *((uint64_t *)&a + 1) ^ *((uint64_t *)&b + 1); - return *(__m128i *)result; + uint64_t result[2]; + result[0] = *(uint64_t*)&a ^ *(uint64_t*)&b; + result[1] = *((uint64_t*)&a + 1) ^ *((uint64_t*)&b + 1); + return *(__m128i*)result; #else - return a ^ b; + return a ^ b; #endif } @@ -1145,8 +1146,6 @@ __m128i __verusclmulwithoutreduction64alignedrepeat_sv2_2( return acc; } - - // uint64_t verusclhash_sv2_2(void *random, const unsigned char buf[64], // uint64_t keyMask, __m128i **pMoveScratch) { // __m128i acc = __verusclmulwithoutreduction64alignedrepeat_sv2_2( @@ -1235,10 +1234,114 @@ void JanusMinerOpt::check_set_header(const std::array& newheader) memcpy(hasherrefresh, hashKey, keyRefreshsize); memset(hasherrefresh + keyRefreshsize, 0, keysize - keyRefreshsize); } +[[nodiscard]] inline uint32_t extract_version(const std::array& header) +{ + uint32_t res; + const auto* from { header.begin() + 68 }; + memcpy(&res, from, 4); + res = hton32(res); + return res; +} +inline bool JanusMinerOpt::mine_job(MineResult& res, const CandidateBatch& j, uint32_t threshold) +{ + if (extract_version(j.shared->mined.header()) == 2) + return mine_job_v2_1(res, j, threshold); + return mine_job_v2_2(res, j, threshold); +} -inline bool JanusMinerOpt::mine_job(MineResult& res, const CandidateBatch& job, const uint32_t threshold) +inline bool JanusMinerOpt::mine_job_v2_1(MineResult& res, const CandidateBatch& job, const uint32_t threshold) { + const auto& mined { job.shared->mined }; + check_set_header(mined.header()); + + std::array dummy; + std::fill(dummy.begin(), dummy.end(), 0xFFFFFFFF); + HashView dummySha256tHash(reinterpret_cast(dummy.data())); + + alignas(32) Hash curHash; + + u128* hashKey = (u128*)key; + uint8_t* const hasherrefresh = ((uint8_t*)hashKey) + keysize; + __m128i** const pMoveScratch = (__m128i**)(hasherrefresh + keyRefreshsize); + unsigned char* const curBuf = vh.curBuf; + + uint32_t& nonce = *reinterpret_cast(curBuf + 32 + (76 - 64)); + + size_t offset { job.offset }; + size_t len { job.len }; + + for (auto& span : job.resultSpans.spans) { + const auto jBound { std::min(offset + len, span.size()) }; + for (size_t j = offset; j < jBound; ++j) { + nonce = hton32(span[j].nonce()); + uint32_t hashStart = span[j].hashStart(); + assert(hashStart != 0); + res.total += 1; + if (hashStart > threshold) + continue; + res.processed += 1; + + // prepare the buffer + *(u128*)(curBuf + 32 + 16) = *(u128*)(curBuf); + + // run verusclhash on the buffer + __m128i acc = __verusclmulwithoutreduction64alignedrepeat_sv2_1( + hashKey, (const __m128i*)curBuf, keyMask, pMoveScratch); + acc = _mm_xor_si128(acc, lazyLengthHash(1024, 64)); + const uint64_t intermediate = precompReduction64(acc); + + *(uint64_t*)(curBuf + 32 + 16) = intermediate; + *(uint64_t*)(curBuf + 32 + 16 + 8) = intermediate; + haraka512_keyed_local(curHash.data(), curBuf, + hashKey + (intermediate & keyMask16)); + + // refresh the key + fixupkey(pMoveScratch); + + // + // now exact test + // + dummy[0] = hton32(hashStart); + auto verusFloat { CustomFloat(curHash) }; + *reinterpret_cast(header.data() + 76) = nonce; + // auto sha256tFloat { CustomFloat(hashSHA256(hashSHA256(hashSHA256(header)))) }; + auto sha256tFloat { CustomFloat(dummySha256tHash) }; + + // auto h2 = double(hashStart) / double(0xFFFFFFFF); + // spdlog::info("janushash(header): {} {} {}", sha256tFloat.to_double(), h2, threshold); + // compute janushash + constexpr auto factor { CustomFloat(0, 3006477107) }; + auto janushash { verusFloat * pow(sha256tFloat, factor) }; + if (janushash < job.targetV2) { + std::span s((const uint8_t*)&nonce, 4); + + // spdlog::info("janushash(header): {}< {}", janushash.to_double(), 1 / job.targetV2.difficulty()); + // spdlog::info("header: {}", serialize_hex(header)); + // spdlog::info("sha256thash: {}", serialize_hex(dummySha256tHash)); + auto hs { hashSHA256(hashSHA256(hashSHA256(header))) }; + // spdlog::info("SHA256(header): {}", serialize_hex(hs)); + // spdlog::info("SHA256tFloat: {}", sha256tFloat.to_double()); + CustomFloat hsf { hs }; + // spdlog::info("SHA256tFloat2: {}", hsf.to_double()); + // spdlog::info("verush(header): {}", serialize_hex(verus_hash(header))); + // spdlog::info("verusFloat: {}", verusFloat.to_double()); + // spdlog::info("j {}, {}", j, span[j].nonce()); + assert(curHash == verus_hash(header, false)); + res.success = Verus::Success { curHash, mined.submit(s) }; + return true; + } + } + len -= jBound - offset; + if (offset > span.size()) + offset = 0; + else + offset -= span.size(); + } + return false; +} +inline bool JanusMinerOpt::mine_job_v2_2(MineResult& res, const CandidateBatch& job, const uint32_t threshold) +{ const auto& mined { job.shared->mined }; check_set_header(mined.header()); @@ -1312,10 +1415,10 @@ inline bool JanusMinerOpt::mine_job(MineResult& res, const CandidateBatch& job, // spdlog::info("SHA256tFloat: {}", sha256tFloat.to_double()); CustomFloat hsf { hs }; // spdlog::info("SHA256tFloat2: {}", hsf.to_double()); - // spdlog::info("verush(header): {}", serialize_hex(verus_hash(header))); + // spdlog::info("verush(header): {}", serialize_hex(curHash)); // spdlog::info("verusFloat: {}", verusFloat.to_double()); // spdlog::info("j {}, {}", j, span[j].nonce()); - assert(curHash == verus_hash(header)); + assert(curHash == verus_hash(header, true)); res.success = Verus::Success { curHash, mined.submit(s) }; return true; } diff --git a/src/miner/verusopt/verus_clhash_opt.hpp b/src/miner/verusopt/verus_clhash_opt.hpp index ce67137..2b47659 100644 --- a/src/miner/verusopt/verus_clhash_opt.hpp +++ b/src/miner/verusopt/verus_clhash_opt.hpp @@ -18,6 +18,8 @@ void haraka512_keyed(unsigned char* out, const unsigned char* in, const u128* rc); uint64_t verusclhash_sv2_1(void* random, const unsigned char buf[64], uint64_t keyMask, __m128i** pMoveScratch); +uint64_t verusclhash_sv2_2(void* random, const unsigned char buf[64], + uint64_t keyMask, __m128i** pMoveScratch); namespace Verus { // class MinerOpt { // struct Success { @@ -58,6 +60,8 @@ class JanusMinerOpt { private: bool mine_job(MineResult& res, const CandidateBatch& j, uint32_t threshold); + bool mine_job_v2_2(MineResult& res, const CandidateBatch& j, uint32_t threshold); + bool mine_job_v2_1(MineResult& res, const CandidateBatch& j, uint32_t threshold); void check_set_header(const std::array&); private: diff --git a/src/shared/src/block/header/header.hpp b/src/shared/src/block/header/header.hpp index 38c3ea1..6923aaf 100644 --- a/src/shared/src/block/header/header.hpp +++ b/src/shared/src/block/header/header.hpp @@ -22,7 +22,6 @@ class Header : public std::array { Header& operator=(HeaderView hv) { return *this = Header(hv); } operator HeaderView() const { return HeaderView(data()); } Target target(NonzeroHeight) const; - inline bool validPOW(const Hash&, NonzeroHeight) const; inline HashView prevhash() const; inline HashView merkleroot() const; void set_merkleroot(std::array); diff --git a/src/shared/src/block/header/header_impl.hpp b/src/shared/src/block/header/header_impl.hpp index 4e2e8de..677d7f4 100644 --- a/src/shared/src/block/header/header_impl.hpp +++ b/src/shared/src/block/header/header_impl.hpp @@ -6,10 +6,6 @@ inline Target Header::target(NonzeroHeight h) const { return static_cast(*this).target(h); } -inline bool Header::validPOW(const Hash& h, NonzeroHeight height) const -{ - return static_cast(*this).validPOW(h,height); -} inline HashView Header::prevhash() const { return static_cast(*this).prevhash(); diff --git a/src/shared/src/block/header/view.hpp b/src/shared/src/block/header/view.hpp index bacb272..cea1228 100644 --- a/src/shared/src/block/header/view.hpp +++ b/src/shared/src/block/header/view.hpp @@ -28,7 +28,6 @@ class HeaderView : public View<80> { inline Target target(NonzeroHeight h) const; - bool validPOW(const Hash& h, NonzeroHeight height) const; inline uint32_t version() const; inline HashView prevhash() const; inline HashView merkleroot() const; diff --git a/src/shared/src/block/header/view_inline.hpp b/src/shared/src/block/header/view_inline.hpp index f408781..153d6e8 100644 --- a/src/shared/src/block/header/view_inline.hpp +++ b/src/shared/src/block/header/view_inline.hpp @@ -6,17 +6,6 @@ #include "difficulty.hpp" #include "general/reader.hpp" -inline bool HeaderView::validPOW(const Hash& h, NonzeroHeight height) const -{ - if (JANUSENABLED && height.value() > JANUSRETARGETSTART){ - HashExponentialDigest hd; // prepare hash product of Proof of Balanced work with two algos: verus + 3xsha256 - hd.digest(verus_hash({ data(), size() })); // verus hash v2.1 - hd.digest(hashSHA256(h)); // triple sha - return target_v2().compatible(hd); - } else { - return target_v1().compatible(h); - } -} inline uint32_t HeaderView::version() const { return readuint32(data() + offset_version); diff --git a/src/shared/src/crypto/verushash/verushash.cpp b/src/shared/src/crypto/verushash/verushash.cpp index bc56649..f00d29a 100644 --- a/src/shared/src/crypto/verushash/verushash.cpp +++ b/src/shared/src/crypto/verushash/verushash.cpp @@ -167,7 +167,7 @@ HashKey::HashKey(HashView seed, // spdlog::error("{}", serialize_hex(key,sizeof(key))); } -Hash VerusHasher::finalize() +Hash VerusHasher::finalize(bool use_2_2) { // fill buffer to the end with the beginning of it to prevent any // foreknowledge of bits that may contain zero @@ -175,11 +175,11 @@ Hash VerusHasher::finalize() // gen new key with what is last in buffer - HashKey hk(curBuf, haraka256_port); + HashKey hk(curBuf, haraka256_port); // run verusclhash on the buffer uint64_t intermediate { hk.apply_verusclhash( - curBuf, verusclhash_sv2_2_port) }; + curBuf, use_2_2 ? verusclhash_sv2_2_port : verusclhash_sv2_1_port) }; // fill buffer to the end with the result FillExtra(&intermediate); @@ -188,7 +188,7 @@ Hash VerusHasher::finalize() constexpr uint64_t mask16 = keyMask >> 4; haraka512_port_keyed(out.data(), curBuf, - (const u128*)hk.key_data() + (intermediate & mask16)); + (const u128*)hk.key_data() + (intermediate & mask16)); return out; }; diff --git a/src/shared/src/crypto/verushash/verushash.hpp b/src/shared/src/crypto/verushash/verushash.hpp index 0b1f2de..e4e78d8 100644 --- a/src/shared/src/crypto/verushash/verushash.hpp +++ b/src/shared/src/crypto/verushash/verushash.hpp @@ -25,7 +25,7 @@ class VerusHasher { { return write(s.data(), s.size()); } - [[nodiscard]] Hash finalize(); + [[nodiscard]] Hash finalize(bool use_2_2); private: // data @@ -63,7 +63,7 @@ class VerusHasher { }; } // namespace Verus -[[nodiscard]] inline Hash verus_hash(std::span s) // verushash v2.1 +[[nodiscard]] inline Hash verus_hash(std::span s, bool use_2_2) { - return Verus::VerusHasher().write(s).finalize(); + return Verus::VerusHasher().write(s).finalize(use_2_2); }